commit 8ff89c09c4856a91cb2787af97c214bbaefe1cc7 Author: Erinn Clark erinn@torproject.org Date: Wed Oct 24 16:32:39 2012 +0100
add stable firefox patches for alpha bundles --- ...nents.interfaces-lookupMethod-from-conten.patch | 50 ++ ...0002-Make-Permissions-Manager-memory-only.patch | 94 ++++ ...-Make-Intermediate-Cert-Store-memory-only.patch | 43 ++ .../firefox/0004-Add-a-string-based-cacheKey.patch | 85 +++ .../0005-Block-all-plugins-except-flash.patch | 85 +++ ...ontent-pref-service-memory-only-clearable.patch | 37 ++ ...owser-exit-when-not-launched-from-Vidalia.patch | 46 ++ .../0008-Disable-SSL-Session-ID-tracking.patch | 28 + ...observer-event-to-close-persistent-connec.patch | 40 ++ ...ice-and-system-specific-CSS-Media-Queries.patch | 154 ++++++ ...11-Limit-the-number-of-fonts-per-document.patch | 228 ++++++++ .../0012-Rebrand-Firefox-to-TorBrowser.patch | 50 ++ .../0013-Make-Download-manager-memory-only.patch | 57 ++ .../0014-Add-DDG-and-StartPage-to-Omnibox.patch | 84 +++ ...-nsICacheService.EvictEntries-synchronous.patch | 44 ++ .../firefox/0016-Prevent-WebSocket-DNS-leak.patch | 132 +++++ ...ize-HTTP-request-order-and-pipeline-depth.patch | 251 +++++++++ ...th-headers-before-the-modify-request-obse.patch | 52 ++ ...Adapt-Steven-Michaud-s-Mac-crashfix-patch.patch | 532 +++++++++++++++++++ ...d-mozIThirdPartyUtil.getFirstPartyURI-API.patch | 31 +- .../0021-Add-canvas-image-extraction-prompt.patch | 551 ++++++++++++++++++++ ...nt-window-coordinates-for-mouse-event-scr.patch | 43 ++ ...se-physical-screen-info.-via-window-and-w.patch | 312 +++++++++++ ...not-expose-system-colors-to-CSS-or-canvas.patch | 537 +++++++++++++++++++ 24 files changed, 3554 insertions(+), 12 deletions(-)
diff --git a/src/current-patches/firefox/0001-Block-Components.interfaces-lookupMethod-from-conten.patch b/src/current-patches/firefox/0001-Block-Components.interfaces-lookupMethod-from-conten.patch new file mode 100644 index 0000000..1a82800 --- /dev/null +++ b/src/current-patches/firefox/0001-Block-Components.interfaces-lookupMethod-from-conten.patch @@ -0,0 +1,50 @@ +From 1c2ccbea73720db5405602e4033c69b706068a8b Mon Sep 17 00:00:00 2001 +From: Mike Perry mikeperry-git@torproject.org +Date: Wed, 1 Feb 2012 15:40:40 -0800 +Subject: [PATCH 01/24] Block Components.interfaces,lookupMethod from content + +This patch removes the ability of content script to access +Components.interfaces.* as well as call or access Components.lookupMethod. + +These two interfaces seem to be exposed to content script only to make our +lives difficult. Components.lookupMethod can undo our JS hooks, and +Components.interfaces is useful for fingerprinting the platform, OS, and +Firebox version. + +They appear to have no other legitimate use. See also: +https://bugzilla.mozilla.org/show_bug.cgi?id=429070 +https://trac.torproject.org/projects/tor/ticket/2873 +https://trac.torproject.org/projects/tor/ticket/2874 +--- + js/xpconnect/src/XPCComponents.cpp | 8 ++++++-- + 1 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp +index 38bfe08..7224b9b 100644 +--- a/js/xpconnect/src/XPCComponents.cpp ++++ b/js/xpconnect/src/XPCComponents.cpp +@@ -4502,7 +4502,9 @@ nsXPCComponents::CanCreateWrapper(const nsIID * iid, char **_retval) + NS_IMETHODIMP + nsXPCComponents::CanCallMethod(const nsIID * iid, const PRUnichar *methodName, char **_retval) + { +- static const char* allowed[] = { "isSuccessCode", "lookupMethod", nsnull }; ++ // XXX: Pref observer? Also, is this what we want? Seems like a plan ++ //static const char* allowed[] = { "isSuccessCode", "lookupMethod", nsnull }; ++ static const char* allowed[] = { "isSuccessCode", nsnull }; + *_retval = xpc_CheckAccessList(methodName, allowed); + return NS_OK; + } +@@ -4511,7 +4513,9 @@ nsXPCComponents::CanCallMethod(const nsIID * iid, const PRUnichar *methodName, c + NS_IMETHODIMP + nsXPCComponents::CanGetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval) + { +- static const char* allowed[] = { "interfaces", "interfacesByID", "results", nsnull}; ++ // XXX: Pref observer? Also, is this what we want? Seems like a plan ++ // static const char* allowed[] = { "interfaces", "interfacesByID", "results", nsnull}; ++ static const char* allowed[] = { "results", nsnull}; + *_retval = xpc_CheckAccessList(propertyName, allowed); + return NS_OK; + } +-- +1.7.5.4 + diff --git a/src/current-patches/firefox/0002-Make-Permissions-Manager-memory-only.patch b/src/current-patches/firefox/0002-Make-Permissions-Manager-memory-only.patch new file mode 100644 index 0000000..fa23d93 --- /dev/null +++ b/src/current-patches/firefox/0002-Make-Permissions-Manager-memory-only.patch @@ -0,0 +1,94 @@ +From cd983b1b57b1f4ae10c8deec5aa12ec957fdc855 Mon Sep 17 00:00:00 2001 +From: Mike Perry mikeperry-git@torproject.org +Date: Wed, 1 Feb 2012 15:45:16 -0800 +Subject: [PATCH 02/24] Make Permissions Manager memory-only + +This patch exposes a pref 'permissions.memory_only' that properly isolates the +permissions manager to memory, which is responsible for all user specified +site permissions, as well as stored STS policy. + +The pref does successfully clear the permissions manager memory if toggled. It +does not need to be set in prefs.js, and can be handled by Torbutton. + +https://trac.torproject.org/projects/tor/ticket/2950 +--- + extensions/cookie/nsPermissionManager.cpp | 34 ++++++++++++++++++++++++++-- + 1 files changed, 31 insertions(+), 3 deletions(-) + +diff --git a/extensions/cookie/nsPermissionManager.cpp b/extensions/cookie/nsPermissionManager.cpp +index 67eb216..12cc7cf 100644 +--- a/extensions/cookie/nsPermissionManager.cpp ++++ b/extensions/cookie/nsPermissionManager.cpp +@@ -58,6 +58,10 @@ + #include "mozStorageHelper.h" + #include "mozStorageCID.h" + #include "nsXULAppAPI.h" ++#include "nsCOMPtr.h" ++#include "nsIPrefService.h" ++#include "nsIPrefBranch.h" ++#include "nsIPrefBranch2.h" + + static nsPermissionManager *gPermissionManager = nsnull; + +@@ -203,6 +207,11 @@ nsPermissionManager::Init() + mObserverService->AddObserver(this, "profile-do-change", true); + } + ++ nsCOMPtr<nsIPrefBranch2> pbi = do_GetService(NS_PREFSERVICE_CONTRACTID); ++ if (pbi) { ++ pbi->AddObserver("permissions.", this, PR_FALSE); ++ } ++ + if (IsChildProcess()) { + // Get the permissions from the parent process + InfallibleTArrayIPC::Permission perms; +@@ -251,8 +260,18 @@ nsPermissionManager::InitDB(bool aRemoveFile) + if (!storage) + return NS_ERROR_UNEXPECTED; + ++ bool memory_db = false; ++ nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); ++ if (prefs) { ++ prefs->GetBoolPref("permissions.memory_only", &memory_db); ++ } ++ + // cache a connection to the hosts database +- rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn)); ++ if (memory_db) { ++ rv = storage->OpenSpecialDatabase("memory", getter_AddRefs(mDBConn)); ++ } else { ++ rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn)); ++ } + NS_ENSURE_SUCCESS(rv, rv); + + bool ready; +@@ -262,7 +281,11 @@ nsPermissionManager::InitDB(bool aRemoveFile) + rv = permissionsFile->Remove(false); + NS_ENSURE_SUCCESS(rv, rv); + +- rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn)); ++ if (memory_db) { ++ rv = storage->OpenSpecialDatabase("memory", getter_AddRefs(mDBConn)); ++ } else { ++ rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn)); ++ } + NS_ENSURE_SUCCESS(rv, rv); + + mDBConn->GetConnectionReady(&ready); +@@ -783,7 +806,12 @@ NS_IMETHODIMP nsPermissionManager::Observe(nsISupports *aSubject, const char *aT + { + ENSURE_NOT_CHILD_PROCESS; + +- if (!nsCRT::strcmp(aTopic, "profile-before-change")) { ++ if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) { ++ if (!nsCRT::strcmp(someData, NS_LITERAL_STRING("permissions.memory_only").get())) { ++ // XXX: Should we remove the file? Probably not.. ++ InitDB(PR_FALSE); ++ } ++ } else if (!nsCRT::strcmp(aTopic, "profile-before-change")) { + // The profile is about to change, + // or is going away because the application is shutting down. + if (!nsCRT::strcmp(someData, NS_LITERAL_STRING("shutdown-cleanse").get())) { +-- +1.7.5.4 + diff --git a/src/current-patches/firefox/0003-Make-Intermediate-Cert-Store-memory-only.patch b/src/current-patches/firefox/0003-Make-Intermediate-Cert-Store-memory-only.patch new file mode 100644 index 0000000..b10fb85 --- /dev/null +++ b/src/current-patches/firefox/0003-Make-Intermediate-Cert-Store-memory-only.patch @@ -0,0 +1,43 @@ +From f100a7979e1a44863a8a67a09743f0e17b5dd14e Mon Sep 17 00:00:00 2001 +From: Mike Perry mikeperry-git@fscked.org +Date: Fri, 19 Aug 2011 17:58:23 -0700 +Subject: [PATCH 03/24] Make Intermediate Cert Store memory-only. + +This patch makes the intermediate SSL cert store exist in memory only. + +The pref must be set before startup in prefs.js. +https://trac.torproject.org/projects/tor/ticket/2949 +--- + security/manager/ssl/src/nsNSSComponent.cpp | 15 ++++++++++++++- + 1 files changed, 14 insertions(+), 1 deletions(-) + +diff --git a/security/manager/ssl/src/nsNSSComponent.cpp b/security/manager/ssl/src/nsNSSComponent.cpp +index a08c4ef..0ec3713 100644 +--- a/security/manager/ssl/src/nsNSSComponent.cpp ++++ b/security/manager/ssl/src/nsNSSComponent.cpp +@@ -1730,8 +1730,21 @@ nsNSSComponent::InitializeNSS(bool showWarningBox) + // Ubuntu 8.04, which loads any nonexistent "<configdir>/libnssckbi.so" as + // "/usr/lib/nss/libnssckbi.so". + PRUint32 init_flags = NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE; +- SECStatus init_rv = ::NSS_Initialize(profileStr.get(), "", "", ++ bool nocertdb = false; ++ mPrefBranch->GetBoolPref("security.nocertdb", &nocertdb); ++ ++ // XXX: We can also do the the following to only disable the certdb. ++ // Leaving this codepath in as a fallback in case InitNODB fails ++ if (nocertdb) ++ init_flags |= NSS_INIT_NOCERTDB; ++ ++ SECStatus init_rv; ++ if (nocertdb) { ++ init_rv = ::NSS_NoDB_Init(NULL); ++ } else { ++ init_rv = ::NSS_Initialize(profileStr.get(), "", "", + SECMOD_DB, init_flags); ++ } + + if (init_rv != SECSuccess) { + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("can not init NSS r/w in %s\n", profileStr.get())); +-- +1.7.5.4 + diff --git a/src/current-patches/firefox/0004-Add-a-string-based-cacheKey.patch b/src/current-patches/firefox/0004-Add-a-string-based-cacheKey.patch new file mode 100644 index 0000000..f3afa97 --- /dev/null +++ b/src/current-patches/firefox/0004-Add-a-string-based-cacheKey.patch @@ -0,0 +1,85 @@ +From d674d09bc233d200b1ebc47f8e6ac4ebd6e4225a Mon Sep 17 00:00:00 2001 +From: Mike Perry mikeperry-git@fscked.org +Date: Fri, 2 Sep 2011 20:47:02 -0700 +Subject: [PATCH 04/24] Add a string-based cacheKey. + +Used for isolating cache according to same-origin policy. +--- + netwerk/base/public/nsICachingChannel.idl | 7 +++++++ + netwerk/protocol/http/nsHttpChannel.cpp | 22 ++++++++++++++++++++++ + netwerk/protocol/http/nsHttpChannel.h | 1 + + 3 files changed, 30 insertions(+), 0 deletions(-) + +diff --git a/netwerk/base/public/nsICachingChannel.idl b/netwerk/base/public/nsICachingChannel.idl +index 2da46d6..4ee5774 100644 +--- a/netwerk/base/public/nsICachingChannel.idl ++++ b/netwerk/base/public/nsICachingChannel.idl +@@ -98,6 +98,13 @@ interface nsICachingChannel : nsICacheInfoChannel + attribute nsISupports cacheKey; + + /** ++ * Set/get the cache domain... uniquely identifies the data in the cache ++ * for this channel. Holding a reference to this key does NOT prevent ++ * the cached data from being removed. ++ */ ++ attribute AUTF8String cacheDomain; ++ ++ /** + * Specifies whether or not the data should be cached to a file. This + * may fail if the disk cache is not present. The value of this attribute + * is usually only settable during the processing of a channel's +diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp +index dec2a83..97bd84c 100644 +--- a/netwerk/protocol/http/nsHttpChannel.cpp ++++ b/netwerk/protocol/http/nsHttpChannel.cpp +@@ -2392,6 +2392,12 @@ nsHttpChannel::AssembleCacheKey(const char *spec, PRUint32 postID, + cacheKey.Append(buf); + } + ++ if (strlen(mCacheDomain.get()) > 0) { ++ cacheKey.AppendLiteral("domain="); ++ cacheKey.Append(mCacheDomain.get()); ++ cacheKey.AppendLiteral("&"); ++ } ++ + if (!cacheKey.IsEmpty()) { + cacheKey.AppendLiteral("uri="); + } +@@ -4695,6 +4701,22 @@ nsHttpChannel::SetCacheForOfflineUse(bool value) + } + + NS_IMETHODIMP ++nsHttpChannel::GetCacheDomain(nsACString &value) ++{ ++ value = mCacheDomain; ++ ++ return NS_OK; ++} ++ ++NS_IMETHODIMP ++nsHttpChannel::SetCacheDomain(const nsACString &value) ++{ ++ mCacheDomain = value; ++ ++ return NS_OK; ++} ++ ++NS_IMETHODIMP + nsHttpChannel::GetOfflineCacheClientID(nsACString &value) + { + value = mOfflineCacheClientID; +diff --git a/netwerk/protocol/http/nsHttpChannel.h b/netwerk/protocol/http/nsHttpChannel.h +index 88ce469..53538cf 100644 +--- a/netwerk/protocol/http/nsHttpChannel.h ++++ b/netwerk/protocol/http/nsHttpChannel.h +@@ -303,6 +303,7 @@ private: + nsCOMPtr<nsICacheEntryDescriptor> mOfflineCacheEntry; + nsCacheAccessMode mOfflineCacheAccess; + nsCString mOfflineCacheClientID; ++ nsCString mCacheDomain; + + // auth specific data + nsCOMPtr<nsIHttpChannelAuthProvider> mAuthProvider; +-- +1.7.5.4 + diff --git a/src/current-patches/firefox/0005-Block-all-plugins-except-flash.patch b/src/current-patches/firefox/0005-Block-all-plugins-except-flash.patch new file mode 100644 index 0000000..e7a831e --- /dev/null +++ b/src/current-patches/firefox/0005-Block-all-plugins-except-flash.patch @@ -0,0 +1,85 @@ +From 88a390822d232ba037de1f15091977ca7e1064bf Mon Sep 17 00:00:00 2001 +From: Mike Perry mikeperry-git@torproject.org +Date: Wed, 1 Feb 2012 15:50:15 -0800 +Subject: [PATCH 05/24] Block all plugins except flash. + +We cannot use the @mozilla.org/extensions/blocklist;1 service, because we +actually want to stop plugins from ever entering the browser's process space +and/or executing code (for example, AV plugins that collect statistics/analyse +urls, magical toolbars that phone home or "help" the user, skype buttons that +ruin our day, and censorship filters). Hence we rolled our own. + +See https://trac.torproject.org/projects/tor/ticket/3547#comment:6 for musings +on a better way. Until then, it is delta-darwinism for us. +--- + dom/plugins/base/nsPluginHost.cpp | 33 +++++++++++++++++++++++++++++++++ + dom/plugins/base/nsPluginHost.h | 2 ++ + 2 files changed, 35 insertions(+), 0 deletions(-) + +diff --git a/dom/plugins/base/nsPluginHost.cpp b/dom/plugins/base/nsPluginHost.cpp +index 992bcd4..f56f231 100644 +--- a/dom/plugins/base/nsPluginHost.cpp ++++ b/dom/plugins/base/nsPluginHost.cpp +@@ -1968,6 +1968,35 @@ bool nsPluginHost::IsDuplicatePlugin(nsPluginTag * aPluginTag) + return false; + } + ++PRBool nsPluginHost::GhettoBlacklist(nsIFile *pluginFile) ++{ ++ nsCString leaf; ++ const char *leafStr; ++ nsresult rv; ++ ++ rv = pluginFile->GetNativeLeafName(leaf); ++ if (NS_FAILED(rv)) { ++ return PR_TRUE; // fuck 'em. blacklist. ++ } ++ ++ leafStr = leaf.get(); ++ ++ if (!leafStr) { ++ return PR_TRUE; // fuck 'em. blacklist. ++ } ++ ++ // libgnashplugin.so, libflashplayer.so, Flash Player-10.4-10.5.plugin, ++ // NPSWF32.dll, NPSWF64.dll ++ if (strstr(leafStr, "libgnashplugin") == leafStr || ++ strstr(leafStr, "libflashplayer") == leafStr || ++ strstr(leafStr, "Flash Player") == leafStr || ++ strstr(leafStr, "NPSWF") == leafStr) { ++ return PR_FALSE; ++ } ++ ++ return PR_TRUE; // fuck 'em. blacklist. ++} ++ + typedef NS_NPAPIPLUGIN_CALLBACK(char *, NP_GETMIMEDESCRIPTION)(void); + + nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir, +@@ -2101,6 +2130,10 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir, + continue; + } + ++ if (GhettoBlacklist(localfile)) { ++ continue; ++ } ++ + // if it is not found in cache info list or has been changed, create a new one + if (!pluginTag) { + nsPluginFile pluginFile(localfile); +diff --git a/dom/plugins/base/nsPluginHost.h b/dom/plugins/base/nsPluginHost.h +index 39a8891..c262abf 100644 +--- a/dom/plugins/base/nsPluginHost.h ++++ b/dom/plugins/base/nsPluginHost.h +@@ -278,6 +278,8 @@ private: + // Loads all cached plugins info into mCachedPlugins + nsresult ReadPluginInfo(); + ++ PRBool GhettoBlacklist(nsIFile *pluginFile); ++ + // Given a file path, returns the plugins info from our cache + // and removes it from the cache. + void RemoveCachedPluginsInfo(const char *filePath, +-- +1.7.5.4 + diff --git a/src/current-patches/firefox/0006-Make-content-pref-service-memory-only-clearable.patch b/src/current-patches/firefox/0006-Make-content-pref-service-memory-only-clearable.patch new file mode 100644 index 0000000..17af793 --- /dev/null +++ b/src/current-patches/firefox/0006-Make-content-pref-service-memory-only-clearable.patch @@ -0,0 +1,37 @@ +From 71ba98d81a6ecada62af4d2ee03be050d371d996 Mon Sep 17 00:00:00 2001 +From: Mike Perry mikeperry-git@fscked.org +Date: Thu, 8 Sep 2011 08:40:17 -0700 +Subject: [PATCH 06/24] Make content pref service memory-only + clearable + +This prevents random urls from being inserted into content-prefs.sqllite in +the profile directory as content prefs change (includes site-zoom and perhaps +other site prefs?). +--- + .../contentprefs/nsContentPrefService.js | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/toolkit/components/contentprefs/nsContentPrefService.js b/toolkit/components/contentprefs/nsContentPrefService.js +index adfb650..1619d5f 100644 +--- a/toolkit/components/contentprefs/nsContentPrefService.js ++++ b/toolkit/components/contentprefs/nsContentPrefService.js +@@ -1240,7 +1240,7 @@ ContentPrefService.prototype = { + + var dbConnection; + +- if (!dbFile.exists()) ++ if (true || !dbFile.exists()) + dbConnection = this._dbCreate(dbService, dbFile); + else { + try { +@@ -1288,7 +1288,7 @@ ContentPrefService.prototype = { + }, + + _dbCreate: function ContentPrefService__dbCreate(aDBService, aDBFile) { +- var dbConnection = aDBService.openDatabase(aDBFile); ++ var dbConnection = aDBService.openSpecialDatabase("memory"); + + try { + this._dbCreateSchema(dbConnection); +-- +1.7.5.4 + diff --git a/src/current-patches/firefox/0007-Make-Tor-Browser-exit-when-not-launched-from-Vidalia.patch b/src/current-patches/firefox/0007-Make-Tor-Browser-exit-when-not-launched-from-Vidalia.patch new file mode 100644 index 0000000..cc496d3 --- /dev/null +++ b/src/current-patches/firefox/0007-Make-Tor-Browser-exit-when-not-launched-from-Vidalia.patch @@ -0,0 +1,46 @@ +From 12579def59d67416b841f6b0a6eadfd94bba72e9 Mon Sep 17 00:00:00 2001 +From: Mike Perry mikeperry-git@fscked.org +Date: Sun, 9 Oct 2011 22:50:07 -0700 +Subject: [PATCH 07/24] Make Tor Browser exit when not launched from Vidalia + +Turns out the Windows 7 UI encourages users to "dock" their Tor Browser app +for easy relaunch. If they manage to do this, we should fail closed rather +than opened. Hopefully they will get the hint and dock Vidalia instead. + +This is an emergency fix for +https://trac.torproject.org/projects/tor/ticket/4192. We can do a better +localized fix w/ a translated alert menu later, if it seems like this might +actually be common. +--- + browser/base/content/browser.js | 15 +++++++++++++++ + 1 files changed, 15 insertions(+), 0 deletions(-) + +diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js +index f16a0c5..20e3666 100644 +--- a/browser/base/content/browser.js ++++ b/browser/base/content/browser.js +@@ -1217,6 +1217,21 @@ function BrowserStartup() { + + prepareForStartup(); + ++ // If this is not a TBB profile, exit. ++ // Solves https://trac.torproject.org/projects/tor/ticket/4192 ++ var foundPref = false; ++ try { ++ foundPref = gPrefService.prefHasUserValue("torbrowser.version"); ++ } catch(e) { ++ //dump("No pref: "+e); ++ } ++ if(!foundPref) { ++ var appStartup = Components.classes["@mozilla.org/toolkit/app-startup;1"] ++ .getService(Components.interfaces.nsIAppStartup); ++ appStartup.quit(3); // Force all windows to close, and then quit. ++ } ++ ++ + if (uriToLoad && !isLoadingBlank) { + if (uriToLoad instanceof Ci.nsISupportsArray) { + let count = uriToLoad.Count(); +-- +1.7.5.4 + diff --git a/src/current-patches/firefox/0008-Disable-SSL-Session-ID-tracking.patch b/src/current-patches/firefox/0008-Disable-SSL-Session-ID-tracking.patch new file mode 100644 index 0000000..39e1483 --- /dev/null +++ b/src/current-patches/firefox/0008-Disable-SSL-Session-ID-tracking.patch @@ -0,0 +1,28 @@ +From 7586e413761858ce705d25d4a1673e608a162bed Mon Sep 17 00:00:00 2001 +From: Mike Perry mikeperry-git@fscked.org +Date: Wed, 7 Dec 2011 19:36:38 -0800 +Subject: [PATCH 08/24] Disable SSL Session ID tracking. + +We can't easily bind SSL Session ID tracking to url bar domain, +so we have to disable them to satisfy +https://www.torproject.org/projects/torbrowser/design/#identifier-linkabilit.... +--- + security/nss/lib/ssl/sslsock.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/security/nss/lib/ssl/sslsock.c b/security/nss/lib/ssl/sslsock.c +index 0c4d0c7..8d23fc0 100644 +--- a/security/nss/lib/ssl/sslsock.c ++++ b/security/nss/lib/ssl/sslsock.c +@@ -173,7 +173,7 @@ static sslOptions ssl_defaults = { + PR_FALSE, /* enableSSL2 */ /* now defaults to off in NSS 3.13 */ + PR_TRUE, /* enableSSL3 */ + PR_TRUE, /* enableTLS */ /* now defaults to on in NSS 3.0 */ +- PR_FALSE, /* noCache */ ++ PR_TRUE, /* noCache */ + PR_FALSE, /* fdx */ + PR_FALSE, /* v2CompatibleHello */ /* now defaults to off in NSS 3.13 */ + PR_TRUE, /* detectRollBack */ +-- +1.7.5.4 + diff --git a/src/current-patches/firefox/0009-Provide-an-observer-event-to-close-persistent-connec.patch b/src/current-patches/firefox/0009-Provide-an-observer-event-to-close-persistent-connec.patch new file mode 100644 index 0000000..e693c71 --- /dev/null +++ b/src/current-patches/firefox/0009-Provide-an-observer-event-to-close-persistent-connec.patch @@ -0,0 +1,40 @@ +From 9c6f997dd9a44336af9a1db17f5b680cc80a0e6c Mon Sep 17 00:00:00 2001 +From: Mike Perry mikeperry-git@torproject.org +Date: Wed, 1 Feb 2012 15:53:28 -0800 +Subject: [PATCH 09/24] Provide an observer event to close persistent + connections + +We need to prevent linkability across "New Identity", which includes closing +keep-alive connections. +--- + netwerk/protocol/http/nsHttpHandler.cpp | 7 +++++++ + 1 files changed, 7 insertions(+), 0 deletions(-) + +diff --git a/netwerk/protocol/http/nsHttpHandler.cpp b/netwerk/protocol/http/nsHttpHandler.cpp +index 281d6ff..8125681 100644 +--- a/netwerk/protocol/http/nsHttpHandler.cpp ++++ b/netwerk/protocol/http/nsHttpHandler.cpp +@@ -325,6 +325,7 @@ nsHttpHandler::Init() + mObserverService->AddObserver(this, "net:clear-active-logins", true); + mObserverService->AddObserver(this, NS_PRIVATE_BROWSING_SWITCH_TOPIC, true); + mObserverService->AddObserver(this, "net:prune-dead-connections", true); ++ mObserverService->AddObserver(this, "net:prune-all-connections", PR_TRUE); + } + + return NS_OK; +@@ -1504,6 +1505,12 @@ nsHttpHandler::Observe(nsISupports *subject, + mConnMgr->PruneDeadConnections(); + } + } ++ else if (strcmp(topic, "net:prune-all-connections") == 0) { ++ if (mConnMgr) { ++ mConnMgr->ClosePersistentConnections(); ++ mConnMgr->PruneDeadConnections(); ++ } ++ } + + return NS_OK; + } +-- +1.7.5.4 + diff --git a/src/current-patches/firefox/0010-Limit-device-and-system-specific-CSS-Media-Queries.patch b/src/current-patches/firefox/0010-Limit-device-and-system-specific-CSS-Media-Queries.patch new file mode 100644 index 0000000..14e584c --- /dev/null +++ b/src/current-patches/firefox/0010-Limit-device-and-system-specific-CSS-Media-Queries.patch @@ -0,0 +1,154 @@ +From 8f97f2f36adb9e4416f3d19af10880c800c846c2 Mon Sep 17 00:00:00 2001 +From: Kathleen Brade brade@pearlcrescent.com +Date: Thu, 4 Oct 2012 14:28:48 -0400 +Subject: [PATCH 10/24] Limit device and system specific CSS Media Queries. + +--- + layout/style/nsMediaFeatures.cpp | 71 ++++++++++++++++++++++++------------- + 1 files changed, 46 insertions(+), 25 deletions(-) + +diff --git a/layout/style/nsMediaFeatures.cpp b/layout/style/nsMediaFeatures.cpp +index 6eca06e..5b1df7e 100644 +--- a/layout/style/nsMediaFeatures.cpp ++++ b/layout/style/nsMediaFeatures.cpp +@@ -130,6 +130,9 @@ GetDeviceContextFor(nsPresContext* aPresContext) + static nsSize + GetDeviceSize(nsPresContext* aPresContext) + { ++ if (!aPresContext->IsChrome()) { ++ return GetSize(aPresContext); ++ } else { + nsSize size; + if (aPresContext->IsRootPaginatedDocument()) + // We want the page size, including unprintable areas and margins. +@@ -140,6 +143,7 @@ GetDeviceSize(nsPresContext* aPresContext) + GetDeviceContextFor(aPresContext)-> + GetDeviceSurfaceDimensions(size.width, size.height); + return size; ++ } + } + + static nsresult +@@ -183,17 +187,17 @@ static nsresult + GetDeviceOrientation(nsPresContext* aPresContext, const nsMediaFeature*, + nsCSSValue& aResult) + { +- nsSize size = GetDeviceSize(aPresContext); +- PRInt32 orientation; +- if (size.width > size.height) { +- orientation = NS_STYLE_ORIENTATION_LANDSCAPE; +- } else { +- // Per spec, square viewports should be 'portrait' +- orientation = NS_STYLE_ORIENTATION_PORTRAIT; +- } +- +- aResult.SetIntValue(orientation, eCSSUnit_Enumerated); +- return NS_OK; ++ nsSize size = GetDeviceSize(aPresContext); ++ PRInt32 orientation; ++ if (size.width > size.height) { ++ orientation = NS_STYLE_ORIENTATION_LANDSCAPE; ++ } else { ++ // Per spec, square viewports should be 'portrait' ++ orientation = NS_STYLE_ORIENTATION_PORTRAIT; ++ } ++ ++ aResult.SetIntValue(orientation, eCSSUnit_Enumerated); ++ return NS_OK; + } + + static nsresult +@@ -236,13 +240,17 @@ static nsresult + GetColor(nsPresContext* aPresContext, const nsMediaFeature*, + nsCSSValue& aResult) + { +- // FIXME: This implementation is bogus. nsDeviceContext +- // doesn't provide reliable information (should be fixed in bug +- // 424386). +- // FIXME: On a monochrome device, return 0! +- nsDeviceContext *dx = GetDeviceContextFor(aPresContext); +- PRUint32 depth; +- dx->GetDepth(depth); ++ PRUint32 depth = 24; // Always return 24 to non-chrome callers. ++ ++ if (aPresContext->IsChrome()) { ++ // FIXME: This implementation is bogus. nsDeviceContext ++ // doesn't provide reliable information (should be fixed in bug ++ // 424386). ++ // FIXME: On a monochrome device, return 0! ++ nsDeviceContext *dx = GetDeviceContextFor(aPresContext); ++ dx->GetDepth(depth); ++ } ++ + // The spec says to use bits *per color component*, so divide by 3, + // and round down, since the spec says to use the smallest when the + // color components differ. +@@ -280,9 +288,14 @@ static nsresult + GetResolution(nsPresContext* aPresContext, const nsMediaFeature*, + nsCSSValue& aResult) + { +- // Resolution values are in device pixels, not CSS pixels. +- nsDeviceContext *dx = GetDeviceContextFor(aPresContext); +- float dpi = float(dx->AppUnitsPerPhysicalInch()) / float(dx->AppUnitsPerDevPixel()); ++ float dpi = 96; // Always return 96 to non-chrome callers. ++ ++ if (aPresContext->IsChrome()) { ++ // Resolution values are in device pixels, not CSS pixels. ++ nsDeviceContext *dx = GetDeviceContextFor(aPresContext); ++ dpi = float(dx->AppUnitsPerPhysicalInch()) / float(dx->AppUnitsPerDevPixel()); ++ } ++ + aResult.SetFloatValue(dpi, eCSSUnit_Inch); + return NS_OK; + } +@@ -311,8 +324,12 @@ static nsresult + GetDevicePixelRatio(nsPresContext* aPresContext, const nsMediaFeature*, + nsCSSValue& aResult) + { +- float ratio = aPresContext->CSSPixelsToDevPixels(1.0f); +- aResult.SetFloatValue(ratio, eCSSUnit_Number); ++ if (aPresContext->IsChrome()) { ++ float ratio = aPresContext->CSSPixelsToDevPixels(1.0f); ++ aResult.SetFloatValue(ratio, eCSSUnit_Number); ++ } else { ++ aResult.SetFloatValue(1.0, eCSSUnit_Number); ++ } + return NS_OK; + } + +@@ -320,18 +337,21 @@ static nsresult + GetSystemMetric(nsPresContext* aPresContext, const nsMediaFeature* aFeature, + nsCSSValue& aResult) + { ++ if (aPresContext->IsChrome()) { + NS_ABORT_IF_FALSE(aFeature->mValueType == nsMediaFeature::eBoolInteger, + "unexpected type"); + nsIAtom *metricAtom = *aFeature->mData.mMetric; + bool hasMetric = nsCSSRuleProcessor::HasSystemMetric(metricAtom); + aResult.SetIntValue(hasMetric ? 1 : 0, eCSSUnit_Integer); +- return NS_OK; ++ } ++ return NS_OK; + } + + static nsresult + GetWindowsTheme(nsPresContext* aPresContext, const nsMediaFeature* aFeature, + nsCSSValue& aResult) + { ++ if (aPresContext->IsChrome()) { + aResult.Reset(); + #ifdef XP_WIN + PRUint8 windowsThemeId = +@@ -350,7 +370,8 @@ GetWindowsTheme(nsPresContext* aPresContext, const nsMediaFeature* aFeature, + } + } + #endif +- return NS_OK; ++ } ++ return NS_OK; + } + + /* +-- +1.7.5.4 + diff --git a/src/current-patches/firefox/0011-Limit-the-number-of-fonts-per-document.patch b/src/current-patches/firefox/0011-Limit-the-number-of-fonts-per-document.patch new file mode 100644 index 0000000..ff9e618 --- /dev/null +++ b/src/current-patches/firefox/0011-Limit-the-number-of-fonts-per-document.patch @@ -0,0 +1,228 @@ +From cb3a6f45dd2c15d6b75084e1a4dded18ed638632 Mon Sep 17 00:00:00 2001 +From: Mike Perry mikeperry-git@torproject.org +Date: Wed, 1 Feb 2012 16:01:21 -0800 +Subject: [PATCH 11/24] Limit the number of fonts per document. + +We create two prefs: +browser.display.max_font_count and browser.display.max_font_attempts. +max_font_count sets a limit on the number of fonts actually used in the +document, and max_font_attempts sets a limit on the total number of CSS +queries that a document is allowed to perform. + +Once either limit is reached, the browser behaves as if +browser.display.use_document_fonts was set to 0 for subsequent font queries. + +If a pref is not set or is negative, that limit does not apply. + +This is done to address: +https://www.torproject.org/projects/torbrowser/design/#fingerprinting-linkab... +--- + layout/base/nsPresContext.cpp | 100 +++++++++++++++++++++++++++++++++++++++++ + layout/base/nsPresContext.h | 9 ++++ + layout/style/nsRuleNode.cpp | 13 ++++- + 3 files changed, 119 insertions(+), 3 deletions(-) + +diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp +index e1587db..9690d9c 100644 +--- a/layout/base/nsPresContext.cpp ++++ b/layout/base/nsPresContext.cpp +@@ -98,6 +98,8 @@ + #include "FrameLayerBuilder.h" + #include "nsDOMMediaQueryList.h" + #include "nsSMILAnimationController.h" ++#include "nsString.h" ++#include "nsUnicharUtils.h" + + #ifdef IBMBIDI + #include "nsBidiPresUtils.h" +@@ -706,6 +708,10 @@ nsPresContext::GetUserPreferences() + // * use fonts? + mUseDocumentFonts = + Preferences::GetInt("browser.display.use_document_fonts") != 0; ++ mMaxFonts = ++ Preferences::GetInt("browser.display.max_font_count", -1); ++ mMaxFontAttempts = ++ Preferences::GetInt("browser.display.max_font_attempts", -1); + + // * replace backslashes with Yen signs? (bug 245770) + mEnableJapaneseTransform = +@@ -1300,6 +1306,100 @@ nsPresContext::GetDefaultFont(PRUint8 aFontID) const + return font; + } + ++PRBool ++nsPresContext::FontUseCountReached(const nsFont &font) { ++ if (mMaxFonts < 0) { ++ return PR_FALSE; ++ } ++ ++ for (PRUint32 i = 0; i < mFontsUsed.Length(); i++) { ++ if (mFontsUsed[i].name.Equals(font.name, ++ nsCaseInsensitiveStringComparator()) ++ // XXX: Style is sometimes filled with garbage?? ++ /*&& mFontsUsed[i].style == font.style*/) { ++ // seen it before: OK ++ return PR_FALSE; ++ } ++ } ++ ++ if (mFontsUsed.Length() >= mMaxFonts) { ++ return PR_TRUE; ++ } ++ ++ return PR_FALSE; ++} ++ ++PRBool ++nsPresContext::FontAttemptCountReached(const nsFont &font) { ++ if (mMaxFontAttempts < 0) { ++ return PR_FALSE; ++ } ++ ++ for (PRUint32 i = 0; i < mFontsTried.Length(); i++) { ++ if (mFontsTried[i].name.Equals(font.name, ++ nsCaseInsensitiveStringComparator()) ++ // XXX: Style is sometimes filled with garbage?? ++ /*&& mFontsTried[i].style == font.style*/) { ++ // seen it before: OK ++ return PR_FALSE; ++ } ++ } ++ ++ if (mFontsTried.Length() >= mMaxFontAttempts) { ++ return PR_TRUE; ++ } ++ ++ return PR_FALSE; ++} ++ ++void ++nsPresContext::AddFontUse(const nsFont &font) { ++ if (mMaxFonts < 0) { ++ return; ++ } ++ ++ for (PRUint32 i = 0; i < mFontsUsed.Length(); i++) { ++ if (mFontsUsed[i].name.Equals(font.name, ++ nsCaseInsensitiveStringComparator()) ++ // XXX: Style is sometimes filled with garbage?? ++ /*&& mFontsUsed[i].style == font.style*/) { ++ // seen it before: OK ++ return; ++ } ++ } ++ ++ if (mFontsUsed.Length() >= mMaxFonts) { ++ return; ++ } ++ ++ mFontsUsed.AppendElement(font); ++ return; ++} ++ ++void ++nsPresContext::AddFontAttempt(const nsFont &font) { ++ if (mMaxFontAttempts < 0) { ++ return; ++ } ++ ++ for (PRUint32 i = 0; i < mFontsTried.Length(); i++) { ++ if (mFontsTried[i].name.Equals(font.name, ++ nsCaseInsensitiveStringComparator()) ++ // XXX: Style is sometimes filled with garbage?? ++ /*&& mFontsTried[i].style == font.style*/) { ++ // seen it before: OK ++ return; ++ } ++ } ++ ++ if (mFontsTried.Length() >= mMaxFontAttempts) { ++ return; ++ } ++ ++ mFontsTried.AppendElement(font); ++ return; ++} ++ + void + nsPresContext::SetFullZoom(float aZoom) + { +diff --git a/layout/base/nsPresContext.h b/layout/base/nsPresContext.h +index ecd01d8..552a69a 100644 +--- a/layout/base/nsPresContext.h ++++ b/layout/base/nsPresContext.h +@@ -548,6 +548,13 @@ public: + } + } + ++ nsTArray<nsFont> mFontsUsed; // currently for font-count limiting only ++ nsTArray<nsFont> mFontsTried; // currently for font-count limiting only ++ void AddFontUse(const nsFont &font); ++ void AddFontAttempt(const nsFont &font); ++ PRBool FontUseCountReached(const nsFont &font); ++ PRBool FontAttemptCountReached(const nsFont &font); ++ + PRInt32 MinFontSize() const { + return NS_MAX(mMinFontSize, mMinimumFontSizePref); + } +@@ -1117,6 +1124,8 @@ protected: + PRUint32 mInterruptChecksToSkip; + + mozilla::TimeStamp mReflowStartTime; ++ PRInt32 mMaxFontAttempts; ++ PRInt32 mMaxFonts; + + unsigned mHasPendingInterrupt : 1; + unsigned mInterruptsEnabled : 1; +diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp +index 27336bf..827585a 100644 +--- a/layout/style/nsRuleNode.cpp ++++ b/layout/style/nsRuleNode.cpp +@@ -3091,6 +3091,7 @@ nsRuleNode::ComputeFontData(void* aStartStruct, + + // See if there is a minimum font-size constraint to honor + nscoord minimumFontSize = mPresContext->MinFontSize(); ++ PRBool isXUL = PR_FALSE; + + if (minimumFontSize < 0) + minimumFontSize = 0; +@@ -3102,10 +3103,10 @@ nsRuleNode::ComputeFontData(void* aStartStruct, + // We only need to know this to determine if we have to use the + // document fonts (overriding the useDocumentFonts flag), or to + // determine if we have to override the minimum font-size constraint. +- if ((!useDocumentFonts || minimumFontSize > 0) && mPresContext->IsChrome()) { ++ if (mPresContext->IsChrome()) { + // if we are not using document fonts, but this is a XUL document, + // then we use the document fonts anyway +- useDocumentFonts = true; ++ isXUL = PR_TRUE; + minimumFontSize = 0; + } + +@@ -3120,9 +3121,13 @@ nsRuleNode::ComputeFontData(void* aStartStruct, + // generic? + nsFont::GetGenericID(font->mFont.name, &generic); + ++ mPresContext->AddFontAttempt(font->mFont); ++ + // If we aren't allowed to use document fonts, then we are only entitled + // to use the user's default variable-width font and fixed-width font +- if (!useDocumentFonts) { ++ if (!isXUL && (!useDocumentFonts || ++ mPresContext->FontAttemptCountReached(font->mFont) || ++ mPresContext->FontUseCountReached(font->mFont))) { + // Extract the generic from the specified font family... + nsAutoString genericName; + if (!font->mFont.EnumerateFamilies(ExtractGeneric, &genericName)) { +@@ -3158,6 +3163,8 @@ nsRuleNode::ComputeFontData(void* aStartStruct, + minimumFontSize, font); + } + ++ if (font->mGenericID == kGenericFont_NONE) ++ mPresContext->AddFontUse(font->mFont); + COMPUTE_END_INHERITED(Font, font) + } + +-- +1.7.5.4 + diff --git a/src/current-patches/firefox/0012-Rebrand-Firefox-to-TorBrowser.patch b/src/current-patches/firefox/0012-Rebrand-Firefox-to-TorBrowser.patch new file mode 100644 index 0000000..e627238 --- /dev/null +++ b/src/current-patches/firefox/0012-Rebrand-Firefox-to-TorBrowser.patch @@ -0,0 +1,50 @@ +From 5820fc300fe1cae27752673e8721a19e70bf727c Mon Sep 17 00:00:00 2001 +From: Erinn Clark erinn@torproject.org +Date: Wed, 25 Apr 2012 09:14:00 -0300 +Subject: [PATCH 12/24] Rebrand Firefox to TorBrowser + +This patch does some basic renaming of Firefox to TorBrowser. The rest of the +branding is done by images and icons. +--- + browser/branding/official/configure.sh | 2 +- + browser/branding/official/locales/en-US/brand.dtd | 6 +++--- + .../official/locales/en-US/brand.properties | 6 +++--- + 3 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/browser/branding/official/configure.sh b/browser/branding/official/configure.sh +index 4d3d297..e9b3738 100644 +--- a/browser/branding/official/configure.sh ++++ b/browser/branding/official/configure.sh +@@ -1,2 +1,2 @@ +-MOZ_APP_DISPLAYNAME=Firefox ++MOZ_APP_DISPLAYNAME=TorBrowser + MOZ_UA_BUILDID=20100101 +diff --git a/browser/branding/official/locales/en-US/brand.dtd b/browser/branding/official/locales/en-US/brand.dtd +index 142d79b..c137e04 100644 +--- a/browser/branding/official/locales/en-US/brand.dtd ++++ b/browser/branding/official/locales/en-US/brand.dtd +@@ -1,4 +1,4 @@ +-<!ENTITY brandShortName "Firefox"> +-<!ENTITY brandFullName "Mozilla Firefox"> +-<!ENTITY vendorShortName "Mozilla"> ++<!ENTITY brandShortName "TorBrowser"> ++<!ENTITY brandFullName "Tor Browser"> ++<!ENTITY vendorShortName "Tor Project"> + <!ENTITY trademarkInfo.part1 "Firefox and the Firefox logos are trademarks of the Mozilla Foundation."> +diff --git a/browser/branding/official/locales/en-US/brand.properties b/browser/branding/official/locales/en-US/brand.properties +index 5f3ad54..62ac2fd 100644 +--- a/browser/branding/official/locales/en-US/brand.properties ++++ b/browser/branding/official/locales/en-US/brand.properties +@@ -1,6 +1,6 @@ +-brandShortName=Firefox +-brandFullName=Mozilla Firefox +-vendorShortName=Mozilla ++brandShortName=TorBrowser ++brandFullName=Tor Browser ++vendorShortName=Tor Project + + homePageSingleStartMain=Firefox Start, a fast home page with built-in search + homePageImport=Import your home page from %S +-- +1.7.5.4 + diff --git a/src/current-patches/firefox/0013-Make-Download-manager-memory-only.patch b/src/current-patches/firefox/0013-Make-Download-manager-memory-only.patch new file mode 100644 index 0000000..1ad0972 --- /dev/null +++ b/src/current-patches/firefox/0013-Make-Download-manager-memory-only.patch @@ -0,0 +1,57 @@ +From 28178fb406d86b317b13b16ade3b06e5e1500c7e Mon Sep 17 00:00:00 2001 +From: Mike Perry mikeperry-git@torproject.org +Date: Wed, 25 Apr 2012 13:39:35 -0700 +Subject: [PATCH 13/24] Make Download manager memory only. + +Solves https://trac.torproject.org/projects/tor/ticket/4017. + +Yes, this is an ugly hack. We *could* send the observer notification from +Torbutton to tell the download manager to switch to memory, but then we have +to dance around and tell it again if the user switches in and out of private +browsing mode.. + +The right way to do this is with a pref. Maybe I'll get to that someday, if +this breaks enough times in conflict. +--- + toolkit/components/downloads/nsDownloadManager.cpp | 4 ++-- + toolkit/components/downloads/nsDownloadManager.h | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/toolkit/components/downloads/nsDownloadManager.cpp b/toolkit/components/downloads/nsDownloadManager.cpp +index 00a6e7d..2e83f61 100644 +--- a/toolkit/components/downloads/nsDownloadManager.cpp ++++ b/toolkit/components/downloads/nsDownloadManager.cpp +@@ -1992,7 +1992,7 @@ nsDownloadManager::Observe(nsISupports *aSubject, + if (NS_LITERAL_STRING("memory").Equals(aData)) + return SwitchDatabaseTypeTo(DATABASE_MEMORY); + else if (NS_LITERAL_STRING("disk").Equals(aData)) +- return SwitchDatabaseTypeTo(DATABASE_DISK); ++ return SwitchDatabaseTypeTo(DATABASE_MEMORY); + } + else if (strcmp(aTopic, "alertclickcallback") == 0) { + nsCOMPtr<nsIDownloadManagerUI> dmui = +@@ -2069,7 +2069,7 @@ nsDownloadManager::OnLeavePrivateBrowsingMode() + (void)ResumeAllDownloads(false); + + // Switch back to the on-disk DB again +- (void)SwitchDatabaseTypeTo(DATABASE_DISK); ++ //(void)SwitchDatabaseTypeTo(DATABASE_DISK); + + mInPrivateBrowsing = false; + } +diff --git a/toolkit/components/downloads/nsDownloadManager.h b/toolkit/components/downloads/nsDownloadManager.h +index 54312e4..cb63b52 100644 +--- a/toolkit/components/downloads/nsDownloadManager.h ++++ b/toolkit/components/downloads/nsDownloadManager.h +@@ -90,7 +90,7 @@ public: + + virtual ~nsDownloadManager(); + nsDownloadManager() : +- mDBType(DATABASE_DISK) ++ mDBType(DATABASE_MEMORY) + , mInPrivateBrowsing(false) + #ifdef DOWNLOAD_SCANNER + , mScanner(nsnull) +-- +1.7.5.4 + diff --git a/src/current-patches/firefox/0014-Add-DDG-and-StartPage-to-Omnibox.patch b/src/current-patches/firefox/0014-Add-DDG-and-StartPage-to-Omnibox.patch new file mode 100644 index 0000000..adbd3d4 --- /dev/null +++ b/src/current-patches/firefox/0014-Add-DDG-and-StartPage-to-Omnibox.patch @@ -0,0 +1,84 @@ +From 2a80e84755c97cf4ff3ab63bda1bd5f0936d9594 Mon Sep 17 00:00:00 2001 +From: Mike Perry mikeperry-git@torproject.org +Date: Wed, 25 Apr 2012 15:03:46 -0700 +Subject: [PATCH 14/24] Add DDG and StartPage to Omnibox. + +You mean there are search engines that don't require captchas if you don't +have a cookie? Holy crap. Get those in there now. +--- + browser/locales/en-US/searchplugins/duckduckgo.xml | 29 ++++++++++++++++++++ + browser/locales/en-US/searchplugins/list.txt | 2 + + browser/locales/en-US/searchplugins/startpage.xml | 11 +++++++ + 3 files changed, 42 insertions(+), 0 deletions(-) + create mode 100644 browser/locales/en-US/searchplugins/duckduckgo.xml + create mode 100644 browser/locales/en-US/searchplugins/startpage.xml + +diff --git a/browser/locales/en-US/searchplugins/duckduckgo.xml b/browser/locales/en-US/searchplugins/duckduckgo.xml +new file mode 100644 +index 0000000..4f00b4d +--- /dev/null ++++ b/browser/locales/en-US/searchplugins/duckduckgo.xml +@@ -0,0 +1,29 @@ ++<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/"> ++<ShortName>DuckDuckGo</ShortName> ++<Description>Duck Duck Go</Description> ++<InputEncoding>UTF-8</InputEncoding> ++<Image width="16" height="16">data:image/png;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAANcNAADXDQAAAAAA ++AAAAAAAAAAAAAAAAAAAAAAAAAAAAJyDsJmlk8pf6+v3s/v7+++zr/fcnIOyzJyDsgCcg7CYAAAAA ++AAAAAAAAAAAAAAAAAAAAAAAAAAAnIOwBJyDscCcg7PZttJ7/7Pfs//////++xO7/S5GA/ycg7P8n ++IOz2JyDscCcg7AEAAAAAAAAAAAAAAAAnIOwBJyDstScg7P8nIOz/Y8p5/2fHZf9Yv0z/YcF2/1rB ++Uv8nIOz/JyDs/ycg7P8nIOy1JyDsAQAAAAAAAAAAJyDscCcg7P8nIOz/JyDs/4jQoP/p9+n///// ++/05X3v9LkYD/JyDs/ycg7P8nIOz/JyDs/ycg7HAAAAAAJyDsJicg7PYnIOz/JyDs/zUu7f/+/v// ++//////////89N+7/JyDs/yUo7f8nIOz/JyDs/ycg7P8nIOz2JyDsJicg7IAnIOz/JyDs/ycg7P9h ++XPH////////////t/P//GIr2/wfD+/8Gyfz/DKv5/yM57/8nIOz/JyDs/ycg7H8nIOyzJyDs/ycg ++7P8nIOz/jov1////////////Otz9/w3G/P8cWfH/JSvt/ycg7P8nIOz/JyDs/ycg7P8nIOyzJyDs ++5icg7P8nIOz/JyDs/7u5+f///////////27l/v8E0v3/BNL9/wTQ/f8Oofn/IT7v/ycg7P8nIOz/ ++JyDs5icg7OYnIOz/JyDs/ycg7P/p6P3/uWsC////////////5fr//6Po/f8Thfb/DKv5/w6f+f8n IOz/JyDs/ycg7OYnIOyzJyDs/ycg7P8nIOz/9/b+/////////////////7lrAv/V1Pv/JyDs/ycg ++7P8nIOz/JyDs/ycg7P8nIOyzJyDsgCcg7P8nIOz/JyDs/8/N+///////////////////////iIX1 ++/ycg7P8nIOz/JyDs/ycg7P8nIOz/JyDsfycg7CYnIOz2JyDs/ycg7P9FP+7/q6n4/+7u/f/n5v3/ ++fXn0/yoj7P8nIOz/JyDs/ycg7P8nIOz/JyDs9icg7CYAAAAAJyDscCcg7P8nIOz/wsD6/+no/f/Y ++1/z/eHTz/ycg7P8nIOz/JyDs/ycg7P8nIOz/JyDs/ycg7HAAAAAAAAAAACcg7AEnIOy1JyDs/ycg ++7P8nIOz/JyDs/ycg7P8nIOz/JyDs/ycg7P8nIOz/JyDs/ycg7LUnIOwBAAAAAAAAAAAAAAAAJyDs ++AScg7HAnIOz2JyDs/ycg7P8nIOz/JyDs/ycg7P8nIOz/JyDs9icg7HAnIOwBAAAAAAAAAAAAAAAA ++AAAAAAAAAAAAAAAAJyDsJicg7IAnIOyzJyDs5icg7OYnIOyzJyDsgCcg7CYAAAAAAAAAAAAAAAAA ++AAAA+B8AAPAPAADAAwAAwAMAAIABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABAACAAQAAwAMAAMAD ++AADwDwAA+B8AAA==</Image> ++<Url type="text/html" method="POST" template="https://duckduckgo.com/html/"> ++ <Param name="q" value="{searchTerms}"/> ++</Url> ++<SearchForm>https://duckduckgo.com/html/</SearchForm> ++</SearchPlugin> +diff --git a/browser/locales/en-US/searchplugins/list.txt b/browser/locales/en-US/searchplugins/list.txt +index 2a1141a..0466f4e 100644 +--- a/browser/locales/en-US/searchplugins/list.txt ++++ b/browser/locales/en-US/searchplugins/list.txt +@@ -1,7 +1,9 @@ + amazondotcom + bing ++duckduckgo + eBay + google ++startpage + twitter + wikipedia + yahoo +diff --git a/browser/locales/en-US/searchplugins/startpage.xml b/browser/locales/en-US/searchplugins/startpage.xml +new file mode 100644 +index 0000000..1a310b1 +--- /dev/null ++++ b/browser/locales/en-US/searchplugins/startpage.xml +@@ -0,0 +1,11 @@ ++<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/"> ++<ShortName>Startpage</ShortName> ++<Description>Start Page</Description> ++<InputEncoding>UTF-8</InputEncoding> ++<Image width="16" height="16">data:image/png;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2jkj+9YtD/vWLQ/71i0P+9otD/vaLRP72i0T+9YtE/vWLRP72i0T+9otD/vaNRP72jUT+9otF/vaLRf73kkv+9Yc///WJP//1iT//9Yk///rAmf/94Mz/+sCa//aRTv/1iUH/9ok///aJP//2i0H/9otB//aJQv/2iUL/9otC//aNRP/2jUT/9o1E//aNRP/6wpv////////////96dr/95dQ//aNRP/2kET/9pBG//aQRv/2kEb/9pBG//aRR//3lEz/95BH//mueP/7xJ3/959g//efYf/4p23//vDm//3p2//3kEr/95FJ//aRSf/niFH/95FK//aRSv/2mE//95hS/vq4iP/////////////////81bj/95xZ//q4iP//////+bF+//eZT//njFT/PSqi/2xGjv/2mVD/951V/vedVv783cX///////vQrf/++PP///////748//+8uj///////m3gf/olFr/PSuj/w8Pt/9sSJD/951V//eeWf73oVv++8ul///////5sXf/+KRi//vRsf////////////3r3v/olF//Piyk/w8Pt/9sSJH/+J5Z//ieWv/3oV/++KZf/vihXP/97N7//vn0//zTs//6wJP/+bBy//q6iP/onW//Piyl/w8Pt/8fGbH/m2iB/+icY//4pGD/96hl/viqZf74pmD/+Kxr//3iy/////////n1//ivbP/onGj/Pi2m/w8Pt/8uJKz/fFeQ/x8Zsf8+Lqb/6J9r//ivbP74rm3++Klm//mpZv/5q2f/+bR9//m0e//poW7/Pi6n/w8Pt/9sTZj/+Ktp//ira/+rd4P/Dw+3/4xijv/5snH+ +LN1/vmvbf/5r23/+a5t//mvb//4r2//TTuk/w8Pt/8fGrL/6ah1//ivcP/4r3P/q3yI/w8Pt/+MZpP/+bN5/vm4ev75t3X/+bV1//m1df/5t3X/+Ld3/8qUhP98XZn/Hxqz/+mse//5t3f/2p+B/x8as/8PD7f/u4qK//m7fv76u4D++bl7//m3fP/5uXz/+bl8//m5fP/5t3z/+bl//x8as/9NPKf/fWCb/x8as/8PD7f/bVOh//q5f//6v4X++sGI/vm9g//5voX/+b6F//m9hf/6vYX/+r6F//nCh/+bepr/Hxu0/w8Pt/8PD7f/fWOh//q+hf/6wof/+saN/vrGjf75xIv/+ceL//nEi//5xIv/+sSL//rHi//6x43/+ceN/+m7kP+7lpj/6ruQ//rHkP/6x43/+seQ//rLlf76ypT++seR//rJkf/6yZH/+seR//rJkf/6yZH/+8mR//vJlP/7yZT/+smU//rJlP/6yZT/+8yV//rJlf/6zpn+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</Image> ++ ++<Url type="text/html" method="POST" template="https://startpage.com/do/search"> ++ <Param name="q" value="{searchTerms}"/> ++</Url> ++<SearchForm>https://startpage.com/do/search/</SearchForm> ++</SearchPlugin> +-- +1.7.5.4 + diff --git a/src/current-patches/firefox/0015-Make-nsICacheService.EvictEntries-synchronous.patch b/src/current-patches/firefox/0015-Make-nsICacheService.EvictEntries-synchronous.patch new file mode 100644 index 0000000..93a989b --- /dev/null +++ b/src/current-patches/firefox/0015-Make-nsICacheService.EvictEntries-synchronous.patch @@ -0,0 +1,44 @@ +From 20c94cb890a8872c07ba13686e293ca147b85cd6 Mon Sep 17 00:00:00 2001 +From: Mike Perry mikeperry-git@torproject.org +Date: Tue, 1 May 2012 15:02:03 -0700 +Subject: [PATCH 15/24] Make nsICacheService.EvictEntries synchronous + +This fixes a race condition that allows cache-based EverCookies to persist for +a brief time (on the order of minutes?) after cache clearing/"New Identity". + +https://trac.torproject.org/projects/tor/ticket/5715 +--- + netwerk/cache/nsCacheService.cpp | 15 +++++++++++++-- + 1 files changed, 13 insertions(+), 2 deletions(-) + +diff --git a/netwerk/cache/nsCacheService.cpp b/netwerk/cache/nsCacheService.cpp +index 83ce887..e9f1a76 100644 +--- a/netwerk/cache/nsCacheService.cpp ++++ b/netwerk/cache/nsCacheService.cpp +@@ -1316,10 +1316,21 @@ NS_IMETHODIMP nsCacheService::VisitEntries(nsICacheVisitor *visitor) + return NS_OK; + } + +- + NS_IMETHODIMP nsCacheService::EvictEntries(nsCacheStoragePolicy storagePolicy) + { +- return EvictEntriesForClient(nsnull, storagePolicy); ++ NS_IMETHODIMP r; ++ r = EvictEntriesForClient(nsnull, storagePolicy); ++ ++ // XXX: Bloody hack until we get this notifier in FF14.0: ++ // https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsICacheListener#... ++ if (storagePolicy == nsICache::STORE_ANYWHERE && ++ NS_IsMainThread() && gService && gService->mInitialized) { ++ nsCacheServiceAutoLock lock; ++ gService->DoomActiveEntries(); ++ gService->ClearDoomList(); ++ (void) SyncWithCacheIOThread(); ++ } ++ return r; + } + + NS_IMETHODIMP nsCacheService::GetCacheIOTarget(nsIEventTarget * *aCacheIOTarget) +-- +1.7.5.4 + diff --git a/src/current-patches/firefox/0016-Prevent-WebSocket-DNS-leak.patch b/src/current-patches/firefox/0016-Prevent-WebSocket-DNS-leak.patch new file mode 100644 index 0000000..bb70b17 --- /dev/null +++ b/src/current-patches/firefox/0016-Prevent-WebSocket-DNS-leak.patch @@ -0,0 +1,132 @@ +From 976f0d4fabb6b0b50c83192d622827357c761bd3 Mon Sep 17 00:00:00 2001 +From: Mike Perry mikeperry-git@torproject.org +Date: Wed, 2 May 2012 17:44:39 -0700 +Subject: [PATCH 16/24] Prevent WebSocket DNS leak. + +This is due to an improper implementation of the WebSocket spec by Mozilla. + +"There MUST be no more than one connection in a CONNECTING state. If multiple +connections to the same IP address are attempted simultaneously, the client +MUST serialize them so that there is no more than one connection at a time +running through the following steps. + +If the client cannot determine the IP address of the remote host (for +example, because all communication is being done through a proxy server that +performs DNS queries itself), then the client MUST assume for the purposes of +this step that each host name refers to a distinct remote host," + +https://tools.ietf.org/html/rfc6455#page-15 + +They implmented the first paragraph, but not the second... + +While we're at it, we also prevent the DNS service from being used to look up +anything other than IP addresses if socks_remote_dns is set to true, so this +bug can't turn up in other components or due to 3rd party addons. +--- + netwerk/dns/nsDNSService2.cpp | 24 ++++++++++++++++++++++- + netwerk/dns/nsDNSService2.h | 1 + + netwerk/protocol/websocket/WebSocketChannel.cpp | 8 +++++- + 3 files changed, 30 insertions(+), 3 deletions(-) + +diff --git a/netwerk/dns/nsDNSService2.cpp b/netwerk/dns/nsDNSService2.cpp +index 68ad8a5..1253b2f 100644 +--- a/netwerk/dns/nsDNSService2.cpp ++++ b/netwerk/dns/nsDNSService2.cpp +@@ -383,6 +383,7 @@ nsDNSService::Init() + bool enableIDN = true; + bool disableIPv6 = false; + bool disablePrefetch = false; ++ bool disableDNS = false; + int proxyType = nsIProtocolProxyService::PROXYCONFIG_DIRECT; + + nsAdoptingCString ipv4OnlyDomains; +@@ -404,6 +405,10 @@ nsDNSService::Init() + + // If a manual proxy is in use, disable prefetch implicitly + prefs->GetIntPref("network.proxy.type", &proxyType); ++ ++ // If the user wants remote DNS, we should fail any lookups that still ++ // make it here. ++ prefs->GetBoolPref("network.proxy.socks_remote_dns", &disableDNS); + } + + if (mFirstTime) { +@@ -420,7 +425,7 @@ nsDNSService::Init() + + // Monitor these to see if there is a change in proxy configuration + // If a manual proxy is in use, disable prefetch implicitly +- prefs->AddObserver("network.proxy.type", this, false); ++ prefs->AddObserver("network.proxy.", this, false); + } + } + +@@ -448,6 +453,7 @@ nsDNSService::Init() + mIDN = idn; + mIPv4OnlyDomains = ipv4OnlyDomains; // exchanges buffer ownership + mDisableIPv6 = disableIPv6; ++ mDisableDNS = disableDNS; + + // Disable prefetching either by explicit preference or if a manual proxy is configured + mDisablePrefetch = disablePrefetch || (proxyType == nsIProtocolProxyService::PROXYCONFIG_MANUAL); +@@ -547,6 +553,14 @@ nsDNSService::AsyncResolve(const nsACString &hostname, + if (mDisablePrefetch && (flags & RESOLVE_SPECULATE)) + return NS_ERROR_DNS_LOOKUP_QUEUE_FULL; + ++ PRNetAddr tempAddr; ++ if (mDisableDNS) { ++ // Allow IP lookups through, but nothing else. ++ if (PR_StringToNetAddr(hostname.BeginReading(), &tempAddr) != PR_SUCCESS) { ++ return NS_ERROR_UNKNOWN_PROXY_HOST; // XXX: NS_ERROR_NOT_IMPLEMENTED? ++ } ++ } ++ + res = mResolver; + idn = mIDN; + } +@@ -597,6 +611,14 @@ nsDNSService::Resolve(const nsACString &hostname, + MutexAutoLock lock(mLock); + res = mResolver; + idn = mIDN; ++ ++ PRNetAddr tempAddr; ++ if (mDisableDNS) { ++ // Allow IP lookups through, but nothing else. ++ if (PR_StringToNetAddr(hostname.BeginReading(), &tempAddr) != PR_SUCCESS) { ++ return NS_ERROR_UNKNOWN_PROXY_HOST; // XXX: NS_ERROR_NOT_IMPLEMENTED? ++ } ++ } + } + NS_ENSURE_TRUE(res, NS_ERROR_OFFLINE); + +diff --git a/netwerk/dns/nsDNSService2.h b/netwerk/dns/nsDNSService2.h +index 1749b41..3ec8eba 100644 +--- a/netwerk/dns/nsDNSService2.h ++++ b/netwerk/dns/nsDNSService2.h +@@ -70,4 +70,5 @@ private: + bool mDisableIPv6; + bool mDisablePrefetch; + bool mFirstTime; ++ bool mDisableDNS; + }; +diff --git a/netwerk/protocol/websocket/WebSocketChannel.cpp b/netwerk/protocol/websocket/WebSocketChannel.cpp +index 9e446e9..42aa6ca 100644 +--- a/netwerk/protocol/websocket/WebSocketChannel.cpp ++++ b/netwerk/protocol/websocket/WebSocketChannel.cpp +@@ -1698,8 +1698,12 @@ WebSocketChannel::ApplyForAdmission() + LOG(("WebSocketChannel::ApplyForAdmission: checking for concurrent open\n")); + nsCOMPtr<nsIThread> mainThread; + NS_GetMainThread(getter_AddRefs(mainThread)); +- dns->AsyncResolve(hostName, 0, this, mainThread, getter_AddRefs(mDNSRequest)); +- NS_ENSURE_SUCCESS(rv, rv); ++ rv = dns->AsyncResolve(hostName, 0, this, mainThread, getter_AddRefs(mDNSRequest)); ++ if (NS_FAILED(rv)) { ++ // Fall back to hostname on dispatch failure ++ mDNSRequest = nsnull; ++ OnLookupComplete(nsnull, nsnull, rv); ++ } + + return NS_OK; + } +-- +1.7.5.4 + diff --git a/src/current-patches/firefox/0017-Randomize-HTTP-request-order-and-pipeline-depth.patch b/src/current-patches/firefox/0017-Randomize-HTTP-request-order-and-pipeline-depth.patch new file mode 100644 index 0000000..f1814e7 --- /dev/null +++ b/src/current-patches/firefox/0017-Randomize-HTTP-request-order-and-pipeline-depth.patch @@ -0,0 +1,251 @@ +From 36f826e64411a74912ba1adebd1a30b84716bf84 Mon Sep 17 00:00:00 2001 +From: Mike Perry mikeperry-git@torproject.org +Date: Wed, 6 Jun 2012 11:08:56 -0700 +Subject: [PATCH 17/24] Randomize HTTP request order and pipeline depth. + +This is an experimental defense against +http://lorre.uni.lu/~andriy/papers/acmccs-wpes11-fingerprinting.pdf + +See: +https://blog.torproject.org/blog/experimental-defense-website-traffic-finger... + +This defense has been improved since that blog post to additionally randomize +the order and concurrency of non-pipelined HTTP requests. +--- + netwerk/protocol/http/nsHttpConnectionMgr.cpp | 136 ++++++++++++++++++++++++- + netwerk/protocol/http/nsHttpConnectionMgr.h | 5 + + 2 files changed, 136 insertions(+), 5 deletions(-) + +diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.cpp b/netwerk/protocol/http/nsHttpConnectionMgr.cpp +index 23ef893..788368f 100644 +--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp ++++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp +@@ -94,6 +94,12 @@ nsHttpConnectionMgr::nsHttpConnectionMgr() + { + LOG(("Creating nsHttpConnectionMgr @%x\n", this)); + mCT.Init(); ++ ++ nsresult rv; ++ mRandomGenerator = do_GetService("@mozilla.org/security/random-generator;1", &rv); ++ if (NS_FAILED(rv)) { ++ mRandomGenerator = nsnull; ++ } + } + + nsHttpConnectionMgr::~nsHttpConnectionMgr() +@@ -342,8 +348,12 @@ nsHttpConnectionMgr::AddTransactionToPipeline(nsHttpPipeline *pipeline) + nsConnectionEntry *ent = mCT.Get(ci->HashKey()); + if (ent) { + // search for another request to pipeline... +- PRInt32 i, count = ent->mPendingQ.Length(); +- for (i=0; i<count; ++i) { ++ PRInt32 i, h, count = ent->mPendingQ.Length(); ++ PRInt32* ind = new PRInt32[count]; ++ ShuffleRequestOrder((PRUint32*)ind, (PRUint32)count); ++ ++ for (h=0; h<count; ++h) { ++ i = ind[h]; // random request sequence + nsHttpTransaction *trans = ent->mPendingQ[i]; + if (trans->Caps() & NS_HTTP_ALLOW_PIPELINING) { + pipeline->AddTransaction(trans); +@@ -354,6 +364,8 @@ nsHttpConnectionMgr::AddTransactionToPipeline(nsHttpPipeline *pipeline) + break; + } + } ++ ++ delete [] ind; + } + } + } +@@ -585,12 +597,17 @@ nsHttpConnectionMgr::ProcessPendingQForEntry(nsConnectionEntry *ent) + LOG(("nsHttpConnectionMgr::ProcessPendingQForEntry [ci=%s]\n", + ent->mConnInfo->HashKey().get())); + +- PRInt32 i, count = ent->mPendingQ.Length(); ++ PRUint32 h, i = 0, count = ent->mPendingQ.Length(); + if (count > 0) { + LOG((" pending-count=%u\n", count)); + nsHttpTransaction *trans = nsnull; + nsHttpConnection *conn = nsnull; +- for (i=0; i<count; ++i) { ++ ++ PRUint32* ind = new PRUint32[count]; ++ ShuffleRequestOrder(ind, count); ++ ++ for (h=0; h<count; ++h) { ++ i = ind[h]; // random request sequence + trans = ent->mPendingQ[i]; + + // When this transaction has already established a half-open +@@ -610,6 +627,7 @@ nsHttpConnectionMgr::ProcessPendingQForEntry(nsConnectionEntry *ent) + if (conn) + break; + } ++ delete [] ind; + if (conn) { + LOG((" dispatching pending transaction...\n")); + +@@ -694,6 +712,19 @@ nsHttpConnectionMgr::AtActiveConnectionLimit(nsConnectionEntry *ent, PRUint8 cap + maxPersistConns = mMaxPersistConnsPerHost; + } + ++ // Fuzz maxConns for website fingerprinting attack ++ // We create a range of maxConns/5 up to 6*maxConns/5 ++ // because this function is called repeatedly, and we'll ++ // end up converging to the high side of concurrent connections ++ // after a short while. ++ PRUint8 *bytes = nsnull; ++ nsresult rv = mRandomGenerator->GenerateRandomBytes(1, &bytes); ++ NS_ENSURE_SUCCESS(rv, rv); ++ ++ bytes[0] = bytes[0] % (maxConns + 1); ++ maxConns = (maxConns/5) + bytes[0]; ++ NS_Free(bytes); ++ + // use >= just to be safe + return (totalCount >= maxConns) || ( (caps & NS_HTTP_ALLOW_KEEPALIVE) && + (persistCount >= maxPersistConns) ); +@@ -865,7 +896,7 @@ nsHttpConnectionMgr::DispatchTransaction(nsConnectionEntry *ent, + nsHttpPipeline *pipeline = nsnull; + if (conn->SupportsPipelining() && (caps & NS_HTTP_ALLOW_PIPELINING)) { + LOG((" looking to build pipeline...\n")); +- if (BuildPipeline(ent, trans, &pipeline)) ++ if (BuildRandomizedPipeline(ent, trans, &pipeline)) + trans = pipeline; + } + +@@ -938,6 +969,101 @@ nsHttpConnectionMgr::BuildPipeline(nsConnectionEntry *ent, + return true; + } + ++ ++// Generate a shuffled request ordering sequence ++void ++nsHttpConnectionMgr::ShuffleRequestOrder(PRUint32 *ind, PRUint32 count) ++{ ++ PRUint32 i; ++ PRUint32 *rints; ++ ++ for (i=0; i<count; ++i) { ++ ind[i] = i; ++ } ++ nsresult rv = mRandomGenerator->GenerateRandomBytes(sizeof(PRUint32)*count, ++ (PRUint8**)&rints); ++ if (NS_FAILED(rv)) ++ return; // Leave unshuffled if error ++ ++ for (i=0; i < count; ++i) { ++ PRInt32 temp = ind[i]; ++ ind[i] = ind[rints[i]%count]; ++ ind[rints[i]%count] = temp; ++ } ++ NS_Free(rints); ++} ++ ++bool ++nsHttpConnectionMgr::BuildRandomizedPipeline(nsConnectionEntry *ent, ++ nsAHttpTransaction *firstTrans, ++ nsHttpPipeline **result) ++{ ++ if (mRandomGenerator == nsnull) ++ return BuildPipeline(ent, firstTrans, result); ++ if (mMaxPipelinedRequests < 2) ++ return PR_FALSE; ++ ++ nsresult rv; ++ PRUint8 *bytes = nsnull; ++ ++ nsHttpPipeline *pipeline = nsnull; ++ nsHttpTransaction *trans; ++ ++ PRUint32 i = 0, numAdded = 0, numAllowed = 0; ++ PRUint32 max = 0; ++ ++ while (i < ent->mPendingQ.Length()) { ++ if (ent->mPendingQ[i]->Caps() & NS_HTTP_ALLOW_PIPELINING) ++ numAllowed++; ++ i++; ++ } ++ ++ rv = mRandomGenerator->GenerateRandomBytes(1, &bytes); ++ NS_ENSURE_SUCCESS(rv, rv); ++ // 4...12 ++ max = 4 + (bytes[0] % (mMaxPipelinedRequests + 1)); ++ NS_Free(bytes); ++ ++ while (numAllowed > 0) { ++ rv = mRandomGenerator->GenerateRandomBytes(1, &bytes); ++ NS_ENSURE_SUCCESS(rv, rv); ++ i = bytes[0] % ent->mPendingQ.Length(); ++ NS_Free(bytes); ++ ++ trans = ent->mPendingQ[i]; ++ ++ if (!(ent->mPendingQ[i]->Caps() & NS_HTTP_ALLOW_PIPELINING)) ++ continue; ++ ++ if (numAdded == 0) { ++ pipeline = new nsHttpPipeline; ++ if (!pipeline) ++ return PR_FALSE; ++ pipeline->AddTransaction(firstTrans); ++ numAdded = 1; ++ } ++ pipeline->AddTransaction(trans); ++ ++ // remove transaction from pending queue ++ ent->mPendingQ.RemoveElementAt(i); ++ NS_RELEASE(trans); ++ ++ numAllowed--; ++ ++ if (++numAdded == max) ++ break; ++ } ++ ++ //fprintf(stderr, "Yay!!! pipelined %u/%u transactions\n", numAdded, max); ++ LOG((" pipelined %u/%u transactions\n", numAdded, max)); ++ ++ if (numAdded == 0) ++ return PR_FALSE; ++ ++ NS_ADDREF(*result = pipeline); ++ return PR_TRUE; ++} ++ + nsresult + nsHttpConnectionMgr::ProcessNewTransaction(nsHttpTransaction *trans) + { +diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.h b/netwerk/protocol/http/nsHttpConnectionMgr.h +index cdf21a9..81b282a 100644 +--- a/netwerk/protocol/http/nsHttpConnectionMgr.h ++++ b/netwerk/protocol/http/nsHttpConnectionMgr.h +@@ -51,6 +51,7 @@ + + #include "nsIObserver.h" + #include "nsITimer.h" ++#include "nsIRandomGenerator.h" + + class nsHttpPipeline; + +@@ -276,6 +277,8 @@ private: + nsresult DispatchTransaction(nsConnectionEntry *, nsAHttpTransaction *, + PRUint8 caps, nsHttpConnection *); + bool BuildPipeline(nsConnectionEntry *, nsAHttpTransaction *, nsHttpPipeline **); ++ bool BuildRandomizedPipeline(nsConnectionEntry *, nsAHttpTransaction *, nsHttpPipeline **); ++ void ShuffleRequestOrder(PRUint32 *, PRUint32); + nsresult ProcessNewTransaction(nsHttpTransaction *); + nsresult EnsureSocketThreadTargetIfOnline(); + void ClosePersistentConnections(nsConnectionEntry *ent); +@@ -353,6 +356,8 @@ private: + PRUint64 mTimeOfNextWakeUp; + // Timer for next pruning of dead connections. + nsCOMPtr<nsITimer> mTimer; ++ // Random number generator for reordering HTTP pipeline ++ nsCOMPtr<nsIRandomGenerator> mRandomGenerator; + + // + // the connection table +-- +1.7.5.4 + diff --git a/src/current-patches/firefox/0018-Add-HTTP-auth-headers-before-the-modify-request-obse.patch b/src/current-patches/firefox/0018-Add-HTTP-auth-headers-before-the-modify-request-obse.patch new file mode 100644 index 0000000..46cf611 --- /dev/null +++ b/src/current-patches/firefox/0018-Add-HTTP-auth-headers-before-the-modify-request-obse.patch @@ -0,0 +1,52 @@ +From c1e26c8a294abe426fd6fb84508db6074ef23379 Mon Sep 17 00:00:00 2001 +From: Mike Perry mikeperry-git@fscked.org +Date: Fri, 2 Sep 2011 15:33:20 -0700 +Subject: [PATCH 18/24] Add HTTP auth headers before the modify-request + observer. + +Otherwise, how are we supposed to modify them? + +Thanks to Georg Koppen for spotting both the problem and this fix. +--- + netwerk/protocol/http/nsHttpChannel.cpp | 11 +++++++---- + 1 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp +index 97bd84c..6205d62 100644 +--- a/netwerk/protocol/http/nsHttpChannel.cpp ++++ b/netwerk/protocol/http/nsHttpChannel.cpp +@@ -316,9 +316,6 @@ nsHttpChannel::Connect(bool firstTime) + return NS_ERROR_DOCUMENT_NOT_CACHED; + } + +- // check to see if authorization headers should be included +- mAuthProvider->AddAuthorizationHeaders(); +- + if (mLoadFlags & LOAD_NO_NETWORK_IO) { + return NS_ERROR_DOCUMENT_NOT_CACHED; + } +@@ -3707,6 +3704,9 @@ nsHttpChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *context) + + AddCookiesToRequest(); + ++ // check to see if authorization headers should be included ++ mAuthProvider->AddAuthorizationHeaders(); ++ + // notify "http-on-modify-request" observers + gHttpHandler->OnModifyRequest(this); + +@@ -4817,7 +4817,10 @@ nsHttpChannel::DoAuthRetry(nsAHttpConnection *conn) + // this authentication attempt (bug 84794). + // TODO: save cookies from auth response and send them here (bug 572151). + AddCookiesToRequest(); +- ++ ++ // check to see if authorization headers should be included ++ mAuthProvider->AddAuthorizationHeaders(); ++ + // notify "http-on-modify-request" observers + gHttpHandler->OnModifyRequest(this); + +-- +1.7.5.4 + diff --git a/src/current-patches/firefox/0019-Adapt-Steven-Michaud-s-Mac-crashfix-patch.patch b/src/current-patches/firefox/0019-Adapt-Steven-Michaud-s-Mac-crashfix-patch.patch new file mode 100644 index 0000000..7f3869c --- /dev/null +++ b/src/current-patches/firefox/0019-Adapt-Steven-Michaud-s-Mac-crashfix-patch.patch @@ -0,0 +1,532 @@ +From 49cccdba3e6fc10e0e376d423b3ba1b6135f62e1 Mon Sep 17 00:00:00 2001 +From: Mike Perry mikeperry-git@torproject.org +Date: Thu, 7 Jun 2012 16:25:48 -0700 +Subject: [PATCH 19/24] Adapt Steven Michaud's Mac crashfix patch + +Source is: https://bugzilla.mozilla.org/show_bug.cgi?id=715885#c35 + +Some minor tweaks were needed to get it to apply and to compile on +MacOS. +--- + widget/public/Makefile.in | 2 + + widget/public/nsIDragService.idl | 1 - + widget/public/nsPIDragService.idl | 48 ++++++++++++++++++++++++++++ + widget/public/nsPIDragServiceWindows.idl | 46 ++++++++++++++++++++++++++ + widget/src/cocoa/nsChildView.mm | 35 +++++++++++++------- + widget/src/gtk2/nsDragService.cpp | 2 +- + widget/src/gtk2/nsWindow.cpp | 2 +- + widget/src/qt/nsDragService.h | 2 + + widget/src/windows/Makefile.in | 1 - + widget/src/windows/nsDragService.cpp | 13 +++++--- + widget/src/windows/nsDragService.h | 12 +++--- + widget/src/windows/nsNativeDragSource.cpp | 7 ++-- + widget/src/windows/nsNativeDragTarget.cpp | 28 ++++++++++------ + widget/src/xpwidgets/nsBaseDragService.cpp | 16 +++++++++- + widget/src/xpwidgets/nsBaseDragService.h | 9 ++--- + 15 files changed, 176 insertions(+), 48 deletions(-) + create mode 100644 widget/public/nsPIDragService.idl + create mode 100644 widget/public/nsPIDragServiceWindows.idl + +diff --git a/widget/public/Makefile.in b/widget/public/Makefile.in +index a70e65a..8a9b73d 100644 +--- a/widget/public/Makefile.in ++++ b/widget/public/Makefile.in +@@ -110,6 +110,8 @@ XPIDLSRCS = \ + nsIClipboardDragDropHooks.idl \ + nsIClipboardDragDropHookList.idl \ + nsIDragSession.idl \ ++ nsPIDragService.idl \ ++ nsPIDragServiceWindows.idl \ + nsIDragService.idl \ + nsIFormatConverter.idl \ + nsIClipboard.idl \ +diff --git a/widget/public/nsIDragService.idl b/widget/public/nsIDragService.idl +index 6863a88..c4a1e26 100644 +--- a/widget/public/nsIDragService.idl ++++ b/widget/public/nsIDragService.idl +@@ -146,7 +146,6 @@ interface nsIDragService : nsISupports + void suppress(); + void unsuppress(); + +- [noscript] void dragMoved(in long aX, in long aY); + }; + + +diff --git a/widget/public/nsPIDragService.idl b/widget/public/nsPIDragService.idl +new file mode 100644 +index 0000000..93a144d +--- /dev/null ++++ b/widget/public/nsPIDragService.idl +@@ -0,0 +1,48 @@ ++/* ***** 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 mozilla.org code. ++ * ++ * The Initial Developer of the Original Code is ++ * The Mozilla Foundation. ++ * Portions created by the Initial Developer are Copyright (C) 2012 ++ * the Initial Developer. All Rights Reserved. ++ * ++ * Contributor(s): ++ * Steven Michaud smichaud@pobox.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 ***** */ ++ ++#include "nsISupports.idl" ++ ++[scriptable, uuid(FAD8C90B-8E1D-446A-9B6C-241486A85CBD)] ++interface nsPIDragService : nsISupports ++{ ++ void dragMoved(in long aX, in long aY); ++ ++ PRUint16 getInputSource(); ++ ++ void setDragEndPoint(in long aX, in long aY); ++}; +diff --git a/widget/public/nsPIDragServiceWindows.idl b/widget/public/nsPIDragServiceWindows.idl +new file mode 100644 +index 0000000..c8a46dd +--- /dev/null ++++ b/widget/public/nsPIDragServiceWindows.idl +@@ -0,0 +1,46 @@ ++/* ***** 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 mozilla.org code. ++ * ++ * The Initial Developer of the Original Code is ++ * The Mozilla Foundation. ++ * Portions created by the Initial Developer are Copyright (C) 2012 ++ * the Initial Developer. All Rights Reserved. ++ * ++ * Contributor(s): ++ * Steven Michaud smichaud@pobox.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 ***** */ ++ ++#include "nsISupports.idl" ++ ++[scriptable, uuid(6FC2117D-5EB4-441A-9C12-62A783BEBC0C)] ++interface nsPIDragServiceWindows : nsISupports ++{ ++ void setIDataObject(in nsISupports aDataObj); ++ ++ void setDroppedLocal(); ++}; +diff --git a/widget/src/cocoa/nsChildView.mm b/widget/src/cocoa/nsChildView.mm +index 64336e3..b2ab6bc 100644 +--- a/widget/src/cocoa/nsChildView.mm ++++ b/widget/src/cocoa/nsChildView.mm +@@ -4513,11 +4513,12 @@ NSEvent* gLastDragMouseDownEvent = nil; + if (!dragService) { + dragService = do_GetService(kDragServiceContractID); + } ++ nsCOMPtr<nsPIDragService> dragServicePriv = do_QueryInterface(dragService); + + if (dragService) { + NSPoint pnt = [NSEvent mouseLocation]; + FlipCocoaScreenCoordinate(pnt); +- dragService->DragMoved(NSToIntRound(pnt.x), NSToIntRound(pnt.y)); ++ dragServicePriv->DragMoved(NSToIntRound(pnt.x), NSToIntRound(pnt.y)); + } + } + +@@ -4538,11 +4539,13 @@ NSEvent* gLastDragMouseDownEvent = nil; + } + + if (mDragService) { +- // set the dragend point from the current mouse location +- nsDragService* dragService = static_cast<nsDragService *>(mDragService); +- NSPoint pnt = [NSEvent mouseLocation]; +- FlipCocoaScreenCoordinate(pnt); +- dragService->SetDragEndPoint(nsIntPoint(NSToIntRound(pnt.x), NSToIntRound(pnt.y))); ++ nsCOMPtr<nsPIDragService> dragServicePriv = do_QueryInterface(mDragService); ++ if (dragServicePriv) { ++ // set the dragend point from the current mouse location ++ NSPoint pnt = [NSEvent mouseLocation]; ++ FlipCocoaScreenCoordinate(pnt); ++ dragServicePriv->SetDragEndPoint(NSToIntRound(pnt.x), NSToIntRound(pnt.y)); ++ } + + // XXX: dropEffect should be updated per |operation|. + // As things stand though, |operation| isn't well handled within "our" +@@ -4553,13 +4556,19 @@ NSEvent* gLastDragMouseDownEvent = nil; + // value for NSDragOperationGeneric that is passed by other applications. + // All that said, NSDragOperationNone is still reliable. + if (operation == NSDragOperationNone) { +- nsCOMPtr<nsIDOMDataTransfer> dataTransfer; +- dragService->GetDataTransfer(getter_AddRefs(dataTransfer)); +- nsCOMPtr<nsIDOMNSDataTransfer> dataTransferNS = +- do_QueryInterface(dataTransfer); +- +- if (dataTransferNS) +- dataTransferNS->SetDropEffectInt(nsIDragService::DRAGDROP_ACTION_NONE); ++ nsCOMPtr<nsIDragSession> dragSession; ++ mDragService->GetCurrentSession(getter_AddRefs(dragSession)); ++ if (dragSession) { ++ nsCOMPtr<nsIDOMDataTransfer> dataTransfer; ++ dragSession->GetDataTransfer(getter_AddRefs(dataTransfer)); ++ if (dataTransfer) { ++ nsCOMPtr<nsIDOMNSDataTransfer> dataTransferNS = ++ do_QueryInterface(dataTransfer); ++ if (dataTransferNS) { ++ dataTransferNS->SetDropEffectInt(nsIDragService::DRAGDROP_ACTION_NONE); ++ } ++ } ++ } + } + + mDragService->EndDragSession(true); +diff --git a/widget/src/gtk2/nsDragService.cpp b/widget/src/gtk2/nsDragService.cpp +index ca5a42c..876fd55 100644 +--- a/widget/src/gtk2/nsDragService.cpp ++++ b/widget/src/gtk2/nsDragService.cpp +@@ -1334,7 +1334,7 @@ nsDragService::SourceEndDragSession(GdkDragContext *aContext, + GdkDisplay* display = gdk_display_get_default(); + if (display) { + gdk_display_get_pointer(display, NULL, &x, &y, NULL); +- SetDragEndPoint(nsIntPoint(x, y)); ++ SetDragEndPoint(x, y); + } + + // Either the drag was aborted or the drop occurred outside the app. +diff --git a/widget/src/gtk2/nsWindow.cpp b/widget/src/gtk2/nsWindow.cpp +index 2fd6f64..a2e27e1 100644 +--- a/widget/src/gtk2/nsWindow.cpp ++++ b/widget/src/gtk2/nsWindow.cpp +@@ -3738,7 +3738,7 @@ nsWindow::OnDragDropEvent(GtkWidget *aWidget, + if (display) { + // get the current cursor position + gdk_display_get_pointer(display, NULL, &x, &y, NULL); +- ((nsDragService *)dragService.get())->SetDragEndPoint(nsIntPoint(x, y)); ++ ((nsDragService *)dragService.get())->SetDragEndPoint(x, y); + } + dragService->EndDragSession(true); + +diff --git a/widget/src/qt/nsDragService.h b/widget/src/qt/nsDragService.h +index 5a3e5bb..50dcfac 100644 +--- a/widget/src/qt/nsDragService.h ++++ b/widget/src/qt/nsDragService.h +@@ -50,6 +50,8 @@ public: + NS_DECL_ISUPPORTS + NS_DECL_NSIDRAGSERVICE + ++ NS_IMETHOD DragMoved(PRInt32 aX, PRInt32 aY); ++ + nsDragService(); + + private: +diff --git a/widget/src/windows/Makefile.in b/widget/src/windows/Makefile.in +index 53277ea..d7ff7ce 100644 +--- a/widget/src/windows/Makefile.in ++++ b/widget/src/windows/Makefile.in +@@ -115,7 +115,6 @@ ifdef MOZ_ENABLE_D3D10_LAYER + DEFINES += -DMOZ_ENABLE_D3D10_LAYER + endif + +- + EXPORTS = nsdefs.h WindowHook.h + EXPORTS_NAMESPACES = mozilla/widget + EXPORTS_mozilla/widget = AudioSession.h +diff --git a/widget/src/windows/nsDragService.cpp b/widget/src/windows/nsDragService.cpp +index 2dcede3..3d8af21 100644 +--- a/widget/src/windows/nsDragService.cpp ++++ b/widget/src/windows/nsDragService.cpp +@@ -97,6 +97,8 @@ nsDragService::~nsDragService() + NS_IF_RELEASE(mDataObject); + } + ++NS_IMPL_ISUPPORTS_INHERITED1(nsDragService, nsBaseDragService, nsPIDragServiceWindows) ++ + bool + nsDragService::CreateDragImage(nsIDOMNode *aDOMNode, + nsIScriptableRegion *aRegion, +@@ -350,7 +352,7 @@ nsDragService::StartInvokingDragSession(IDataObject * aDataObj, + POINT cpos; + cpos.x = GET_X_LPARAM(pos); + cpos.y = GET_Y_LPARAM(pos); +- SetDragEndPoint(nsIntPoint(cpos.x, cpos.y)); ++ SetDragEndPoint(cpos.x, cpos.y); + EndDragSession(true); + + mDoingDrag = false; +@@ -468,25 +470,26 @@ nsDragService::GetData(nsITransferable * aTransferable, PRUint32 anItem) + + //--------------------------------------------------------- + NS_IMETHODIMP +-nsDragService::SetIDataObject(IDataObject * aDataObj) ++nsDragService::SetIDataObject(nsISupports * aDataObj) + { ++ IDataObject *dataObj = (IDataObject*) aDataObj; + // When the native drag starts the DragService gets + // the IDataObject that is being dragged + NS_IF_RELEASE(mDataObject); +- mDataObject = aDataObj; ++ mDataObject = dataObj; + NS_IF_ADDREF(mDataObject); + + return NS_OK; + } + + //--------------------------------------------------------- +-void ++NS_IMETHODIMP + nsDragService::SetDroppedLocal() + { + // Sent from the native drag handler, letting us know + // a drop occurred within the application vs. outside of it. + mSentLocalDropEvent = true; +- return; ++ return NS_OK; + } + + //------------------------------------------------------------------------- +diff --git a/widget/src/windows/nsDragService.h b/widget/src/windows/nsDragService.h +index 067bcf2..2699e47 100644 +--- a/widget/src/windows/nsDragService.h ++++ b/widget/src/windows/nsDragService.h +@@ -39,6 +39,7 @@ + #define nsDragService_h__ + + #include "nsBaseDragService.h" ++#include "nsPIDragServiceWindows.h" + #include <windows.h> + #include <shlobj.h> + +@@ -52,12 +53,15 @@ class nsString; + * Native Win32 DragService wrapper + */ + +-class nsDragService : public nsBaseDragService ++class nsDragService : public nsBaseDragService, public nsPIDragServiceWindows + { + public: + nsDragService(); + virtual ~nsDragService(); +- ++ ++ NS_DECL_ISUPPORTS_INHERITED ++ NS_DECL_NSPIDRAGSERVICEWINDOWS ++ + // nsIDragService + NS_IMETHOD InvokeDragSession(nsIDOMNode *aDOMNode, + nsISupportsArray *anArrayTransferables, +@@ -71,13 +75,9 @@ public: + NS_IMETHOD EndDragSession(bool aDoneDrag); + + // native impl. +- NS_IMETHOD SetIDataObject(IDataObject * aDataObj); + NS_IMETHOD StartInvokingDragSession(IDataObject * aDataObj, + PRUint32 aActionType); + +- // A drop occurred within the application vs. outside of it. +- void SetDroppedLocal(); +- + protected: + nsDataObjCollection* GetDataObjCollection(IDataObject * aDataObj); + +diff --git a/widget/src/windows/nsNativeDragSource.cpp b/widget/src/windows/nsNativeDragSource.cpp +index e51101e..0fe6ffe 100644 +--- a/widget/src/windows/nsNativeDragSource.cpp ++++ b/widget/src/windows/nsNativeDragSource.cpp +@@ -42,7 +42,7 @@ + #include "nsIServiceManager.h" + #include "nsToolkit.h" + #include "nsWidgetsCID.h" +-#include "nsIDragService.h" ++#include "nsDragService.h" + + static NS_DEFINE_IID(kCDragServiceCID, NS_DRAGSERVICE_CID); + +@@ -101,9 +101,10 @@ STDMETHODIMP + nsNativeDragSource::QueryContinueDrag(BOOL fEsc, DWORD grfKeyState) + { + nsCOMPtr<nsIDragService> dragService = do_GetService(kCDragServiceCID); +- if (dragService) { ++ nsCOMPtr<nsPIDragService> dragServicePriv = do_QueryInterface(dragService); ++ if (dragServicePriv) { + DWORD pos = ::GetMessagePos(); +- dragService->DragMoved(GET_X_LPARAM(pos), GET_Y_LPARAM(pos)); ++ dragServicePriv->DragMoved(GET_X_LPARAM(pos), GET_Y_LPARAM(pos)); + } + + if (fEsc) { +diff --git a/widget/src/windows/nsNativeDragTarget.cpp b/widget/src/windows/nsNativeDragTarget.cpp +index cf6196b..82ad3c6 100644 +--- a/widget/src/windows/nsNativeDragTarget.cpp ++++ b/widget/src/windows/nsNativeDragTarget.cpp +@@ -209,7 +209,11 @@ nsNativeDragTarget::DispatchDragDropEvent(PRUint32 aEventType, POINTL aPT) + event.isControl = IsKeyDown(NS_VK_CONTROL); + event.isMeta = false; + event.isAlt = IsKeyDown(NS_VK_ALT); +- event.inputSource = static_cast<nsBaseDragService*>(mDragService)->GetInputSource(); ++ event.inputSource = 0; ++ nsCOMPtr<nsPIDragService> dragServicePriv = do_QueryInterface(mDragService); ++ if (dragServicePriv) { ++ dragServicePriv->GetInputSource(&event.inputSource); ++ } + + mWindow->DispatchEvent(&event, status); + } +@@ -296,9 +300,8 @@ nsNativeDragTarget::DragEnter(LPDATAOBJECT pIDataSource, + // This cast is ok because in the constructor we created a + // the actual implementation we wanted, so we know this is + // a nsDragService. It should be a private interface, though. +- nsDragService * winDragService = +- static_cast<nsDragService *>(mDragService); +- winDragService->SetIDataObject(pIDataSource); ++ nsCOMPtr<nsPIDragServiceWindows> winDragService = do_QueryInterface(mDragService); ++ winDragService->SetIDataObject((nsISupports*)pIDataSource); + + // Now process the native drag state and then dispatch the event + ProcessDrag(NS_DRAGDROP_ENTER, grfKeyState, ptl, pdwEffect); +@@ -436,8 +439,8 @@ nsNativeDragTarget::Drop(LPDATAOBJECT pData, + // This cast is ok because in the constructor we created a + // the actual implementation we wanted, so we know this is + // a nsDragService (but it should still be a private interface) +- nsDragService* winDragService = static_cast<nsDragService*>(mDragService); +- winDragService->SetIDataObject(pData); ++ nsCOMPtr<nsPIDragServiceWindows> winDragService = do_QueryInterface(mDragService); ++ winDragService->SetIDataObject((nsISupports*)pData); + + // NOTE: ProcessDrag spins the event loop which may destroy arbitrary objects. + // We use strong refs to prevent it from destroying these: +@@ -461,11 +464,14 @@ nsNativeDragTarget::Drop(LPDATAOBJECT pData, + // tell the drag service we're done with the session + // Use GetMessagePos to get the position of the mouse at the last message + // seen by the event loop. (Bug 489729) +- DWORD pos = ::GetMessagePos(); +- POINT cpos; +- cpos.x = GET_X_LPARAM(pos); +- cpos.y = GET_Y_LPARAM(pos); +- winDragService->SetDragEndPoint(nsIntPoint(cpos.x, cpos.y)); ++ nsCOMPtr<nsPIDragService> dragServicePriv = do_QueryInterface(mDragService); ++ if (dragServicePriv) { ++ DWORD pos = ::GetMessagePos(); ++ POINT cpos; ++ cpos.x = GET_X_LPARAM(pos); ++ cpos.y = GET_Y_LPARAM(pos); ++ dragServicePriv->SetDragEndPoint(cpos.x, cpos.y); ++ } + serv->EndDragSession(true); + + // release the ref that was taken in DragEnter +diff --git a/widget/src/xpwidgets/nsBaseDragService.cpp b/widget/src/xpwidgets/nsBaseDragService.cpp +index 52efb7e..1c35673 100644 +--- a/widget/src/xpwidgets/nsBaseDragService.cpp ++++ b/widget/src/xpwidgets/nsBaseDragService.cpp +@@ -89,7 +89,7 @@ nsBaseDragService::~nsBaseDragService() + { + } + +-NS_IMPL_ISUPPORTS2(nsBaseDragService, nsIDragService, nsIDragSession) ++NS_IMPL_ISUPPORTS3(nsBaseDragService, nsIDragService, nsPIDragService, nsIDragSession) + + //--------------------------------------------------------- + NS_IMETHODIMP +@@ -443,6 +443,20 @@ nsBaseDragService::DragMoved(PRInt32 aX, PRInt32 aY) + return NS_OK; + } + ++NS_IMETHODIMP ++nsBaseDragService::SetDragEndPoint(PRInt32 aX, PRInt32 aY) ++{ ++ mEndDragPoint = nsIntPoint(aX, aY); ++ return NS_OK; ++} ++ ++NS_IMETHODIMP ++nsBaseDragService::GetInputSource(PRUint16* aInputSource) ++{ ++ *aInputSource = mInputSource; ++ return NS_OK; ++} ++ + static nsIPresShell* + GetPresShellForContent(nsIDOMNode* aDOMNode) + { +diff --git a/widget/src/xpwidgets/nsBaseDragService.h b/widget/src/xpwidgets/nsBaseDragService.h +index 290c0cb..2ceac2b 100644 +--- a/widget/src/xpwidgets/nsBaseDragService.h ++++ b/widget/src/xpwidgets/nsBaseDragService.h +@@ -39,6 +39,7 @@ + #define nsBaseDragService_h__ + + #include "nsIDragService.h" ++#include "nsPIDragService.h" + #include "nsIDragSession.h" + #include "nsITransferable.h" + #include "nsISupportsArray.h" +@@ -64,6 +65,7 @@ class nsICanvasElementExternal; + */ + + class nsBaseDragService : public nsIDragService, ++ public nsPIDragService, + public nsIDragSession + { + +@@ -74,14 +76,11 @@ public: + //nsISupports + NS_DECL_ISUPPORTS + +- //nsIDragSession and nsIDragService ++ //nsIDragSession, nsIDragService and nsPIDragService + NS_DECL_NSIDRAGSERVICE ++ NS_DECL_NSPIDRAGSERVICE + NS_DECL_NSIDRAGSESSION + +- void SetDragEndPoint(nsIntPoint aEndDragPoint) { mEndDragPoint = aEndDragPoint; } +- +- PRUint16 GetInputSource() { return mInputSource; } +- + protected: + + /** +-- +1.7.5.4 + diff --git a/src/current-patches/firefox/0020-Add-mozIThirdPartyUtil.getFirstPartyURI-API.patch b/src/current-patches/firefox/0020-Add-mozIThirdPartyUtil.getFirstPartyURI-API.patch index 56d9848..114301d 100644 --- a/src/current-patches/firefox/0020-Add-mozIThirdPartyUtil.getFirstPartyURI-API.patch +++ b/src/current-patches/firefox/0020-Add-mozIThirdPartyUtil.getFirstPartyURI-API.patch @@ -1,17 +1,17 @@ -From 73e548ceee36b99f06e33010163ed8b8cc86b3dd Mon Sep 17 00:00:00 2001 +From 36d57455893bcf6dc08e91a2784970f285c5e84b Mon Sep 17 00:00:00 2001 From: Mike Perry mikeperry-git@torproject.org Date: Tue, 28 Aug 2012 18:35:33 -0700 -Subject: [PATCH 20/20] Add mozIThirdPartyUtil.getFirstPartyURI API +Subject: [PATCH 20/24] Add mozIThirdPartyUtil.getFirstPartyURI API
API allows you to get the url bar URI for a channel or nsIDocument. --- - content/base/src/ThirdPartyUtil.cpp | 52 ++++++++++++++++++++++++++++ + content/base/src/ThirdPartyUtil.cpp | 59 ++++++++++++++++++++++++++++ content/base/src/ThirdPartyUtil.h | 2 + - netwerk/base/public/mozIThirdPartyUtil.idl | 21 +++++++++++ - 3 files changed, 75 insertions(+), 0 deletions(-) + netwerk/base/public/mozIThirdPartyUtil.idl | 21 ++++++++++ + 3 files changed, 82 insertions(+), 0 deletions(-)
diff --git a/content/base/src/ThirdPartyUtil.cpp b/content/base/src/ThirdPartyUtil.cpp -index 6a415e9..62333f3 100644 +index 6a415e9..52b3dab 100644 --- a/content/base/src/ThirdPartyUtil.cpp +++ b/content/base/src/ThirdPartyUtil.cpp @@ -40,6 +40,9 @@ @@ -32,7 +32,7 @@ index 6a415e9..62333f3 100644 return rv; }
-@@ -315,3 +319,51 @@ ThirdPartyUtil::GetBaseDomain(nsIURI* aHostURI, +@@ -315,3 +319,58 @@ ThirdPartyUtil::GetBaseDomain(nsIURI* aHostURI,
return NS_OK; } @@ -62,12 +62,19 @@ index 6a415e9..62333f3 100644 + if (NS_FAILED(rv) && aDoc) { + nsCOMPtr<nsIDOMWindow> top; + nsCOMPtr<nsIDOMDocument> topDDoc; -+ -+ aDoc->GetWindow()->GetTop(getter_AddRefs(top)); -+ top->GetDocument(getter_AddRefs(topDDoc)); ++ ++ if (aDoc->GetWindow()) { ++ aDoc->GetWindow()->GetTop(getter_AddRefs(top)); ++ top->GetDocument(getter_AddRefs(topDDoc)); + -+ nsCOMPtr<nsIDocument> topDoc(do_QueryInterface(topDDoc)); -+ *aOutput = topDoc->GetOriginalURI(); ++ nsCOMPtr<nsIDocument> topDoc(do_QueryInterface(topDDoc)); ++ *aOutput = topDoc->GetOriginalURI(); ++ } else { ++ // XXX: Chrome callers (such as NoScript) can end up here ++ // through getImageData/canvas usage with no document state ++ // (no Window and a document URI of about:blank). Propogate ++ // rv fail (by doing nothing), and hope caller recovers. ++ } + + if (*aOutput) + rv = NS_OK; diff --git a/src/current-patches/firefox/0021-Add-canvas-image-extraction-prompt.patch b/src/current-patches/firefox/0021-Add-canvas-image-extraction-prompt.patch new file mode 100644 index 0000000..cf5dd61 --- /dev/null +++ b/src/current-patches/firefox/0021-Add-canvas-image-extraction-prompt.patch @@ -0,0 +1,551 @@ +From 29ce940434ebbb8e54c0d9b8f84ccf6ec6bd71bc Mon Sep 17 00:00:00 2001 +From: Kathleen Brade brade@pearlcrescent.com +Date: Tue, 9 Oct 2012 11:21:06 -0400 +Subject: [PATCH 21/24] Add canvas image extraction prompt. + +--- + browser/base/content/browser.css | 1 + + browser/base/content/browser.js | 102 ++++++++++++++++++++ + browser/base/content/browser.xul | 1 + + .../en-US/chrome/browser/browser.properties | 7 ++ + browser/themes/gnomestripe/browser/browser.css | 2 + + browser/themes/pinstripe/browser/browser.css | 2 + + browser/themes/winstripe/browser/browser.css | 2 + + content/canvas/src/CanvasUtils.cpp | 63 ++++++++++++ + content/canvas/src/CanvasUtils.h | 2 + + content/canvas/src/nsCanvasRenderingContext2D.cpp | 15 +++ + .../canvas/src/nsCanvasRenderingContext2DAzure.cpp | 15 +++ + content/html/content/public/nsHTMLCanvasElement.h | 3 + + content/html/content/src/Makefile.in | 1 + + content/html/content/src/nsHTMLCanvasElement.cpp | 39 ++++++-- + 14 files changed, 246 insertions(+), 9 deletions(-) + +diff --git a/browser/base/content/browser.css b/browser/base/content/browser.css +index f033c2b..c709631 100644 +--- a/browser/base/content/browser.css ++++ b/browser/base/content/browser.css +@@ -440,6 +440,7 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-m + created with a null anchorID, so in that case use a default anchor icon. */ + #notification-popup-box[anchorid="notification-popup-box"] > #default-notification-icon, + #notification-popup-box[anchorid="geo-notification-icon"] > #geo-notification-icon, ++#notification-popup-box[anchorid="canvas-notification-icon"] > #canvas-notification-icon, + #notification-popup-box[anchorid="indexedDB-notification-icon"] > #indexedDB-notification-icon, + #notification-popup-box[anchorid="addons-notification-icon"] > #addons-notification-icon, + #notification-popup-box[anchorid="password-notification-icon"] > #password-notification-icon { +diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js +index 20e3666..0c6bd46 100644 +--- a/browser/base/content/browser.js ++++ b/browser/base/content/browser.js +@@ -1522,6 +1522,7 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) { + BrowserOffline.init(); + OfflineApps.init(); + IndexedDBPromptHelper.init(); ++ CanvasPermissionPromptHelper.init(); + gFormSubmitObserver.init(); + AddonManager.addAddonListener(AddonsMgrListener); + +@@ -1834,6 +1835,7 @@ function BrowserShutdown() { + BrowserOffline.uninit(); + OfflineApps.uninit(); + IndexedDBPromptHelper.uninit(); ++ CanvasPermissionPromptHelper.uninit(); + AddonManager.removeAddonListener(AddonsMgrListener); + } + +@@ -6656,6 +6658,106 @@ var IndexedDBPromptHelper = { + } + }; + ++var CanvasPermissionPromptHelper = { ++ _permissionsPrompt: "canvas-permissions-prompt", ++ _notificationIcon: "canvas-notification-icon", ++ ++ init: ++ function CanvasPermissionPromptHelper_init() { ++ Services.obs.addObserver(this, this._permissionsPrompt, false); ++ }, ++ ++ uninit: ++ function CanvasPermissionPromptHelper_uninit() { ++ Services.obs.removeObserver(this, this._permissionsPrompt, false); ++ }, ++ ++ // aSubject is an nsIDOMWindow. ++ // aData is an URL string. ++ observe: ++ function CanvasPermissionPromptHelper_observe(aSubject, aTopic, aData) { ++ if ((aTopic != this._permissionsPrompt) || !aData) ++ throw new Error("Unexpected topic or missing URL"); ++ ++ var uri = makeURI(aData); ++ var contentWindow = aSubject.QueryInterface(Ci.nsIDOMWindow); ++ var contentDocument = contentWindow.document; ++ var browserWindow = ++ OfflineApps._getBrowserWindowForContentWindow(contentWindow); ++ ++ if (browserWindow != window) { ++ // Must belong to some other window. ++ return; ++ } ++ ++ // If canvas prompt is already displayed, just return. This is OK (and ++ // more efficient) since this permission is associated with the top ++ // browser's URL. ++ if (PopupNotifications.getNotification(aTopic, browser)) ++ return; ++ ++ var bundleSvc = Cc["@mozilla.org/intl/stringbundle;1"]. ++ getService(Ci.nsIStringBundleService); ++ var torBtnBundle; ++ try { ++ torBtnBundle = bundleSvc.createBundle( ++ "chrome://torbutton/locale/torbutton.properties"); ++ } catch (e) {} ++ ++ var message = getLocalizedString("canvas.siteprompt", [ uri.asciiHost ]); ++ ++ var mainAction = { ++ label: getLocalizedString("canvas.allow"), ++ accessKey: getLocalizedString("canvas.allowAccessKey"), ++ callback: function() { ++ setCanvasPermission(uri, Ci.nsIPermissionManager.ALLOW_ACTION); ++ } ++ }; ++ ++ var secondaryActions = [ ++ { ++ label: getLocalizedString("canvas.never"), ++ accessKey: getLocalizedString("canvas.neverAccessKey"), ++ callback: function() { ++ setCanvasPermission(uri, Ci.nsIPermissionManager.DENY_ACTION); ++ } ++ } ++ ]; ++ ++ // Since we have a process in place to perform localization for the ++ // Torbutton extension, get our strings from the extension if possible. ++ function getLocalizedString(aID, aParams) { ++ var s; ++ if (torBtnBundle) try { ++ if (aParams) ++ s = torBtnBundle.formatStringFromName(aID, aParams, aParams.length); ++ else ++ s = torBtnBundle.GetStringFromName(aID); ++ } catch (e) {} ++ ++ if (!s) { ++ if (aParams) ++ s = gNavigatorBundle.getFormattedString(aID, aParams); ++ else ++ s = gNavigatorBundle.getString(aID); ++ } ++ ++ return s; ++ } ++ ++ function setCanvasPermission(aURI, aPerm) { ++ Services.perms.add(aURI, "canvas/extractData", aPerm, ++ Ci.nsIPermissionManager.EXPIRE_NEVER); ++ } ++ ++ var browser = OfflineApps._getBrowserForContentWindow(browserWindow, ++ contentWindow); ++ notification = PopupNotifications.show(browser, aTopic, message, ++ this._notificationIcon, mainAction, ++ secondaryActions, null); ++ } ++}; ++ + function WindowIsClosing() + { + if (TabView.isVisible()) { +diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul +index ba2a7cb..1acea43 100644 +--- a/browser/base/content/browser.xul ++++ b/browser/base/content/browser.xul +@@ -520,6 +520,7 @@ + <image id="default-notification-icon" class="notification-anchor-icon" role="button"/> + <image id="geo-notification-icon" class="notification-anchor-icon" role="button"/> + <image id="addons-notification-icon" class="notification-anchor-icon" role="button"/> ++ <image id="canvas-notification-icon" class="notification-anchor-icon" role="button"/> + <image id="indexedDB-notification-icon" class="notification-anchor-icon" role="button"/> + <image id="password-notification-icon" class="notification-anchor-icon" role="button"/> + </box> +diff --git a/browser/locales/en-US/chrome/browser/browser.properties b/browser/locales/en-US/chrome/browser/browser.properties +index 380e3c3..98154d1 100644 +--- a/browser/locales/en-US/chrome/browser/browser.properties ++++ b/browser/locales/en-US/chrome/browser/browser.properties +@@ -197,6 +197,13 @@ offlineApps.usage=This website (%S) is now storing more than %SMB of data on you + offlineApps.manageUsage=Show settings + offlineApps.manageUsageAccessKey=S + ++# Canvas permission prompt ++canvas.siteprompt=This website (%S) attempted to access image data on a canvas. Blank (white) image data was returned this time. ++canvas.allow=Allow in the Future ++canvas.allowAccessKey=A ++canvas.never=Never for This Site ++canvas.neverAccessKey=e ++ + # LOCALIZATION NOTE (indexedDB.usage): %1$S is the website host name + # %2$S a number of megabytes. + indexedDB.usage=This website (%1$S) is attempting to store more than %2$S MB of data on your computer for offline use. +diff --git a/browser/themes/gnomestripe/browser/browser.css b/browser/themes/gnomestripe/browser/browser.css +index edc0b72..8ba057e 100644 +--- a/browser/themes/gnomestripe/browser/browser.css ++++ b/browser/themes/gnomestripe/browser/browser.css +@@ -1227,6 +1227,7 @@ toolbar[iconsize="small"] #feed-button { + list-style-image: url("moz-icon://stock/gtk-cancel?size=menu"); + } + ++.popup-notification-icon[popupid="canvas-permissions-prompt"], + .popup-notification-icon[popupid="indexedDB-permissions-prompt"], + .popup-notification-icon[popupid="indexedDB-quota-prompt"] { + list-style-image: url(chrome://global/skin/icons/question-64.png); +@@ -1281,6 +1282,7 @@ toolbar[iconsize="small"] #feed-button { + list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric-16.png); + } + ++#canvas-notification-icon, + #indexedDB-notification-icon { + list-style-image: url(chrome://global/skin/icons/question-16.png); + } +diff --git a/browser/themes/pinstripe/browser/browser.css b/browser/themes/pinstripe/browser/browser.css +index 2a96556..f94a6f2 100644 +--- a/browser/themes/pinstripe/browser/browser.css ++++ b/browser/themes/pinstripe/browser/browser.css +@@ -2404,10 +2404,12 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker { + -moz-image-region: rect(0px, 48px, 16px, 32px); + } + ++#canvas-notification-icon, + #indexedDB-notification-icon { + list-style-image: url(chrome://global/skin/icons/question-16.png); + } + ++.popup-notification-icon[popupid="canvas-permissions-prompt"], + .popup-notification-icon[popupid="indexedDB-permissions-prompt"], + .popup-notification-icon[popupid="indexedDB-quota-prompt"] { + list-style-image: url(chrome://global/skin/icons/question-64.png); +diff --git a/browser/themes/winstripe/browser/browser.css b/browser/themes/winstripe/browser/browser.css +index 0103c79..d352790 100644 +--- a/browser/themes/winstripe/browser/browser.css ++++ b/browser/themes/winstripe/browser/browser.css +@@ -2294,6 +2294,7 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] { + -moz-image-region: rect(32px, 32px, 48px, 16px); + } + ++.popup-notification-icon[popupid="canvas-permissions-prompt"], + .popup-notification-icon[popupid="indexedDB-permissions-prompt"], + .popup-notification-icon[popupid="indexedDB-quota-prompt"] { + list-style-image: url(chrome://global/skin/icons/question-64.png); +@@ -2346,6 +2347,7 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] { + list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric-16.png); + } + ++#canvas-notification-icon, + #indexedDB-notification-icon { + list-style-image: url(chrome://global/skin/icons/question-16.png); + } +diff --git a/content/canvas/src/CanvasUtils.cpp b/content/canvas/src/CanvasUtils.cpp +index 2f822eb..d7d0591 100644 +--- a/content/canvas/src/CanvasUtils.cpp ++++ b/content/canvas/src/CanvasUtils.cpp +@@ -59,6 +59,15 @@ + #include "CanvasUtils.h" + #include "mozilla/gfx/Matrix.h" + ++#include "nsIScriptObjectPrincipal.h" ++#include "nsIPermissionManager.h" ++#include "mozIThirdPartyUtil.h" ++#include "nsContentUtils.h" ++#include "nsUnicharUtils.h" ++ ++#define TOPIC_CANVAS_PERMISSIONS_PROMPT "canvas-permissions-prompt" ++#define PERMISSION_CANVAS_EXTRACT_DATA "canvas/extractData" ++ + namespace mozilla { + namespace CanvasUtils { + +@@ -101,6 +110,60 @@ DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement, + aCanvasElement->SetWriteOnly(); + } + ++// Check site-specific permission and display prompt if appropriate. ++bool ++IsImageExtractionAllowed(nsIDocument *aDocument) ++{ ++ if (!aDocument) ++ return false; ++ ++ nsPIDOMWindow *win = aDocument->GetWindow(); ++ nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(win)); ++ if (sop && nsContentUtils::IsSystemPrincipal(sop->GetPrincipal())) ++ return true; ++ ++ bool isAllowed = false; ++ nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil = ++ do_GetService(THIRDPARTYUTIL_CONTRACTID); ++ nsCOMPtr<nsIPermissionManager> permissionManager = ++ do_GetService(NS_PERMISSIONMANAGER_CONTRACTID); ++ if (thirdPartyUtil && permissionManager) { ++ nsCOMPtr<nsIURI> uri; ++ nsresult rv = thirdPartyUtil->GetFirstPartyURI(NULL, aDocument, ++ getter_AddRefs(uri)); ++ uint32_t permission = nsIPermissionManager::UNKNOWN_ACTION; ++ if (NS_SUCCEEDED(rv)) { ++ // Allow local files to access canvas data; check content permissions ++ // for remote pages. ++ bool isFileURL = false; ++ (void)uri->SchemeIs("file", &isFileURL); ++ if (isFileURL) ++ permission = nsIPermissionManager::ALLOW_ACTION; ++ else { ++ rv = permissionManager->TestPermission(uri, ++ PERMISSION_CANVAS_EXTRACT_DATA, &permission); ++ } ++ } ++ ++ if (NS_SUCCEEDED(rv)) { ++ isAllowed = (permission == nsIPermissionManager::ALLOW_ACTION); ++ ++ if (!isAllowed && (permission != nsIPermissionManager::DENY_ACTION)) { ++ // Send notification so that a prompt is displayed. ++ nsCString spec; ++ rv = uri->GetSpec(spec); ++ NS_ENSURE_SUCCESS(rv, rv); ++ nsCOMPtr<nsIObserverService> obs = ++ mozilla::services::GetObserverService(); ++ obs->NotifyObservers(win, TOPIC_CANVAS_PERMISSIONS_PROMPT, ++ NS_ConvertUTF8toUTF16(spec).get()); ++ } ++ } ++ } ++ ++ return isAllowed; ++} ++ + void + LogMessage (const nsCString& errorString) + { +diff --git a/content/canvas/src/CanvasUtils.h b/content/canvas/src/CanvasUtils.h +index 36186dd..067ee46 100644 +--- a/content/canvas/src/CanvasUtils.h ++++ b/content/canvas/src/CanvasUtils.h +@@ -77,6 +77,8 @@ void DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement, + bool forceWriteOnly, + bool CORSUsed); + ++bool IsImageExtractionAllowed(nsIDocument *aDocument); ++ + void LogMessage (const nsCString& errorString); + void LogMessagef (const char *fmt, ...); + +diff --git a/content/canvas/src/nsCanvasRenderingContext2D.cpp b/content/canvas/src/nsCanvasRenderingContext2D.cpp +index 36389b0..0cf97ce 100644 +--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp ++++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp +@@ -3886,6 +3886,21 @@ nsCanvasRenderingContext2D::GetImageData_explicit(PRInt32 x, PRInt32 y, PRUint32 + if (!rightMost.valid() || !bottomMost.valid()) + return NS_ERROR_DOM_SYNTAX_ERR; + ++ // Check for site-specific permission and return all-white, opaque pixel ++ // data if no permission. This check is not needed if the canvas was ++ // created with a docshell (that is only done for special internal uses). ++ bool usePlaceholder = false; ++ if (mCanvasElement) { ++ nsCOMPtr<nsIDocument> ownerDoc = HTMLCanvasElement()->OwnerDoc(); ++ usePlaceholder = !ownerDoc || ++ !CanvasUtils::IsImageExtractionAllowed(ownerDoc); ++ } ++ ++ if (usePlaceholder) { ++ memset(aData, 0xFF, aDataLen); ++ return NS_OK; ++ } ++ + /* Copy the surface contents to the buffer */ + nsRefPtr<gfxImageSurface> tmpsurf = + new gfxImageSurface(aData, +diff --git a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp +index 13baaa5..e8dfb1e 100644 +--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp ++++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp +@@ -4038,6 +4038,21 @@ nsCanvasRenderingContext2DAzure::GetImageData_explicit(PRInt32 x, PRInt32 y, PRU + return NS_OK; + } + ++ // Check for site-specific permission and return all-white, opaque pixel ++ // data if no permission. This check is not needed if the canvas was ++ // created with a docshell (that is only done for special internal uses). ++ bool usePlaceholder = false; ++ if (mCanvasElement) { ++ nsCOMPtr<nsIDocument> ownerDoc = HTMLCanvasElement()->OwnerDoc(); ++ usePlaceholder = !ownerDoc || ++ !CanvasUtils::IsImageExtractionAllowed(ownerDoc); ++ } ++ ++ if (usePlaceholder) { ++ memset(aData, 0xFF, aDataLen); ++ return NS_OK; ++ } ++ + IntRect srcRect(0, 0, mWidth, mHeight); + IntRect destRect(x, y, w, h); + +diff --git a/content/html/content/public/nsHTMLCanvasElement.h b/content/html/content/public/nsHTMLCanvasElement.h +index 86202a8..66176f2 100644 +--- a/content/html/content/public/nsHTMLCanvasElement.h ++++ b/content/html/content/public/nsHTMLCanvasElement.h +@@ -188,13 +188,16 @@ protected: + nsresult UpdateContext(nsIPropertyBag *aNewContextOptions = nsnull); + nsresult ExtractData(const nsAString& aType, + const nsAString& aOptions, ++ bool aUsePlaceholder, + nsIInputStream** aStream, + bool& aFellBackToPNG); + nsresult ToDataURLImpl(const nsAString& aMimeType, + nsIVariant* aEncoderOptions, ++ bool aUsePlaceholder, + nsAString& aDataURL); + nsresult MozGetAsFileImpl(const nsAString& aName, + const nsAString& aType, ++ bool aUsePlaceholder, + nsIDOMFile** aResult); + nsresult GetContextHelper(const nsAString& aContextId, + bool aForceThebes, +diff --git a/content/html/content/src/Makefile.in b/content/html/content/src/Makefile.in +index 019d297..3db4f7c 100644 +--- a/content/html/content/src/Makefile.in ++++ b/content/html/content/src/Makefile.in +@@ -138,6 +138,7 @@ INCLUDES += \ + -I$(srcdir)/../../../events/src \ + -I$(srcdir)/../../../xbl/src \ + -I$(srcdir)/../../../xul/content/src \ ++ -I$(srcdir)/../../../canvas/src/ \ + -I$(srcdir)/../../../../layout/forms \ + -I$(srcdir)/../../../../layout/style \ + -I$(srcdir)/../../../../layout/tables \ +diff --git a/content/html/content/src/nsHTMLCanvasElement.cpp b/content/html/content/src/nsHTMLCanvasElement.cpp +index a302f67..572a81b 100644 +--- a/content/html/content/src/nsHTMLCanvasElement.cpp ++++ b/content/html/content/src/nsHTMLCanvasElement.cpp +@@ -60,6 +60,8 @@ + + #include "nsIWritablePropertyBag2.h" + ++#include "CanvasUtils.h" ++ + #define DEFAULT_CANVAS_WIDTH 300 + #define DEFAULT_CANVAS_HEIGHT 150 + +@@ -213,25 +215,36 @@ nsHTMLCanvasElement::ToDataURL(const nsAString& aType, nsIVariant* aParams, + return NS_ERROR_DOM_SECURITY_ERR; + } + +- return ToDataURLImpl(aType, aParams, aDataURL); ++ // Check site-specific permission and display prompt if appropriate. ++ // If no permission, return all-white, opaque image data. ++ bool usePlaceholder = !CanvasUtils::IsImageExtractionAllowed(OwnerDoc()); ++ return ToDataURLImpl(aType, aParams, usePlaceholder, aDataURL); + } + ++// TODO: on FF trunk, we also need to patch mozFetchAsStream(). + nsresult + nsHTMLCanvasElement::ExtractData(const nsAString& aType, + const nsAString& aOptions, ++ bool aUsePlaceholder, + nsIInputStream** aStream, + bool& aFellBackToPNG) + { + // note that if we don't have a current context, the spec says we're + // supposed to just return transparent black pixels of the canvas + // dimensions. ++ // If placeholder data was requested, return all-white, opaque image data. + nsRefPtr<gfxImageSurface> emptyCanvas; + nsIntSize size = GetWidthHeight(); +- if (!mCurrentContext) { ++ if (aUsePlaceholder || !mCurrentContext) { + emptyCanvas = new gfxImageSurface(gfxIntSize(size.width, size.height), gfxASurface::ImageFormatARGB32); + if (emptyCanvas->CairoStatus()) { + return NS_ERROR_INVALID_ARG; + } ++ ++ if (aUsePlaceholder) { ++ int32_t dataSize = emptyCanvas->GetDataSize(); ++ memset(emptyCanvas->Data(), 0xFF, dataSize); ++ } + } + + nsresult rv; +@@ -241,12 +254,13 @@ nsHTMLCanvasElement::ExtractData(const nsAString& aType, + NS_ConvertUTF16toUTF8 encoderType(aType); + + try_again: +- if (mCurrentContext) { ++ if (!aUsePlaceholder && mCurrentContext) { + rv = mCurrentContext->GetInputStream(encoderType.get(), + nsPromiseFlatString(aOptions).get(), + getter_AddRefs(imgStream)); + } else { +- // no context, so we have to encode the empty image we created above ++ // Using placeholder or we have no context: encode the empty/white image ++ // we created above. + nsCString enccid("@mozilla.org/image/encoder;2?type="); + enccid += encoderType; + +@@ -284,6 +298,7 @@ nsHTMLCanvasElement::ExtractData(const nsAString& aType, + nsresult + nsHTMLCanvasElement::ToDataURLImpl(const nsAString& aMimeType, + nsIVariant* aEncoderOptions, ++ bool aUsePlaceholder, + nsAString& aDataURL) + { + bool fallbackToPNG = false; +@@ -339,13 +354,15 @@ nsHTMLCanvasElement::ToDataURLImpl(const nsAString& aMimeType, + } + + nsCOMPtr<nsIInputStream> stream; +- rv = ExtractData(type, params, getter_AddRefs(stream), fallbackToPNG); ++ rv = ExtractData(type, params, aUsePlaceholder, ++ getter_AddRefs(stream), fallbackToPNG); + + // If there are unrecognized custom parse options, we should fall back to + // the default values for the encoder without any options at all. + if (rv == NS_ERROR_INVALID_ARG && usingCustomParseOptions) { + fallbackToPNG = false; +- rv = ExtractData(type, EmptyString(), getter_AddRefs(stream), fallbackToPNG); ++ rv = ExtractData(type, EmptyString(), aUsePlaceholder, ++ getter_AddRefs(stream), fallbackToPNG); + } + + NS_ENSURE_SUCCESS(rv, rv); +@@ -376,19 +393,23 @@ nsHTMLCanvasElement::MozGetAsFile(const nsAString& aName, + return NS_ERROR_DOM_SECURITY_ERR; + } + +- return MozGetAsFileImpl(aName, aType, aResult); ++ // Check site-speciifc permission and display prompt if appropriate. ++ // If no permission, return all-white, opaque image data. ++ bool usePlaceholder = !CanvasUtils::IsImageExtractionAllowed(OwnerDoc()); ++ return MozGetAsFileImpl(aName, aType, usePlaceholder, aResult); + } + + nsresult + nsHTMLCanvasElement::MozGetAsFileImpl(const nsAString& aName, + const nsAString& aType, ++ bool aUsePlaceholder, + nsIDOMFile** aResult) + { + bool fallbackToPNG = false; + + nsCOMPtr<nsIInputStream> stream; +- nsresult rv = ExtractData(aType, EmptyString(), getter_AddRefs(stream), +- fallbackToPNG); ++ nsresult rv = ExtractData(aType, EmptyString(), aUsePlaceholder, ++ getter_AddRefs(stream), fallbackToPNG); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString type(aType); +-- +1.7.5.4 + diff --git a/src/current-patches/firefox/0022-Return-client-window-coordinates-for-mouse-event-scr.patch b/src/current-patches/firefox/0022-Return-client-window-coordinates-for-mouse-event-scr.patch new file mode 100644 index 0000000..6da9c72 --- /dev/null +++ b/src/current-patches/firefox/0022-Return-client-window-coordinates-for-mouse-event-scr.patch @@ -0,0 +1,43 @@ +From 74215e38ba60b74df59216122c4f2cc068e33216 Mon Sep 17 00:00:00 2001 +From: Kathleen Brade brade@pearlcrescent.com +Date: Tue, 9 Oct 2012 11:13:45 -0400 +Subject: [PATCH 22/24] Return client window coordinates for mouse event + screenX/Y (for dragend, 0,0 is returned). + +--- + content/events/src/nsDOMUIEvent.cpp | 15 +++++++++++++++ + 1 files changed, 15 insertions(+), 0 deletions(-) + +diff --git a/content/events/src/nsDOMUIEvent.cpp b/content/events/src/nsDOMUIEvent.cpp +index fe57f52..d641f0d 100644 +--- a/content/events/src/nsDOMUIEvent.cpp ++++ b/content/events/src/nsDOMUIEvent.cpp +@@ -135,10 +135,25 @@ nsDOMUIEvent::GetScreenPoint() + return nsIntPoint(0, 0); + } + ++ bool isChrome = nsContentUtils::IsCallerChrome(); ++ + if (!((nsGUIEvent*)mEvent)->widget ) { ++ // For non-chrome callers, return 0,0 if there is no widget associated ++ // with this event, e.g., for dragend events. Since dragend is for the ++ // drag originator and not for the receiver, it is probably not widely ++ // used (receivers get a drop event). Therefore, returning 0,0 should ++ // not break many web pages. Also, a few years ago Firefox returned 0,0. ++ // See: https://bugzilla.mozilla.org/show_bug.cgi?id=466379 ++ if (!isChrome) ++ return nsIntPoint(0, 0); ++ + return mEvent->refPoint; + } + ++ // For non-chrome callers, return client area coordinates instead. ++ if (!isChrome) ++ return GetClientPoint(); ++ + nsIntPoint offset = mEvent->refPoint + + ((nsGUIEvent*)mEvent)->widget->WidgetToScreenOffset(); + nscoord factor = mPresContext->DeviceContext()->UnscaledAppUnitsPerDevPixel(); +-- +1.7.5.4 + diff --git a/src/current-patches/firefox/0023-Do-not-expose-physical-screen-info.-via-window-and-w.patch b/src/current-patches/firefox/0023-Do-not-expose-physical-screen-info.-via-window-and-w.patch new file mode 100644 index 0000000..1b925e0 --- /dev/null +++ b/src/current-patches/firefox/0023-Do-not-expose-physical-screen-info.-via-window-and-w.patch @@ -0,0 +1,312 @@ +From d944531b020848e09ac280af11d039d992ab6461 Mon Sep 17 00:00:00 2001 +From: Kathleen Brade brade@pearlcrescent.com +Date: Wed, 3 Oct 2012 17:06:48 -0400 +Subject: [PATCH 23/24] Do not expose physical screen info. via window and + window.screen. + +--- + dom/base/nsGlobalWindow.cpp | 46 +++++++++++++++++++++ + dom/base/nsGlobalWindow.h | 2 + + dom/base/nsScreen.cpp | 92 +++++++++++++++++++++++++++++++++++++++++++ + dom/base/nsScreen.h | 3 + + 4 files changed, 143 insertions(+), 0 deletions(-) + +diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp +index 2c99571..982d931 100644 +--- a/dom/base/nsGlobalWindow.cpp ++++ b/dom/base/nsGlobalWindow.cpp +@@ -3817,6 +3817,10 @@ nsGlobalWindow::GetOuterWidth(PRInt32* aOuterWidth) + { + FORWARD_TO_OUTER(GetOuterWidth, (aOuterWidth), NS_ERROR_NOT_INITIALIZED); + ++ // For non-chrome callers, return inner width to prevent fingerprinting. ++ if (!IsChrome()) ++ return GetInnerWidth(aOuterWidth); ++ + nsIntSize sizeCSSPixels; + nsresult rv = GetOuterSize(&sizeCSSPixels); + NS_ENSURE_SUCCESS(rv, rv); +@@ -3830,6 +3834,10 @@ nsGlobalWindow::GetOuterHeight(PRInt32* aOuterHeight) + { + FORWARD_TO_OUTER(GetOuterHeight, (aOuterHeight), NS_ERROR_NOT_INITIALIZED); + ++ // For non-chrome callers, return inner height to prevent fingerprinting. ++ if (!IsChrome()) ++ return GetInnerHeight(aOuterHeight); ++ + nsIntSize sizeCSSPixels; + nsresult rv = GetOuterSize(&sizeCSSPixels); + NS_ENSURE_SUCCESS(rv, rv); +@@ -3892,6 +3900,12 @@ nsGlobalWindow::GetScreenX(PRInt32* aScreenX) + { + FORWARD_TO_OUTER(GetScreenX, (aScreenX), NS_ERROR_NOT_INITIALIZED); + ++ // For non-chrome callers, always return 0 to prevent fingerprinting. ++ if (!IsChrome()) { ++ *aScreenX = 0; ++ return NS_OK; ++ } ++ + nsCOMPtr<nsIBaseWindow> treeOwnerAsWin; + GetTreeOwner(getter_AddRefs(treeOwnerAsWin)); + NS_ENSURE_TRUE(treeOwnerAsWin, NS_ERROR_FAILURE); +@@ -3933,6 +3947,12 @@ nsGlobalWindow::GetMozInnerScreenX(float* aScreenX) + { + FORWARD_TO_OUTER(GetMozInnerScreenX, (aScreenX), NS_ERROR_NOT_INITIALIZED); + ++ // For non-chrome callers, always return 0 to prevent fingerprinting. ++ if (!IsChrome()) { ++ *aScreenX = 0; ++ return NS_OK; ++ } ++ + nsRect r = GetInnerScreenRect(); + *aScreenX = nsPresContext::AppUnitsToFloatCSSPixels(r.x); + return NS_OK; +@@ -3943,6 +3963,12 @@ nsGlobalWindow::GetMozInnerScreenY(float* aScreenY) + { + FORWARD_TO_OUTER(GetMozInnerScreenY, (aScreenY), NS_ERROR_NOT_INITIALIZED); + ++ // For non-chrome callers, always return 0 to prevent fingerprinting. ++ if (!IsChrome()) { ++ *aScreenY = 0; ++ return NS_OK; ++ } ++ + nsRect r = GetInnerScreenRect(); + *aScreenY = nsPresContext::AppUnitsToFloatCSSPixels(r.y); + return NS_OK; +@@ -4064,6 +4090,12 @@ nsGlobalWindow::GetScreenY(PRInt32* aScreenY) + { + FORWARD_TO_OUTER(GetScreenY, (aScreenY), NS_ERROR_NOT_INITIALIZED); + ++ // For non-chrome callers, always return 0 to prevent fingerprinting. ++ if (!IsChrome()) { ++ *aScreenY = 0; ++ return NS_OK; ++ } ++ + nsCOMPtr<nsIBaseWindow> treeOwnerAsWin; + GetTreeOwner(getter_AddRefs(treeOwnerAsWin)); + NS_ENSURE_TRUE(treeOwnerAsWin, NS_ERROR_FAILURE); +@@ -4110,6 +4142,20 @@ nsGlobalWindow::SetScreenY(PRInt32 aScreenY) + return NS_OK; + } + ++bool ++nsGlobalWindow::IsChrome() ++{ ++ bool isChrome = false; ++ ++ if (mDocShell) { ++ nsRefPtr<nsPresContext> presContext; ++ mDocShell->GetPresContext(getter_AddRefs(presContext)); ++ isChrome = (presContext && presContext->IsChrome()); ++ } ++ ++ return isChrome; ++} ++ + // NOTE: Arguments to this function should have values scaled to + // CSS pixels, not device pixels. + nsresult +diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h +index 2ffe4a7..863329c 100644 +--- a/dom/base/nsGlobalWindow.h ++++ b/dom/base/nsGlobalWindow.h +@@ -744,6 +744,8 @@ protected: + nsresult SetOuterSize(PRInt32 aLengthCSSPixels, bool aIsWidth); + nsRect GetInnerScreenRect(); + ++ bool IsChrome(); ++ + bool IsFrame() + { + return GetParentInternal() != nsnull; +diff --git a/dom/base/nsScreen.cpp b/dom/base/nsScreen.cpp +index 33a03dc..29a3598 100644 +--- a/dom/base/nsScreen.cpp ++++ b/dom/base/nsScreen.cpp +@@ -82,6 +82,12 @@ nsScreen::SetDocShell(nsIDocShell* aDocShell) + NS_IMETHODIMP + nsScreen::GetTop(PRInt32* aTop) + { ++ // For non-chrome callers, always return 0 to prevent fingerprinting. ++ if (!IsChrome()) { ++ *aTop = 0; ++ return NS_OK; ++ } ++ + nsRect rect; + nsresult rv = GetRect(rect); + +@@ -94,6 +100,12 @@ nsScreen::GetTop(PRInt32* aTop) + NS_IMETHODIMP + nsScreen::GetLeft(PRInt32* aLeft) + { ++ // For non-chrome callers, always return 0 to prevent fingerprinting. ++ if (!IsChrome()) { ++ *aLeft = 0; ++ return NS_OK; ++ } ++ + nsRect rect; + nsresult rv = GetRect(rect); + +@@ -106,6 +118,14 @@ nsScreen::GetLeft(PRInt32* aLeft) + NS_IMETHODIMP + nsScreen::GetWidth(PRInt32* aWidth) + { ++ // For non-chrome callers, return content width to prevent fingerprinting. ++ if (!IsChrome()) { ++ nsCOMPtr<nsIDOMWindow> win; ++ nsresult rv = GetDOMWindow(getter_AddRefs(win)); ++ NS_ENSURE_SUCCESS(rv, rv); ++ return win->GetInnerWidth(aWidth); ++ } ++ + nsRect rect; + nsresult rv = GetRect(rect); + +@@ -117,6 +137,14 @@ nsScreen::GetWidth(PRInt32* aWidth) + NS_IMETHODIMP + nsScreen::GetHeight(PRInt32* aHeight) + { ++ // For non-chrome callers, return content height to prevent fingerprinting. ++ if (!IsChrome()) { ++ nsCOMPtr<nsIDOMWindow> win; ++ nsresult rv = GetDOMWindow(getter_AddRefs(win)); ++ NS_ENSURE_SUCCESS(rv, rv); ++ return win->GetInnerHeight(aHeight); ++ } ++ + nsRect rect; + nsresult rv = GetRect(rect); + +@@ -128,6 +156,12 @@ nsScreen::GetHeight(PRInt32* aHeight) + NS_IMETHODIMP + nsScreen::GetPixelDepth(PRInt32* aPixelDepth) + { ++ // For non-chrome callers, always return 24 to prevent fingerprinting. ++ if (!IsChrome()) { ++ *aPixelDepth = 24; ++ return NS_OK; ++ } ++ + nsDeviceContext* context = GetDeviceContext(); + + if (!context) { +@@ -153,6 +187,14 @@ nsScreen::GetColorDepth(PRInt32* aColorDepth) + NS_IMETHODIMP + nsScreen::GetAvailWidth(PRInt32* aAvailWidth) + { ++ // For non-chrome callers, return content width to prevent fingerprinting. ++ if (!IsChrome()) { ++ nsCOMPtr<nsIDOMWindow> win; ++ nsresult rv = GetDOMWindow(getter_AddRefs(win)); ++ NS_ENSURE_SUCCESS(rv, rv); ++ return win->GetInnerWidth(aAvailWidth); ++ } ++ + nsRect rect; + nsresult rv = GetAvailRect(rect); + +@@ -164,6 +206,14 @@ nsScreen::GetAvailWidth(PRInt32* aAvailWidth) + NS_IMETHODIMP + nsScreen::GetAvailHeight(PRInt32* aAvailHeight) + { ++ // For non-chrome callers, return content height to prevent fingerprinting. ++ if (!IsChrome()) { ++ nsCOMPtr<nsIDOMWindow> win; ++ nsresult rv = GetDOMWindow(getter_AddRefs(win)); ++ NS_ENSURE_SUCCESS(rv, rv); ++ return win->GetInnerHeight(aAvailHeight); ++ } ++ + nsRect rect; + nsresult rv = GetAvailRect(rect); + +@@ -175,6 +225,12 @@ nsScreen::GetAvailHeight(PRInt32* aAvailHeight) + NS_IMETHODIMP + nsScreen::GetAvailLeft(PRInt32* aAvailLeft) + { ++ // For non-chrome callers, always return 0 to prevent fingerprinting. ++ if (!IsChrome()) { ++ *aAvailLeft = 0; ++ return NS_OK; ++ } ++ + nsRect rect; + nsresult rv = GetAvailRect(rect); + +@@ -186,6 +242,12 @@ nsScreen::GetAvailLeft(PRInt32* aAvailLeft) + NS_IMETHODIMP + nsScreen::GetAvailTop(PRInt32* aAvailTop) + { ++ // For non-chrome callers, always return 0 to prevent fingerprinting. ++ if (!IsChrome()) { ++ *aAvailTop = 0; ++ return NS_OK; ++ } ++ + nsRect rect; + nsresult rv = GetAvailRect(rect); + +@@ -237,3 +299,33 @@ nsScreen::GetAvailRect(nsRect& aRect) + + return NS_OK; + } ++ ++bool ++nsScreen::IsChrome() ++{ ++ bool isChrome = false; ++ if (mDocShell) { ++ nsRefPtr<nsPresContext> presContext; ++ mDocShell->GetPresContext(getter_AddRefs(presContext)); ++ if (presContext) ++ isChrome = presContext->IsChrome(); ++ } ++ ++ return isChrome; ++} ++ ++nsresult ++nsScreen::GetDOMWindow(nsIDOMWindow **aResult) ++{ ++ NS_ENSURE_ARG_POINTER(aResult); ++ *aResult = NULL; ++ ++ if (!mDocShell) ++ return NS_ERROR_FAILURE; ++ ++ nsCOMPtr<nsIDOMWindow> win = do_GetInterface(mDocShell); ++ NS_ENSURE_STATE(win); ++ win.swap(*aResult); ++ ++ return NS_OK; ++} +diff --git a/dom/base/nsScreen.h b/dom/base/nsScreen.h +index 52eab29..d4edaa3 100644 +--- a/dom/base/nsScreen.h ++++ b/dom/base/nsScreen.h +@@ -44,6 +44,7 @@ + + class nsIDocShell; + class nsDeviceContext; ++class nsIDOMWindow; + struct nsRect; + + // Script "screen" object +@@ -62,6 +63,8 @@ protected: + nsDeviceContext* GetDeviceContext(); + nsresult GetRect(nsRect& aRect); + nsresult GetAvailRect(nsRect& aRect); ++ bool IsChrome(); ++ nsresult GetDOMWindow(nsIDOMWindow **aResult); + + nsIDocShell* mDocShell; // Weak Reference + }; +-- +1.7.5.4 + diff --git a/src/current-patches/firefox/0024-Do-not-expose-system-colors-to-CSS-or-canvas.patch b/src/current-patches/firefox/0024-Do-not-expose-system-colors-to-CSS-or-canvas.patch new file mode 100644 index 0000000..629a759 --- /dev/null +++ b/src/current-patches/firefox/0024-Do-not-expose-system-colors-to-CSS-or-canvas.patch @@ -0,0 +1,537 @@ +From 38a469e05779315cb2990be60c13fb167812e54d Mon Sep 17 00:00:00 2001 +From: Kathleen Brade brade@pearlcrescent.com +Date: Thu, 4 Oct 2012 14:53:13 -0400 +Subject: [PATCH 24/24] Do not expose system colors to CSS or canvas. + +--- + content/canvas/src/nsCanvasRenderingContext2D.cpp | 36 +++- + .../canvas/src/nsCanvasRenderingContext2DAzure.cpp | 51 ++++-- + layout/style/nsCSSParser.cpp | 19 ++- + layout/style/nsRuleNode.cpp | 4 +- + widget/public/LookAndFeel.h | 9 + + widget/src/xpwidgets/nsXPLookAndFeel.cpp | 173 +++++++++++++++++++- + widget/src/xpwidgets/nsXPLookAndFeel.h | 5 +- + 7 files changed, 269 insertions(+), 28 deletions(-) + +diff --git a/content/canvas/src/nsCanvasRenderingContext2D.cpp b/content/canvas/src/nsCanvasRenderingContext2D.cpp +index 0cf97ce..6c47821 100644 +--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp ++++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp +@@ -186,8 +186,9 @@ class nsCanvasGradient : public nsIDOMCanvasGradient + public: + NS_DECLARE_STATIC_IID_ACCESSOR(NS_CANVASGRADIENT_PRIVATE_IID) + +- nsCanvasGradient(gfxPattern* pat) +- : mPattern(pat) ++ nsCanvasGradient(mozilla::css::Loader* aLoader, gfxPattern* pat) ++ : mCSSLoader(aLoader) ++ , mPattern(pat) + { + } + +@@ -203,7 +204,7 @@ public: + return NS_ERROR_DOM_INDEX_SIZE_ERR; + + nscolor color; +- nsCSSParser parser; ++ nsCSSParser parser(mCSSLoader); + nsresult rv = parser.ParseColorString(nsString(colorstr), + nsnull, 0, &color); + if (NS_FAILED(rv)) +@@ -217,6 +218,7 @@ public: + NS_DECL_ISUPPORTS + + protected: ++ mozilla::css::Loader* mCSSLoader; // not ref counted, it owns us + nsRefPtr<gfxPattern> mPattern; + }; + +@@ -875,7 +877,9 @@ nsCanvasRenderingContext2D::SetStyleFromStringOrInterface(const nsAString& aStr, + HTMLCanvasElement()->OwnerDoc() : nsnull; + + // Pass the CSS Loader object to the parser, to allow parser error +- // reports to include the outer window ID. ++ // reports to include the outer window ID. The parser also uses it to ++ // detect whether the caller is chrome in order to avoid exposing ++ // system colors. + nsCSSParser parser(document ? document->CSSLoader() : nsnull); + rv = parser.ParseColorString(aStr, nsnull, 0, &color); + if (NS_FAILED(rv)) { +@@ -1778,7 +1782,14 @@ nsCanvasRenderingContext2D::CreateLinearGradient(float x0, float y0, float x1, f + if (!gradpat) + return NS_ERROR_OUT_OF_MEMORY; + +- nsRefPtr<nsIDOMCanvasGradient> grad = new nsCanvasGradient(gradpat); ++ // Pass the CSS Loader object to the parser, to allow parser error reports ++ // to include the outer window ID. The parser also uses it to detect ++ // whether the caller is chrome in order to avoid exposing system colors. ++ nsIDocument* doc = mCanvasElement ? HTMLCanvasElement()->OwnerDoc() ++ : nsnull; ++ mozilla::css::Loader* cssLoader = doc ? doc->CSSLoader() : nsnull; ++ nsRefPtr<nsIDOMCanvasGradient> grad = new nsCanvasGradient(cssLoader, ++ gradpat); + if (!grad) + return NS_ERROR_OUT_OF_MEMORY; + +@@ -1800,7 +1811,14 @@ nsCanvasRenderingContext2D::CreateRadialGradient(float x0, float y0, float r0, f + if (!gradpat) + return NS_ERROR_OUT_OF_MEMORY; + +- nsRefPtr<nsIDOMCanvasGradient> grad = new nsCanvasGradient(gradpat); ++ // Pass the CSS Loader object to the parser, to allow parser error reports ++ // to include the outer window ID. The parser also uses it to detect ++ // whether the caller is chrome in order to avoid exposing system colors. ++ nsIDocument* doc = mCanvasElement ? HTMLCanvasElement()->OwnerDoc() ++ : nsnull; ++ mozilla::css::Loader* cssLoader = doc ? doc->CSSLoader() : nsnull; ++ nsRefPtr<nsIDOMCanvasGradient> grad = new nsCanvasGradient(cssLoader, ++ gradpat); + if (!grad) + return NS_ERROR_OUT_OF_MEMORY; + +@@ -1922,7 +1940,8 @@ nsCanvasRenderingContext2D::SetShadowColor(const nsAString& colorstr) + HTMLCanvasElement()->OwnerDoc() : nsnull; + + // Pass the CSS Loader object to the parser, to allow parser error reports +- // to include the outer window ID. ++ // to include the outer window ID. The parser also uses it to detect ++ // whether the caller is chrome in order to avoid exposing system colors. + nsCSSParser parser(document ? document->CSSLoader() : nsnull); + nscolor color; + nsresult rv = parser.ParseColorString(colorstr, nsnull, 0, &color); +@@ -3694,7 +3713,8 @@ nsCanvasRenderingContext2D::DrawWindow(nsIDOMWindow* aWindow, float aX, float aY + HTMLCanvasElement()->OwnerDoc() : nsnull; + + // Pass the CSS Loader object to the parser, to allow parser error reports +- // to include the outer window ID. ++ // to include the outer window ID. The parser also uses it to detect ++ // whether the caller is chrome in order to avoid exposing system colors. + nsCSSParser parser(elementDoc ? elementDoc->CSSLoader() : nsnull); + nsresult rv = parser.ParseColorString(PromiseFlatString(aBGColor), + nsnull, 0, &bgColor); +diff --git a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp +index e8dfb1e..cb5a5f5 100644 +--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp ++++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp +@@ -201,7 +201,10 @@ public: + } + + nscolor color; +- nsCSSParser parser; ++ // Pass the CSS Loader object to the parser, to allow parser error reports ++ // to include the outer window ID. The parser also uses it to detect ++ // whether the caller is chrome in order to avoid exposing system colors. ++ nsCSSParser parser(mCSSLoader);; + nsresult rv = parser.ParseColorString(nsString(colorstr), + nsnull, 0, &color); + if (NS_FAILED(rv)) { +@@ -221,20 +224,24 @@ public: + } + + protected: +- nsCanvasGradientAzure(Type aType) : mType(aType) ++ nsCanvasGradientAzure(mozilla::css::Loader* aLoader, Type aType) ++ : mCSSLoader(aLoader) ++ , mType(aType) + {} + + nsTArray<GradientStop> mRawStops; + RefPtr<GradientStops> mStops; ++ mozilla::css::Loader* mCSSLoader; // not ref counted, it owns us + Type mType; + }; + + class nsCanvasRadialGradientAzure : public nsCanvasGradientAzure + { + public: +- nsCanvasRadialGradientAzure(const Point &aBeginOrigin, Float aBeginRadius, ++ nsCanvasRadialGradientAzure(mozilla::css::Loader* aLoader, ++ const Point &aBeginOrigin, Float aBeginRadius, + const Point &aEndOrigin, Float aEndRadius) +- : nsCanvasGradientAzure(RADIAL) ++ : nsCanvasGradientAzure(aLoader, RADIAL) + , mCenter1(aBeginOrigin) + , mCenter2(aEndOrigin) + , mRadius1(aBeginRadius) +@@ -251,8 +258,9 @@ public: + class nsCanvasLinearGradientAzure : public nsCanvasGradientAzure + { + public: +- nsCanvasLinearGradientAzure(const Point &aBegin, const Point &aEnd) +- : nsCanvasGradientAzure(LINEAR) ++ nsCanvasLinearGradientAzure(mozilla::css::Loader* aLoader, ++ const Point &aBegin, const Point &aEnd) ++ : nsCanvasGradientAzure(aLoader, LINEAR) + , mBegin(aBegin) + , mEnd(aEnd) + { +@@ -1066,8 +1074,9 @@ nsCanvasRenderingContext2DAzure::SetStyleFromStringOrInterface(const nsAString& + nsIDocument* document = mCanvasElement ? + HTMLCanvasElement()->OwnerDoc() : nsnull; + +- // Pass the CSS Loader object to the parser, to allow parser error +- // reports to include the outer window ID. ++ // Pass the CSS Loader object to the parser, to allow parser error reports ++ // to include the outer window ID. The parser also uses it to detect ++ // whether the caller is chrome in order to avoid exposing system colors. + nsCSSParser parser(document ? document->CSSLoader() : nsnull); + rv = parser.ParseColorString(aStr, nsnull, 0, &color); + if (NS_FAILED(rv)) { +@@ -1855,8 +1864,14 @@ nsCanvasRenderingContext2DAzure::CreateLinearGradient(float x0, float y0, float + return NS_ERROR_DOM_NOT_SUPPORTED_ERR; + } + +- nsRefPtr<nsIDOMCanvasGradient> grad = +- new nsCanvasLinearGradientAzure(Point(x0, y0), Point(x1, y1)); ++ // Pass the CSS Loader object to the parser, to allow parser error reports ++ // to include the outer window ID. The parser also uses it to detect ++ // whether the caller is chrome in order to avoid exposing system colors. ++ nsIDocument* doc = mCanvasElement ? HTMLCanvasElement()->OwnerDoc() ++ : nsnull; ++ mozilla::css::Loader* cssLoader = doc ? doc->CSSLoader() : nsnull; ++ nsRefPtr<nsIDOMCanvasGradient> grad = new nsCanvasLinearGradientAzure( ++ cssLoader, Point(x0, y0), Point(x1, y1)); + + *_retval = grad.forget().get(); + return NS_OK; +@@ -1875,8 +1890,14 @@ nsCanvasRenderingContext2DAzure::CreateRadialGradient(float x0, float y0, float + return NS_ERROR_DOM_INDEX_SIZE_ERR; + } + +- nsRefPtr<nsIDOMCanvasGradient> grad = +- new nsCanvasRadialGradientAzure(Point(x0, y0), r0, Point(x1, y1), r1); ++ // Pass the CSS Loader object to the parser, to allow parser error reports ++ // to include the outer window ID. The parser also uses it to detect ++ // whether the caller is chrome in order to avoid exposing system colors. ++ nsIDocument* doc = mCanvasElement ? HTMLCanvasElement()->OwnerDoc() ++ : nsnull; ++ mozilla::css::Loader* cssLoader = doc ? doc->CSSLoader() : nsnull; ++ nsRefPtr<nsIDOMCanvasGradient> grad = new nsCanvasRadialGradientAzure( ++ cssLoader, Point(x0, y0), r0, Point(x1, y1), r1); + + *_retval = grad.forget().get(); + return NS_OK; +@@ -2024,7 +2045,8 @@ nsCanvasRenderingContext2DAzure::SetShadowColor(const nsAString& colorstr) + HTMLCanvasElement()->OwnerDoc() : nsnull; + + // Pass the CSS Loader object to the parser, to allow parser error reports +- // to include the outer window ID. ++ // to include the outer window ID. The parser also uses it to detect ++ // whether the caller is chrome in order to avoid exposing system colors. + nsCSSParser parser(document ? document->CSSLoader() : nsnull); + nscolor color; + nsresult rv = parser.ParseColorString(colorstr, nsnull, 0, &color); +@@ -3847,7 +3869,8 @@ nsCanvasRenderingContext2DAzure::DrawWindow(nsIDOMWindow* aWindow, float aX, flo + HTMLCanvasElement()->OwnerDoc() : nsnull; + + // Pass the CSS Loader object to the parser, to allow parser error reports +- // to include the outer window ID. ++ // to include the outer window ID. The parser also uses it to detect ++ // whether the caller is chrome in order to avoid exposing system colors. + nsCSSParser parser(elementDoc ? elementDoc->CSSLoader() : nsnull); + nsresult rv = parser.ParseColorString(PromiseFlatString(aBGColor), + nsnull, 0, &bgColor); +diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp +index ae1a474..30e179c 100644 +--- a/layout/style/nsCSSParser.cpp ++++ b/layout/style/nsCSSParser.cpp +@@ -1216,8 +1216,25 @@ CSSParserImpl::ParseColorString(const nsSubstring& aBuffer, + // Should remove this limitation at some point. + return NS_ERROR_FAILURE; + } ++ ++ // We do not want to expose system/native colors to content. All callers ++ // who are working with content should ensure that they set the CSS ++ // loader (mChildLoader) so we can check here if the content is chrome. ++ bool isChrome = true; ++ if (mChildLoader) { ++ nsIDocument *doc = mChildLoader->GetDocument(); ++ if (doc) { ++ nsIPresShell *presShell = doc->GetShell(); ++ if (presShell) { ++ nsPresContext* presCtxt = presShell->GetPresContext(); ++ if (presCtxt) ++ isChrome = presCtxt->IsChrome(); ++ } ++ } ++ } + nscolor rgba; +- nsresult rv = LookAndFeel::GetColor(LookAndFeel::ColorID(val), &rgba); ++ nsresult rv = LookAndFeel::GetColor(LookAndFeel::ColorID(val), !isChrome, ++ &rgba); + if (NS_FAILED(rv)) { + return rv; + } +diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp +index 827585a..d19524e 100644 +--- a/layout/style/nsRuleNode.cpp ++++ b/layout/style/nsRuleNode.cpp +@@ -768,7 +768,9 @@ static bool SetColor(const nsCSSValue& aValue, const nscolor aParentColor, + PRInt32 intValue = aValue.GetIntValue(); + if (0 <= intValue) { + LookAndFeel::ColorID colorID = (LookAndFeel::ColorID) intValue; +- if (NS_SUCCEEDED(LookAndFeel::GetColor(colorID, &aResult))) { ++ bool useStandinsForNativeColors = !aPresContext->IsChrome(); ++ if (NS_SUCCEEDED(LookAndFeel::GetColor(colorID, ++ useStandinsForNativeColors, &aResult))) { + result = true; + } + } +diff --git a/widget/public/LookAndFeel.h b/widget/public/LookAndFeel.h +index aae3b28..bb7be3c 100644 +--- a/widget/public/LookAndFeel.h ++++ b/widget/public/LookAndFeel.h +@@ -445,6 +445,15 @@ public: + static nsresult GetColor(ColorID aID, nscolor* aResult); + + /** ++ * This variant of GetColor() take an extra Boolean parameter that allows ++ * the caller to ask that hard-coded color values be substituted for ++ * native colors (used when it is desireable to hide system colors to ++ * avoid system fingerprinting). ++ */ ++ static nsresult GetColor(ColorID aID, bool aUseStandinsForNativeColors, ++ nscolor* aResult); ++ ++ /** + * GetInt() and GetFloat() return a int or float value for aID. The result + * might be distance, time, some flags or a int value which has particular + * meaning. See each document at definition of each ID for the detail. +diff --git a/widget/src/xpwidgets/nsXPLookAndFeel.cpp b/widget/src/xpwidgets/nsXPLookAndFeel.cpp +index 8053432..96937ac 100644 +--- a/widget/src/xpwidgets/nsXPLookAndFeel.cpp ++++ b/widget/src/xpwidgets/nsXPLookAndFeel.cpp +@@ -502,6 +502,155 @@ nsXPLookAndFeel::IsSpecialColor(ColorID aID, nscolor &aColor) + return false; + } + ++bool ++nsXPLookAndFeel::ColorIsNotCSSAccessible(ColorID aID) ++{ ++ bool result = false; ++ ++ switch (aID) { ++ case eColorID_WindowBackground: ++ case eColorID_WindowForeground: ++ case eColorID_WidgetBackground: ++ case eColorID_WidgetForeground: ++ case eColorID_WidgetSelectBackground: ++ case eColorID_WidgetSelectForeground: ++ case eColorID_Widget3DHighlight: ++ case eColorID_Widget3DShadow: ++ case eColorID_TextBackground: ++ case eColorID_TextForeground: ++ case eColorID_TextSelectBackground: ++ case eColorID_TextSelectForeground: ++ case eColorID_TextSelectBackgroundDisabled: ++ case eColorID_TextSelectBackgroundAttention: ++ case eColorID_TextHighlightBackground: ++ case eColorID_TextHighlightForeground: ++ case eColorID_IMERawInputBackground: ++ case eColorID_IMERawInputForeground: ++ case eColorID_IMERawInputUnderline: ++ case eColorID_IMESelectedRawTextBackground: ++ case eColorID_IMESelectedRawTextForeground: ++ case eColorID_IMESelectedRawTextUnderline: ++ case eColorID_IMEConvertedTextBackground: ++ case eColorID_IMEConvertedTextForeground: ++ case eColorID_IMEConvertedTextUnderline: ++ case eColorID_IMESelectedConvertedTextBackground: ++ case eColorID_IMESelectedConvertedTextForeground: ++ case eColorID_IMESelectedConvertedTextUnderline: ++ case eColorID_SpellCheckerUnderline: ++ result = true; ++ break; ++ default: ++ break; ++ } ++ ++ return result; ++} ++ ++nscolor ++nsXPLookAndFeel::GetStandinForNativeColor(ColorID aID) ++{ ++ nscolor result = NS_RGB(0xFF, 0xFF, 0xFF); ++ ++ // The stand-in colors are taken from the Windows 7 Aero theme ++ // except Mac-specific colors which are taken from Mac OS 10.7. ++ switch (aID) { ++ // CSS 2 colors: ++ case eColorID_activeborder: result = NS_RGB(0xB4, 0xB4, 0xB4); break; ++ case eColorID_activecaption: result = NS_RGB(0x99, 0xB4, 0xD1); break; ++ case eColorID_appworkspace: result = NS_RGB(0xAB, 0xAB, 0xAB); break; ++ case eColorID_background: result = NS_RGB(0x00, 0x00, 0x00); break; ++ case eColorID_buttonface: result = NS_RGB(0xF0, 0xF0, 0xF0); break; ++ case eColorID_buttonhighlight: result = NS_RGB(0xFF, 0xFF, 0xFF); break; ++ case eColorID_buttonshadow: result = NS_RGB(0xA0, 0xA0, 0xA0); break; ++ case eColorID_buttontext: result = NS_RGB(0x00, 0x00, 0x00); break; ++ case eColorID_captiontext: result = NS_RGB(0x00, 0x00, 0x00); break; ++ case eColorID_graytext: result = NS_RGB(0x6D, 0x6D, 0x6D); break; ++ case eColorID_highlight: result = NS_RGB(0x33, 0x99, 0xFF); break; ++ case eColorID_highlighttext: result = NS_RGB(0xFF, 0xFF, 0xFF); break; ++ case eColorID_inactiveborder: result = NS_RGB(0xF4, 0xF7, 0xFC); break; ++ case eColorID_inactivecaption: result = NS_RGB(0xBF, 0xCD, 0xDB); break; ++ case eColorID_inactivecaptiontext: ++ result = NS_RGB(0x43, 0x4E, 0x54); break; ++ case eColorID_infobackground: result = NS_RGB(0xFF, 0xFF, 0xE1); break; ++ case eColorID_infotext: result = NS_RGB(0x00, 0x00, 0x00); break; ++ case eColorID_menu: result = NS_RGB(0xF0, 0xF0, 0xF0); break; ++ case eColorID_menutext: result = NS_RGB(0x00, 0x00, 0x00); break; ++ case eColorID_scrollbar: result = NS_RGB(0xC8, 0xC8, 0xC8); break; ++ case eColorID_threeddarkshadow: result = NS_RGB(0x69, 0x69, 0x69); break; ++ case eColorID_threedface: result = NS_RGB(0xF0, 0xF0, 0xF0); break; ++ case eColorID_threedhighlight: result = NS_RGB(0xFF, 0xFF, 0xFF); break; ++ case eColorID_threedlightshadow: result = NS_RGB(0xE3, 0xE3, 0xE3); break; ++ case eColorID_threedshadow: result = NS_RGB(0xA0, 0xA0, 0xA0); break; ++ case eColorID_window: result = NS_RGB(0xFF, 0xFF, 0xFF); break; ++ case eColorID_windowframe: result = NS_RGB(0x64, 0x64, 0x64); break; ++ case eColorID_windowtext: result = NS_RGB(0x00, 0x00, 0x00); break; ++ case eColorID__moz_buttondefault: ++ result = NS_RGB(0x69, 0x69, 0x69); break; ++ case eColorID__moz_field: result = NS_RGB(0xFF, 0xFF, 0xFF); break; ++ case eColorID__moz_fieldtext: result = NS_RGB(0x00, 0x00, 0x00); break; ++ case eColorID__moz_dialog: result = NS_RGB(0xF0, 0xF0, 0xF0); break; ++ case eColorID__moz_dialogtext: result = NS_RGB(0x00, 0x00, 0x00); break; ++ case eColorID__moz_dragtargetzone: ++ result = NS_RGB(0xFF, 0xFF, 0xFF); break; ++ case eColorID__moz_cellhighlight: ++ result = NS_RGB(0xF0, 0xF0, 0xF0); break; ++ case eColorID__moz_cellhighlighttext: ++ result = NS_RGB(0x00, 0x00, 0x00); break; ++ case eColorID__moz_html_cellhighlight: ++ result = NS_RGB(0x33, 0x99, 0xFF); break; ++ case eColorID__moz_html_cellhighlighttext: ++ result = NS_RGB(0xFF, 0xFF, 0xFF); break; ++ case eColorID__moz_buttonhoverface: ++ result = NS_RGB(0xF0, 0xF0, 0xF0); break; ++ case eColorID__moz_buttonhovertext: ++ result = NS_RGB(0x00, 0x00, 0x00); break; ++ case eColorID__moz_menuhover: ++ result = NS_RGB(0x33, 0x99, 0xFF); break; ++ case eColorID__moz_menuhovertext: ++ result = NS_RGB(0x00, 0x00, 0x00); break; ++ case eColorID__moz_menubartext: ++ result = NS_RGB(0x00, 0x00, 0x00); break; ++ case eColorID__moz_menubarhovertext: ++ result = NS_RGB(0x00, 0x00, 0x00); break; ++ case eColorID__moz_oddtreerow: ++ result = NS_RGB(0xFF, 0xFF, 0xFF); break; ++ case eColorID__moz_mac_chrome_active: ++ result = NS_RGB(0xB2, 0xB2, 0xB2); break; ++ case eColorID__moz_mac_chrome_inactive: ++ result = NS_RGB(0xE1, 0xE1, 0xE1); break; ++ case eColorID__moz_mac_focusring: ++ result = NS_RGB(0x60, 0x9D, 0xD7); break; ++ case eColorID__moz_mac_menuselect: ++ result = NS_RGB(0x38, 0x75, 0xD7); break; ++ case eColorID__moz_mac_menushadow: ++ result = NS_RGB(0xA3, 0xA3, 0xA3); break; ++ case eColorID__moz_mac_menutextdisable: ++ result = NS_RGB(0x88, 0x88, 0x88); break; ++ case eColorID__moz_mac_menutextselect: ++ result = NS_RGB(0xFF, 0xFF, 0xFF); break; ++ case eColorID__moz_mac_disabledtoolbartext: ++ result = NS_RGB(0x3F, 0x3F, 0x3F); break; ++ case eColorID__moz_mac_alternateprimaryhighlight: ++ result = NS_RGB(0x38, 0x75, 0xD7); break; ++ case eColorID__moz_mac_secondaryhighlight: ++ result = NS_RGB(0xD4, 0xD4, 0xD4); break; ++ case eColorID__moz_win_mediatext: ++ result = NS_RGB(0xFF, 0xFF, 0xFF); break; ++ case eColorID__moz_win_communicationstext: ++ result = NS_RGB(0xFF, 0xFF, 0xFF); break; ++ case eColorID__moz_nativehyperlinktext: ++ result = NS_RGB(0x00, 0x66, 0xCC); break; ++ case eColorID__moz_comboboxtext: ++ result = NS_RGB(0x00, 0x00, 0x00); break; ++ case eColorID__moz_combobox: ++ result = NS_RGB(0xFF, 0xFF, 0xFF); break; ++ default: ++ break; ++ } ++ ++ return result; ++} ++ + // + // All these routines will return NS_OK if they have a value, + // in which case the nsLookAndFeel should use that value; +@@ -509,7 +658,8 @@ nsXPLookAndFeel::IsSpecialColor(ColorID aID, nscolor &aColor) + // platform-specific nsLookAndFeel should use its own values instead. + // + nsresult +-nsXPLookAndFeel::GetColorImpl(ColorID aID, nscolor &aResult) ++nsXPLookAndFeel::GetColorImpl(ColorID aID, bool aUseStandinsForNativeColors, ++ nscolor &aResult) + { + if (!sInitialized) + Init(); +@@ -595,7 +745,10 @@ nsXPLookAndFeel::GetColorImpl(ColorID aID, nscolor &aResult) + } + #endif // DEBUG_SYSTEM_COLOR_USE + +- if (IS_COLOR_CACHED(aID)) { ++ if (aUseStandinsForNativeColors && ColorIsNotCSSAccessible(aID)) ++ aUseStandinsForNativeColors = false; ++ ++ if (!aUseStandinsForNativeColors && IS_COLOR_CACHED(aID)) { + aResult = sCachedColors[aID]; + return NS_OK; + } +@@ -629,6 +782,12 @@ nsXPLookAndFeel::GetColorImpl(ColorID aID, nscolor &aResult) + return NS_OK; + } + ++ if (sUseNativeColors && aUseStandinsForNativeColors) ++ { ++ aResult = GetStandinForNativeColor(aID); ++ return NS_OK; ++ } ++ + if (sUseNativeColors && NS_SUCCEEDED(NativeGetColor(aID, aResult))) { + if ((gfxPlatform::GetCMSMode() == eCMSMode_All) && + !IsSpecialColor(aID, aResult)) { +@@ -719,7 +878,15 @@ namespace mozilla { + nsresult + LookAndFeel::GetColor(ColorID aID, nscolor* aResult) + { +- return nsLookAndFeel::GetInstance()->GetColorImpl(aID, *aResult); ++ return nsLookAndFeel::GetInstance()->GetColorImpl(aID, false, *aResult); ++} ++ ++nsresult ++LookAndFeel::GetColor(ColorID aID, bool aUseStandinsForNativeColors, ++ nscolor* aResult) ++{ ++ return nsLookAndFeel::GetInstance()->GetColorImpl(aID, ++ aUseStandinsForNativeColors, *aResult); + } + + // static +diff --git a/widget/src/xpwidgets/nsXPLookAndFeel.h b/widget/src/xpwidgets/nsXPLookAndFeel.h +index ce06575..c0ecc32 100644 +--- a/widget/src/xpwidgets/nsXPLookAndFeel.h ++++ b/widget/src/xpwidgets/nsXPLookAndFeel.h +@@ -84,7 +84,8 @@ public: + // otherwise we'll return NS_ERROR_NOT_AVAILABLE, in which case, the + // platform-specific nsLookAndFeel should use its own values instead. + // +- nsresult GetColorImpl(ColorID aID, nscolor &aResult); ++ nsresult GetColorImpl(ColorID aID, bool aUseStandinsForNativeColors, ++ nscolor &aResult); + virtual nsresult GetIntImpl(IntID aID, PRInt32 &aResult); + virtual nsresult GetFloatImpl(FloatID aID, float &aResult); + +@@ -111,6 +112,8 @@ protected: + void InitColorFromPref(PRInt32 aIndex); + virtual nsresult NativeGetColor(ColorID aID, nscolor &aResult) = 0; + bool IsSpecialColor(ColorID aID, nscolor &aColor); ++ bool ColorIsNotCSSAccessible(ColorID aID); ++ nscolor GetStandinForNativeColor(ColorID aID); + + static int OnPrefChanged(const char* aPref, void* aClosure); + +-- +1.7.5.4 +
tor-commits@lists.torproject.org