[tor-commits] [torbrowser/master] Update patches for Firefox 17ESR.
mikeperry at torproject.org
mikeperry at torproject.org
Thu Jan 17 01:19:31 UTC 2013
commit 4281125f4d3d7a2c337d48b6569689ab254083da
Author: Mike Perry <mikeperry-git at fscked.org>
Date: Wed Jan 16 00:19:54 2013 -0800
Update patches for Firefox 17ESR.
---
...-Block-Components.interfaces-from-content.patch | 37 +
...nents.interfaces-lookupMethod-from-conten.patch | 50 --
...0002-Make-Permissions-Manager-memory-only.patch | 28 +-
...-Make-Intermediate-Cert-Store-memory-only.patch | 21 +-
.../firefox/0004-Add-a-string-based-cacheKey.patch | 32 +-
.../0005-Block-all-plugins-except-flash.patch | 20 +-
...ontent-pref-service-memory-only-clearable.patch | 10 +-
...owser-exit-when-not-launched-from-Vidalia.patch | 52 +-
.../0008-Disable-SSL-Session-ID-tracking.patch | 4 +-
...observer-event-to-close-persistent-connec.patch | 20 +-
...ice-and-system-specific-CSS-Media-Queries.patch | 101 +--
...11-Limit-the-number-of-fonts-per-document.patch | 97 ++-
.../0012-Rebrand-Firefox-to-TorBrowser.patch | 29 +-
.../0013-Make-Download-manager-memory-only.patch | 18 +-
.../0014-Add-DDG-and-StartPage-to-Omnibox.patch | 4 +-
...-nsICacheService.EvictEntries-synchronous.patch | 23 +-
.../firefox/0016-Prevent-WebSocket-DNS-leak.patch | 55 +-
...ize-HTTP-request-order-and-pipeline-depth.patch | 296 +++-----
...Adapt-Steven-Michaud-s-Mac-crashfix-patch.patch | 545 ++++++++++++
...th-headers-before-the-modify-request-obse.patch | 52 --
...Adapt-Steven-Michaud-s-Mac-crashfix-patch.patch | 532 ------------
...d-mozIThirdPartyUtil.getFirstPartyURI-API.patch | 154 ++++
.../0020-Add-canvas-image-extraction-prompt.patch | 548 ++++++++++++
...d-mozIThirdPartyUtil.getFirstPartyURI-API.patch | 155 ----
.../0021-Add-canvas-image-extraction-prompt.patch | 551 ------------
...nt-window-coordinates-for-mouse-event-scr.patch | 77 ++
...se-physical-screen-info.-via-window-and-w.patch | 310 +++++++
...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 | 466 ++++++++++
...not-expose-system-colors-to-CSS-or-canvas.patch | 537 ------------
...solate-the-Image-Cache-per-url-bar-domain.patch | 912 ++++++++++++++++++++
.../0025-nsIHTTPChannel.redirectTo-API.patch | 474 ++++++++++
...26-Isolate-DOM-storage-to-first-party-URI.patch | 776 +++++++++++++++++
34 files changed, 4673 insertions(+), 2668 deletions(-)
diff --git a/src/current-patches/firefox/0001-Block-Components.interfaces-from-content.patch b/src/current-patches/firefox/0001-Block-Components.interfaces-from-content.patch
new file mode 100644
index 0000000..7a2faac
--- /dev/null
+++ b/src/current-patches/firefox/0001-Block-Components.interfaces-from-content.patch
@@ -0,0 +1,37 @@
+From 60f2318ffa6e9a3bdb37192378e0711aa14bd772 Mon Sep 17 00:00:00 2001
+From: Mike Perry <mikeperry-git at torproject.org>
+Date: Tue, 4 Dec 2012 15:41:09 -0800
+Subject: [PATCH 01/26] Block Components.interfaces from content
+
+This patch removes the ability of content script to access
+Components.interfaces.*.
+
+Components.interfaces is useful for fingerprinting the platform, OS, and
+Firebox version.
+
+It appears to have no other legitimate use. See also:
+https://bugzilla.mozilla.org/show_bug.cgi?id=429070
+https://trac.torproject.org/projects/tor/ticket/2874
+
+Note: We no longer block Components.lookupMethod, because we no longer rely on
+JS hooks for fingerprinting defenses.
+---
+ js/xpconnect/src/XPCComponents.cpp | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp
+index 3a14254..4040349 100644
+--- a/js/xpconnect/src/XPCComponents.cpp
++++ b/js/xpconnect/src/XPCComponents.cpp
+@@ -4838,7 +4838,7 @@ 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", nullptr};
++ static const char* allowed[] = { "results", nullptr};
+ *_retval = xpc_CheckAccessList(propertyName, allowed);
+ return NS_OK;
+ }
+--
+1.7.5.4
+
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
deleted file mode 100644
index 1a82800..0000000
--- a/src/current-patches/firefox/0001-Block-Components.interfaces-lookupMethod-from-conten.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-From 1c2ccbea73720db5405602e4033c69b706068a8b Mon Sep 17 00:00:00 2001
-From: Mike Perry <mikeperry-git at 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
index fa23d93..cb04eae 100644
--- a/src/current-patches/firefox/0002-Make-Permissions-Manager-memory-only.patch
+++ b/src/current-patches/firefox/0002-Make-Permissions-Manager-memory-only.patch
@@ -1,7 +1,7 @@
-From cd983b1b57b1f4ae10c8deec5aa12ec957fdc855 Mon Sep 17 00:00:00 2001
+From db27e73d62d4f680b98a4ad9e7493b62070e23ae Mon Sep 17 00:00:00 2001
From: Mike Perry <mikeperry-git at torproject.org>
-Date: Wed, 1 Feb 2012 15:45:16 -0800
-Subject: [PATCH 02/24] Make Permissions Manager memory-only
+Date: Tue, 4 Dec 2012 15:45:59 -0800
+Subject: [PATCH 02/26] 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
@@ -16,21 +16,21 @@ https://trac.torproject.org/projects/tor/ticket/2950
1 files changed, 31 insertions(+), 3 deletions(-)
diff --git a/extensions/cookie/nsPermissionManager.cpp b/extensions/cookie/nsPermissionManager.cpp
-index 67eb216..12cc7cf 100644
+index 9c50080..4102408 100644
--- a/extensions/cookie/nsPermissionManager.cpp
+++ b/extensions/cookie/nsPermissionManager.cpp
-@@ -58,6 +58,10 @@
- #include "mozStorageHelper.h"
- #include "mozStorageCID.h"
- #include "nsXULAppAPI.h"
+@@ -24,6 +24,10 @@
+ #include "nsIPrincipal.h"
+ #include "nsContentUtils.h"
+ #include "nsIScriptSecurityManager.h"
+#include "nsCOMPtr.h"
+#include "nsIPrefService.h"
+#include "nsIPrefBranch.h"
+#include "nsIPrefBranch2.h"
- static nsPermissionManager *gPermissionManager = nsnull;
+ static nsPermissionManager *gPermissionManager = nullptr;
-@@ -203,6 +207,11 @@ nsPermissionManager::Init()
+@@ -301,6 +305,11 @@ nsPermissionManager::Init()
mObserverService->AddObserver(this, "profile-do-change", true);
}
@@ -42,7 +42,7 @@ index 67eb216..12cc7cf 100644
if (IsChildProcess()) {
// Get the permissions from the parent process
InfallibleTArray<IPC::Permission> perms;
-@@ -251,8 +260,18 @@ nsPermissionManager::InitDB(bool aRemoveFile)
+@@ -356,8 +365,18 @@ nsPermissionManager::InitDB(bool aRemoveFile)
if (!storage)
return NS_ERROR_UNEXPECTED;
@@ -62,7 +62,7 @@ index 67eb216..12cc7cf 100644
NS_ENSURE_SUCCESS(rv, rv);
bool ready;
-@@ -262,7 +281,11 @@ nsPermissionManager::InitDB(bool aRemoveFile)
+@@ -367,7 +386,11 @@ nsPermissionManager::InitDB(bool aRemoveFile)
rv = permissionsFile->Remove(false);
NS_ENSURE_SUCCESS(rv, rv);
@@ -75,7 +75,7 @@ index 67eb216..12cc7cf 100644
NS_ENSURE_SUCCESS(rv, rv);
mDBConn->GetConnectionReady(&ready);
-@@ -783,7 +806,12 @@ NS_IMETHODIMP nsPermissionManager::Observe(nsISupports *aSubject, const char *aT
+@@ -1052,7 +1075,12 @@ NS_IMETHODIMP nsPermissionManager::Observe(nsISupports *aSubject, const char *aT
{
ENSURE_NOT_CHILD_PROCESS;
@@ -88,7 +88,7 @@ index 67eb216..12cc7cf 100644
+ } 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())) {
+ mIsShuttingDown = true;
--
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
index b10fb85..a367d67 100644
--- 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
@@ -1,25 +1,26 @@
-From f100a7979e1a44863a8a67a09743f0e17b5dd14e Mon Sep 17 00:00:00 2001
-From: Mike Perry <mikeperry-git at fscked.org>
-Date: Fri, 19 Aug 2011 17:58:23 -0700
-Subject: [PATCH 03/24] Make Intermediate Cert Store memory-only.
+From ac380269829788ddbd721d642ec57af0fff350de Mon Sep 17 00:00:00 2001
+From: Mike Perry <mikeperry-git at torproject.org>
+Date: Tue, 4 Dec 2012 15:51:07 -0800
+Subject: [PATCH 03/26] 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(-)
+ security/manager/ssl/src/nsNSSComponent.cpp | 17 +++++++++++++++--
+ 1 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/security/manager/ssl/src/nsNSSComponent.cpp b/security/manager/ssl/src/nsNSSComponent.cpp
-index a08c4ef..0ec3713 100644
+index c9205bc..159985c 100644
--- a/security/manager/ssl/src/nsNSSComponent.cpp
+++ b/security/manager/ssl/src/nsNSSComponent.cpp
-@@ -1730,8 +1730,21 @@ nsNSSComponent::InitializeNSS(bool showWarningBox)
+@@ -1736,8 +1736,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;
+ uint32_t init_flags = NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE;
- SECStatus init_rv = ::NSS_Initialize(profileStr.get(), "", "",
+- SECMOD_DB, init_flags);
+ bool nocertdb = false;
+ mPrefBranch->GetBoolPref("security.nocertdb", &nocertdb);
+
@@ -33,7 +34,7 @@ index a08c4ef..0ec3713 100644
+ init_rv = ::NSS_NoDB_Init(NULL);
+ } else {
+ init_rv = ::NSS_Initialize(profileStr.get(), "", "",
- SECMOD_DB, init_flags);
++ SECMOD_DB, init_flags);
+ }
if (init_rv != SECSuccess) {
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
index f3afa97..c1ca50a 100644
--- a/src/current-patches/firefox/0004-Add-a-string-based-cacheKey.patch
+++ b/src/current-patches/firefox/0004-Add-a-string-based-cacheKey.patch
@@ -1,7 +1,7 @@
-From d674d09bc233d200b1ebc47f8e6ac4ebd6e4225a Mon Sep 17 00:00:00 2001
-From: Mike Perry <mikeperry-git at fscked.org>
-Date: Fri, 2 Sep 2011 20:47:02 -0700
-Subject: [PATCH 04/24] Add a string-based cacheKey.
+From e991fbe8787ad8a50621f6a11633a121910d77fb Mon Sep 17 00:00:00 2001
+From: Mike Perry <mikeperry-git at torproject.org>
+Date: Tue, 4 Dec 2012 16:01:42 -0800
+Subject: [PATCH 04/26] Add a string-based cacheKey.
Used for isolating cache according to same-origin policy.
---
@@ -11,10 +11,10 @@ Used for isolating cache according to same-origin policy.
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
+index 3119dd9..fd2ec89 100644
--- a/netwerk/base/public/nsICachingChannel.idl
+++ b/netwerk/base/public/nsICachingChannel.idl
-@@ -98,6 +98,13 @@ interface nsICachingChannel : nsICacheInfoChannel
+@@ -65,6 +65,13 @@ interface nsICachingChannel : nsICacheInfoChannel
attribute nsISupports cacheKey;
/**
@@ -29,10 +29,10 @@ index 2da46d6..4ee5774 100644
* 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
+index f1ae96a..9223d08 100644
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
-@@ -2392,6 +2392,12 @@ nsHttpChannel::AssembleCacheKey(const char *spec, PRUint32 postID,
+@@ -2721,6 +2721,12 @@ nsHttpChannel::AssembleCacheKey(const char *spec, uint32_t postID,
cacheKey.Append(buf);
}
@@ -45,8 +45,8 @@ index dec2a83..97bd84c 100644
if (!cacheKey.IsEmpty()) {
cacheKey.AppendLiteral("uri=");
}
-@@ -4695,6 +4701,22 @@ nsHttpChannel::SetCacheForOfflineUse(bool value)
- }
+@@ -5179,6 +5185,22 @@ nsHttpChannel::SetCacheTokenCachedCharset(const nsACString &aCharset)
+ //-----------------------------------------------------------------------------
NS_IMETHODIMP
+nsHttpChannel::GetCacheDomain(nsACString &value)
@@ -65,17 +65,17 @@ index dec2a83..97bd84c 100644
+}
+
+NS_IMETHODIMP
- nsHttpChannel::GetOfflineCacheClientID(nsACString &value)
+ nsHttpChannel::GetCacheToken(nsISupports **token)
{
- value = mOfflineCacheClientID;
+ NS_ENSURE_ARG_POINTER(token);
diff --git a/netwerk/protocol/http/nsHttpChannel.h b/netwerk/protocol/http/nsHttpChannel.h
-index 88ce469..53538cf 100644
+index 5b8c654..5b4ddb9 100644
--- a/netwerk/protocol/http/nsHttpChannel.h
+++ b/netwerk/protocol/http/nsHttpChannel.h
-@@ -303,6 +303,7 @@ private:
- nsCOMPtr<nsICacheEntryDescriptor> mOfflineCacheEntry;
+@@ -298,6 +298,7 @@ private:
nsCacheAccessMode mOfflineCacheAccess;
- nsCString mOfflineCacheClientID;
+ uint32_t mOfflineCacheLastModifiedTime;
+ nsCOMPtr<nsIApplicationCache> mApplicationCacheForWrite;
+ nsCString mCacheDomain;
// auth specific data
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
index e7a831e..f452b0f 100644
--- a/src/current-patches/firefox/0005-Block-all-plugins-except-flash.patch
+++ b/src/current-patches/firefox/0005-Block-all-plugins-except-flash.patch
@@ -1,7 +1,7 @@
-From 88a390822d232ba037de1f15091977ca7e1064bf Mon Sep 17 00:00:00 2001
+From 1ff6423fed745b7efd041fb6397065bd39a16d1a Mon Sep 17 00:00:00 2001
From: Mike Perry <mikeperry-git at torproject.org>
-Date: Wed, 1 Feb 2012 15:50:15 -0800
-Subject: [PATCH 05/24] Block all plugins except flash.
+Date: Tue, 4 Dec 2012 16:03:13 -0800
+Subject: [PATCH 05/26] 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
@@ -17,12 +17,12 @@ on a better way. Until then, it is delta-darwinism for us.
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
+index b4233fa..1fe506a 100644
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
-@@ -1968,6 +1968,35 @@ bool nsPluginHost::IsDuplicatePlugin(nsPluginTag * aPluginTag)
- return false;
- }
+@@ -2040,6 +2040,35 @@ struct CompareFilesByTime
+
+ } // anonymous namespace
+PRBool nsPluginHost::GhettoBlacklist(nsIFile *pluginFile)
+{
@@ -56,7 +56,7 @@ index 992bcd4..f56f231 100644
typedef NS_NPAPIPLUGIN_CALLBACK(char *, NP_GETMIMEDESCRIPTION)(void);
nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
-@@ -2101,6 +2130,10 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
+@@ -2144,6 +2173,10 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
continue;
}
@@ -68,10 +68,10 @@ index 992bcd4..f56f231 100644
if (!pluginTag) {
nsPluginFile pluginFile(localfile);
diff --git a/dom/plugins/base/nsPluginHost.h b/dom/plugins/base/nsPluginHost.h
-index 39a8891..c262abf 100644
+index fdaa76d..9e328a2 100644
--- a/dom/plugins/base/nsPluginHost.h
+++ b/dom/plugins/base/nsPluginHost.h
-@@ -278,6 +278,8 @@ private:
+@@ -261,6 +261,8 @@ private:
// Loads all cached plugins info into mCachedPlugins
nsresult ReadPluginInfo();
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
index 17af793..32eb7c2 100644
--- 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
@@ -1,7 +1,7 @@
-From 71ba98d81a6ecada62af4d2ee03be050d371d996 Mon Sep 17 00:00:00 2001
+From 60c8edec8d90c6661ab5577970800c01b1205e02 Mon Sep 17 00:00:00 2001
From: Mike Perry <mikeperry-git at fscked.org>
Date: Thu, 8 Sep 2011 08:40:17 -0700
-Subject: [PATCH 06/24] Make content pref service memory-only + clearable
+Subject: [PATCH 06/26] 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
@@ -11,10 +11,10 @@ other site prefs?).
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
+index ed8ad2e..794c9f3 100644
--- a/toolkit/components/contentprefs/nsContentPrefService.js
+++ b/toolkit/components/contentprefs/nsContentPrefService.js
-@@ -1240,7 +1240,7 @@ ContentPrefService.prototype = {
+@@ -1206,7 +1206,7 @@ ContentPrefService.prototype = {
var dbConnection;
@@ -23,7 +23,7 @@ index adfb650..1619d5f 100644
dbConnection = this._dbCreate(dbService, dbFile);
else {
try {
-@@ -1288,7 +1288,7 @@ ContentPrefService.prototype = {
+@@ -1254,7 +1254,7 @@ ContentPrefService.prototype = {
},
_dbCreate: function ContentPrefService__dbCreate(aDBService, aDBFile) {
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
index cc496d3..80c55c2 100644
--- 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
@@ -1,7 +1,7 @@
-From 12579def59d67416b841f6b0a6eadfd94bba72e9 Mon Sep 17 00:00:00 2001
-From: Mike Perry <mikeperry-git at fscked.org>
-Date: Sun, 9 Oct 2011 22:50:07 -0700
-Subject: [PATCH 07/24] Make Tor Browser exit when not launched from Vidalia
+From 5f9d3e18c44f8b25f34e68fb6b35b229d3561559 Mon Sep 17 00:00:00 2001
+From: Mike Perry <mikeperry-git at torproject.org>
+Date: Tue, 4 Dec 2012 16:29:24 -0800
+Subject: [PATCH 07/26] 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
@@ -12,35 +12,33 @@ 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(-)
+ browser/base/content/browser.js | 13 +++++++++++++
+ 1 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
-index f16a0c5..20e3666 100644
+index 80174dc..1fc137c 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
-@@ -1217,6 +1217,21 @@ function BrowserStartup() {
+@@ -1096,6 +1096,19 @@ var gBrowserInit = {
+ // setup simple gestures support
+ gGestureSupport.init(true);
- 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 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();
+ if (uriToLoad && uriToLoad != "about:blank") {
+ if (uriToLoad instanceof Ci.nsISupportsArray) {
--
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
index 39e1483..9b3de6b 100644
--- a/src/current-patches/firefox/0008-Disable-SSL-Session-ID-tracking.patch
+++ b/src/current-patches/firefox/0008-Disable-SSL-Session-ID-tracking.patch
@@ -1,7 +1,7 @@
-From 7586e413761858ce705d25d4a1673e608a162bed Mon Sep 17 00:00:00 2001
+From 376f1f9b86d4b04e121d25553feed2c4380088d2 Mon Sep 17 00:00:00 2001
From: Mike Perry <mikeperry-git at fscked.org>
Date: Wed, 7 Dec 2011 19:36:38 -0800
-Subject: [PATCH 08/24] Disable SSL Session ID tracking.
+Subject: [PATCH 08/26] 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
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
index e693c71..a366141 100644
--- 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
@@ -1,7 +1,7 @@
-From 9c6f997dd9a44336af9a1db17f5b680cc80a0e6c Mon Sep 17 00:00:00 2001
+From 74b6b99f7ac6e4a4153613feeafef53a5c3b9a4a Mon Sep 17 00:00:00 2001
From: Mike Perry <mikeperry-git at torproject.org>
-Date: Wed, 1 Feb 2012 15:53:28 -0800
-Subject: [PATCH 09/24] Provide an observer event to close persistent
+Date: Fri, 7 Sep 2012 16:18:26 -0700
+Subject: [PATCH 09/26] Provide an observer event to close persistent
connections
We need to prevent linkability across "New Identity", which includes closing
@@ -11,20 +11,20 @@ keep-alive connections.
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
+index d897a2c..e33ff08 100644
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
-@@ -325,6 +325,7 @@ nsHttpHandler::Init()
+@@ -312,6 +312,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);
++ mObserverService->AddObserver(this, "net:prune-all-connections", true);
+ mObserverService->AddObserver(this, "net:failed-to-process-uri-content", true);
}
- return NS_OK;
-@@ -1504,6 +1505,12 @@ nsHttpHandler::Observe(nsISupports *subject,
- mConnMgr->PruneDeadConnections();
- }
+@@ -1576,6 +1577,12 @@ nsHttpHandler::Observe(nsISupports *subject,
+ if (uri && mConnMgr)
+ mConnMgr->ReportFailedToProcess(uri);
}
+ else if (strcmp(topic, "net:prune-all-connections") == 0) {
+ if (mConnMgr) {
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
index 14e584c..9e49285 100644
--- 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
@@ -1,17 +1,17 @@
-From 8f97f2f36adb9e4416f3d19af10880c800c846c2 Mon Sep 17 00:00:00 2001
+From 278e285820d9082d2be161fbdee6c230a4477204 Mon Sep 17 00:00:00 2001
From: Kathleen Brade <brade at pearlcrescent.com>
-Date: Thu, 4 Oct 2012 14:28:48 -0400
-Subject: [PATCH 10/24] Limit device and system specific CSS Media Queries.
+Date: Wed, 28 Nov 2012 09:49:40 -0500
+Subject: [PATCH 10/26] Limit device and system specific CSS Media Queries.
---
- layout/style/nsMediaFeatures.cpp | 71 ++++++++++++++++++++++++-------------
- 1 files changed, 46 insertions(+), 25 deletions(-)
+ layout/style/nsMediaFeatures.cpp | 68 +++++++++++++++++++++++++-------------
+ 1 files changed, 45 insertions(+), 23 deletions(-)
diff --git a/layout/style/nsMediaFeatures.cpp b/layout/style/nsMediaFeatures.cpp
-index 6eca06e..5b1df7e 100644
+index d5741ea..5f2e6dd 100644
--- a/layout/style/nsMediaFeatures.cpp
+++ b/layout/style/nsMediaFeatures.cpp
-@@ -130,6 +130,9 @@ GetDeviceContextFor(nsPresContext* aPresContext)
+@@ -98,6 +98,9 @@ GetDeviceContextFor(nsPresContext* aPresContext)
static nsSize
GetDeviceSize(nsPresContext* aPresContext)
{
@@ -21,7 +21,7 @@ index 6eca06e..5b1df7e 100644
nsSize size;
if (aPresContext->IsRootPaginatedDocument())
// We want the page size, including unprintable areas and margins.
-@@ -140,6 +143,7 @@ GetDeviceSize(nsPresContext* aPresContext)
+@@ -108,6 +111,7 @@ GetDeviceSize(nsPresContext* aPresContext)
GetDeviceContextFor(aPresContext)->
GetDeviceSurfaceDimensions(size.width, size.height);
return size;
@@ -29,36 +29,7 @@ index 6eca06e..5b1df7e 100644
}
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
+@@ -204,13 +208,17 @@ static nsresult
GetColor(nsPresContext* aPresContext, const nsMediaFeature*,
nsCSSValue& aResult)
{
@@ -67,9 +38,9 @@ index 6eca06e..5b1df7e 100644
- // 424386).
- // FIXME: On a monochrome device, return 0!
- nsDeviceContext *dx = GetDeviceContextFor(aPresContext);
-- PRUint32 depth;
+- uint32_t depth;
- dx->GetDepth(depth);
-+ PRUint32 depth = 24; // Always return 24 to non-chrome callers.
++ uint32_t depth = 24; // Always return 24 to non-chrome callers.
+
+ if (aPresContext->IsChrome()) {
+ // FIXME: This implementation is bogus. nsDeviceContext
@@ -83,25 +54,42 @@ index 6eca06e..5b1df7e 100644
// 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
+@@ -248,18 +256,23 @@ 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());
+- // Resolution measures device pixels per CSS (inch/cm/pixel). We
+- // return it in device pixels per CSS inches.
+- //
+- // However, on platforms where the CSS viewport is not fixed to the
+- // screen viewport, use the device resolution instead (bug 779527).
+- nsIPresShell *shell = aPresContext->PresShell();
+- float appUnitsPerInch = shell->GetIsViewportOverridden() ?
+- GetDeviceContextFor(aPresContext)->AppUnitsPerPhysicalInch() :
+- nsPresContext::AppUnitsPerCSSInch();
+-
+- float dpi = appUnitsPerInch /
+ 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());
++ // Resolution measures device pixels per CSS (inch/cm/pixel). We
++ // return it in device pixels per CSS inches.
++ //
++ // However, on platforms where the CSS viewport is not fixed to the
++ // screen viewport, use the device resolution instead (bug 779527).
++ nsIPresShell *shell = aPresContext->PresShell();
++ float appUnitsPerInch = shell->GetIsViewportOverridden() ?
++ GetDeviceContextFor(aPresContext)->AppUnitsPerPhysicalInch() :
++ nsPresContext::AppUnitsPerCSSInch();
++
++ dpi = appUnitsPerInch /
+ float(aPresContext->AppUnitsPerDevPixel());
+ }
+
aResult.SetFloatValue(dpi, eCSSUnit_Inch);
return NS_OK;
}
-@@ -311,8 +324,12 @@ static nsresult
+@@ -288,8 +301,12 @@ static nsresult
GetDevicePixelRatio(nsPresContext* aPresContext, const nsMediaFeature*,
nsCSSValue& aResult)
{
@@ -116,10 +104,11 @@ index 6eca06e..5b1df7e 100644
return NS_OK;
}
-@@ -320,18 +337,21 @@ static nsresult
+@@ -297,20 +314,24 @@ static nsresult
GetSystemMetric(nsPresContext* aPresContext, const nsMediaFeature* aFeature,
nsCSSValue& aResult)
{
++ aResult.Reset();
+ if (aPresContext->IsChrome()) {
NS_ABORT_IF_FALSE(aFeature->mValueType == nsMediaFeature::eBoolInteger,
"unexpected type");
@@ -135,16 +124,20 @@ index 6eca06e..5b1df7e 100644
GetWindowsTheme(nsPresContext* aPresContext, const nsMediaFeature* aFeature,
nsCSSValue& aResult)
{
-+ if (aPresContext->IsChrome()) {
- aResult.Reset();
+- aResult.Reset();
++ aResult.Reset();
#ifdef XP_WIN
- PRUint8 windowsThemeId =
-@@ -350,7 +370,8 @@ GetWindowsTheme(nsPresContext* aPresContext, const nsMediaFeature* aFeature,
++ if (aPresContext->IsChrome()) {
+ uint8_t windowsThemeId =
+ nsCSSRuleProcessor::GetWindowsThemeIdentifier();
+
+@@ -326,8 +347,9 @@ GetWindowsTheme(nsPresContext* aPresContext, const nsMediaFeature* aFeature,
+ break;
}
}
++ }
#endif
- return NS_OK;
-+ }
+ return NS_OK;
}
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
index ff9e618..c6eb24f 100644
--- 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
@@ -1,7 +1,7 @@
-From cb3a6f45dd2c15d6b75084e1a4dded18ed638632 Mon Sep 17 00:00:00 2001
+From 9ae4f468446cd1edef028d2b60ccca91cad2bc2e Mon Sep 17 00:00:00 2001
From: Mike Perry <mikeperry-git at torproject.org>
-Date: Wed, 1 Feb 2012 16:01:21 -0800
-Subject: [PATCH 11/24] Limit the number of fonts per document.
+Date: Wed, 5 Dec 2012 12:25:21 -0800
+Subject: [PATCH 11/26] Limit the number of fonts per document.
We create two prefs:
browser.display.max_font_count and browser.display.max_font_attempts.
@@ -17,25 +17,39 @@ 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-linkability
---
+ gfx/thebes/gfxPangoFonts.cpp | 1 +
layout/base/nsPresContext.cpp | 100 +++++++++++++++++++++++++++++++++++++++++
layout/base/nsPresContext.h | 9 ++++
- layout/style/nsRuleNode.cpp | 13 ++++-
- 3 files changed, 119 insertions(+), 3 deletions(-)
+ layout/style/nsCSSParser.cpp | 1 +
+ layout/style/nsRuleNode.cpp | 14 +++++-
+ 5 files changed, 122 insertions(+), 3 deletions(-)
+diff --git a/gfx/thebes/gfxPangoFonts.cpp b/gfx/thebes/gfxPangoFonts.cpp
+index c94a299..88c8b8e 100644
+--- a/gfx/thebes/gfxPangoFonts.cpp
++++ b/gfx/thebes/gfxPangoFonts.cpp
+@@ -1408,6 +1408,7 @@ gfxFcFontSet::SortPreferredFonts(bool &aWaitForUserFont)
+ const nsTArray< nsCountedRef<FcPattern> > *familyFonts = nullptr;
+
+ // Is this an @font-face family?
++ // XXX: Make use of this + pass to nsFont??
+ bool isUserFont = false;
+ if (mUserFontSet) {
+ // Have some @font-face definitions
diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp
-index e1587db..9690d9c 100644
+index d47460a..8064fb4 100644
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
-@@ -98,6 +98,8 @@
- #include "FrameLayerBuilder.h"
+@@ -63,6 +63,8 @@
#include "nsDOMMediaQueryList.h"
#include "nsSMILAnimationController.h"
+ #include "mozilla/css/ImageLoader.h"
+#include "nsString.h"
+#include "nsUnicharUtils.h"
#ifdef IBMBIDI
#include "nsBidiPresUtils.h"
-@@ -706,6 +708,10 @@ nsPresContext::GetUserPreferences()
+@@ -712,6 +714,10 @@ nsPresContext::GetUserPreferences()
// * use fonts?
mUseDocumentFonts =
Preferences::GetInt("browser.display.use_document_fonts") != 0;
@@ -46,7 +60,7 @@ index e1587db..9690d9c 100644
// * replace backslashes with Yen signs? (bug 245770)
mEnableJapaneseTransform =
-@@ -1300,6 +1306,100 @@ nsPresContext::GetDefaultFont(PRUint8 aFontID) const
+@@ -1328,6 +1334,100 @@ nsPresContext::GetDefaultFont(uint8_t aFontID, nsIAtom *aLanguage) const
return font;
}
@@ -148,10 +162,10 @@ index e1587db..9690d9c 100644
nsPresContext::SetFullZoom(float aZoom)
{
diff --git a/layout/base/nsPresContext.h b/layout/base/nsPresContext.h
-index ecd01d8..552a69a 100644
+index 5f0f528..ffe4766 100644
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
-@@ -548,6 +548,13 @@ public:
+@@ -467,6 +467,13 @@ public:
}
}
@@ -162,11 +176,11 @@ index ecd01d8..552a69a 100644
+ 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;
+ /**
+ * Get the minimum font size for the specified language. If aLanguage
+ * is nullptr, then the document's language is used.
+@@ -1104,6 +1111,8 @@ protected:
+ uint32_t mInterruptChecksToSkip;
mozilla::TimeStamp mReflowStartTime;
+ PRInt32 mMaxFontAttempts;
@@ -174,32 +188,49 @@ index ecd01d8..552a69a 100644
unsigned mHasPendingInterrupt : 1;
unsigned mInterruptsEnabled : 1;
+diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp
+index 37a19c4..30fd021 100644
+--- a/layout/style/nsCSSParser.cpp
++++ b/layout/style/nsCSSParser.cpp
+@@ -8719,6 +8719,7 @@ CSSParserImpl::ParseFontSrc(nsCSSValue& aValue)
+ return false;
+ }
+
++ // XXX: Getting closer...
+ // the style parameters to the nsFont constructor are ignored,
+ // because it's only being used to call EnumerateFamilies
+ nsFont font(family, 0, 0, 0, 0, 0, 0);
diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp
-index 27336bf..827585a 100644
+index 64504fb..33ce21e 100644
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
-@@ -3091,6 +3091,7 @@ nsRuleNode::ComputeFontData(void* aStartStruct,
+@@ -2954,6 +2954,7 @@ nsRuleNode::SetFont(nsPresContext* aPresContext, nsStyleContext* aContext,
+ aPresContext->GetDefaultFont(kPresContext_DefaultVariableFont_ID,
+ aFont->mLanguage);
+
++ // XXX: Bleh. Disable these somehow?
+ // -moz-system-font: enum (never inherit!)
+ MOZ_STATIC_ASSERT(
+ NS_STYLE_FONT_CAPTION == LookAndFeel::eFont_Caption &&
+@@ -3439,14 +3440,15 @@ nsRuleNode::ComputeFontData(void* aStartStruct,
- // See if there is a minimum font-size constraint to honor
- nscoord minimumFontSize = mPresContext->MinFontSize();
-+ PRBool isXUL = PR_FALSE;
+ bool useDocumentFonts =
+ mPresContext->GetCachedBoolPref(kPresContext_UseDocumentFonts);
++ bool isXUL = PR_FALSE;
- if (minimumFontSize < 0)
- minimumFontSize = 0;
-@@ -3102,10 +3103,10 @@ nsRuleNode::ComputeFontData(void* aStartStruct,
+ // See if we are in the chrome
// 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()) {
+ // document fonts (overriding the useDocumentFonts flag).
+- if (!useDocumentFonts && 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;
++ isXUL = true;
}
-@@ -3120,9 +3121,13 @@ nsRuleNode::ComputeFontData(void* aStartStruct,
+ // Figure out if we are a generic font
+@@ -3460,9 +3462,13 @@ nsRuleNode::ComputeFontData(void* aStartStruct,
// generic?
nsFont::GetGenericID(font->mFont.name, &generic);
@@ -214,8 +245,8 @@ index 27336bf..827585a 100644
// 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);
+@@ -3498,6 +3504,8 @@ nsRuleNode::ComputeFontData(void* aStartStruct,
+ font);
}
+ if (font->mGenericID == kGenericFont_NONE)
diff --git a/src/current-patches/firefox/0012-Rebrand-Firefox-to-TorBrowser.patch b/src/current-patches/firefox/0012-Rebrand-Firefox-to-TorBrowser.patch
index e627238..6fc03f6 100644
--- a/src/current-patches/firefox/0012-Rebrand-Firefox-to-TorBrowser.patch
+++ b/src/current-patches/firefox/0012-Rebrand-Firefox-to-TorBrowser.patch
@@ -1,7 +1,7 @@
-From 5820fc300fe1cae27752673e8721a19e70bf727c Mon Sep 17 00:00:00 2001
-From: Erinn Clark <erinn at torproject.org>
-Date: Wed, 25 Apr 2012 09:14:00 -0300
-Subject: [PATCH 12/24] Rebrand Firefox to TorBrowser
+From e0675863770a2a33fef70079a73233a9e78a3c48 Mon Sep 17 00:00:00 2001
+From: Mike Perry <mikeperry-git at torproject.org>
+Date: Tue, 28 Aug 2012 18:05:11 -0700
+Subject: [PATCH 12/26] 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.
@@ -12,18 +12,24 @@ branding is done by images and icons.
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
+index 55f3f18..33102b0 100644
--- a/browser/branding/official/configure.sh
+++ b/browser/branding/official/configure.sh
-@@ -1,2 +1,2 @@
+@@ -2,5 +2,5 @@
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
-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
+index 8e7f6c9..76e405d 100644
--- a/browser/branding/official/locales/en-US/brand.dtd
+++ b/browser/branding/official/locales/en-US/brand.dtd
-@@ -1,4 +1,4 @@
+@@ -2,7 +2,7 @@
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
-<!ENTITY brandShortName "Firefox">
-<!ENTITY brandFullName "Mozilla Firefox">
-<!ENTITY vendorShortName "Mozilla">
@@ -32,10 +38,13 @@ index 142d79b..c137e04 100644
+<!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
+index 4a67c55..9ae168e 100644
--- a/browser/branding/official/locales/en-US/brand.properties
+++ b/browser/branding/official/locales/en-US/brand.properties
-@@ -1,6 +1,6 @@
+@@ -2,9 +2,9 @@
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
-brandShortName=Firefox
-brandFullName=Mozilla Firefox
-vendorShortName=Mozilla
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
index 1ad0972..f9f938f 100644
--- a/src/current-patches/firefox/0013-Make-Download-manager-memory-only.patch
+++ b/src/current-patches/firefox/0013-Make-Download-manager-memory-only.patch
@@ -1,7 +1,7 @@
-From 28178fb406d86b317b13b16ade3b06e5e1500c7e Mon Sep 17 00:00:00 2001
+From 2b0cc620b5d9af06262c9fdfc1ef8f34b5682859 Mon Sep 17 00:00:00 2001
From: Mike Perry <mikeperry-git at torproject.org>
-Date: Wed, 25 Apr 2012 13:39:35 -0700
-Subject: [PATCH 13/24] Make Download manager memory only.
+Date: Tue, 4 Dec 2012 16:05:55 -0800
+Subject: [PATCH 13/26] Make Download manager memory only.
Solves https://trac.torproject.org/projects/tor/ticket/4017.
@@ -18,10 +18,10 @@ this breaks enough times in conflict.
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
+index 024686f..7845544 100644
--- a/toolkit/components/downloads/nsDownloadManager.cpp
+++ b/toolkit/components/downloads/nsDownloadManager.cpp
-@@ -1992,7 +1992,7 @@ nsDownloadManager::Observe(nsISupports *aSubject,
+@@ -2002,7 +2002,7 @@ nsDownloadManager::Observe(nsISupports *aSubject,
if (NS_LITERAL_STRING("memory").Equals(aData))
return SwitchDatabaseTypeTo(DATABASE_MEMORY);
else if (NS_LITERAL_STRING("disk").Equals(aData))
@@ -30,7 +30,7 @@ index 00a6e7d..2e83f61 100644
}
else if (strcmp(aTopic, "alertclickcallback") == 0) {
nsCOMPtr<nsIDownloadManagerUI> dmui =
-@@ -2069,7 +2069,7 @@ nsDownloadManager::OnLeavePrivateBrowsingMode()
+@@ -2079,7 +2079,7 @@ nsDownloadManager::OnLeavePrivateBrowsingMode()
(void)ResumeAllDownloads(false);
// Switch back to the on-disk DB again
@@ -40,10 +40,10 @@ index 00a6e7d..2e83f61 100644
mInPrivateBrowsing = false;
}
diff --git a/toolkit/components/downloads/nsDownloadManager.h b/toolkit/components/downloads/nsDownloadManager.h
-index 54312e4..cb63b52 100644
+index bbe7f39..6bdad89 100644
--- a/toolkit/components/downloads/nsDownloadManager.h
+++ b/toolkit/components/downloads/nsDownloadManager.h
-@@ -90,7 +90,7 @@ public:
+@@ -54,7 +54,7 @@ public:
virtual ~nsDownloadManager();
nsDownloadManager() :
@@ -51,7 +51,7 @@ index 54312e4..cb63b52 100644
+ mDBType(DATABASE_MEMORY)
, mInPrivateBrowsing(false)
#ifdef DOWNLOAD_SCANNER
- , mScanner(nsnull)
+ , mScanner(nullptr)
--
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
index adbd3d4..4cb626f 100644
--- 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
@@ -1,7 +1,7 @@
-From 2a80e84755c97cf4ff3ab63bda1bd5f0936d9594 Mon Sep 17 00:00:00 2001
+From a2de75def3f8ac88a5f5092ab9bd6815d088e7d5 Mon Sep 17 00:00:00 2001
From: Mike Perry <mikeperry-git at torproject.org>
Date: Wed, 25 Apr 2012 15:03:46 -0700
-Subject: [PATCH 14/24] Add DDG and StartPage to Omnibox.
+Subject: [PATCH 14/26] 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.
diff --git a/src/current-patches/firefox/0015-Make-nsICacheService.EvictEntries-synchronous.patch b/src/current-patches/firefox/0015-Make-nsICacheService.EvictEntries-synchronous.patch
index 93a989b..87547a7 100644
--- a/src/current-patches/firefox/0015-Make-nsICacheService.EvictEntries-synchronous.patch
+++ b/src/current-patches/firefox/0015-Make-nsICacheService.EvictEntries-synchronous.patch
@@ -1,36 +1,33 @@
-From 20c94cb890a8872c07ba13686e293ca147b85cd6 Mon Sep 17 00:00:00 2001
+From 0d030acc527aa206582e3f19219f4fa128f98bef Mon Sep 17 00:00:00 2001
From: Mike Perry <mikeperry-git at torproject.org>
-Date: Tue, 1 May 2012 15:02:03 -0700
-Subject: [PATCH 15/24] Make nsICacheService.EvictEntries synchronous
+Date: Tue, 4 Dec 2012 16:25:52 -0800
+Subject: [PATCH 15/26] 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(-)
+ netwerk/cache/nsCacheService.cpp | 14 +++++++++++++-
+ 1 files changed, 13 insertions(+), 1 deletions(-)
diff --git a/netwerk/cache/nsCacheService.cpp b/netwerk/cache/nsCacheService.cpp
-index 83ce887..e9f1a76 100644
+index e88de40..4225742 100644
--- a/netwerk/cache/nsCacheService.cpp
+++ b/netwerk/cache/nsCacheService.cpp
-@@ -1316,10 +1316,21 @@ NS_IMETHODIMP nsCacheService::VisitEntries(nsICacheVisitor *visitor)
- return NS_OK;
- }
+@@ -1555,7 +1555,19 @@ NS_IMETHODIMP nsCacheService::VisitEntries(nsICacheVisitor *visitor)
--
NS_IMETHODIMP nsCacheService::EvictEntries(nsCacheStoragePolicy storagePolicy)
{
-- return EvictEntriesForClient(nsnull, storagePolicy);
+- return EvictEntriesForClient(nullptr, storagePolicy);
+ NS_IMETHODIMP r;
-+ r = EvictEntriesForClient(nsnull, storagePolicy);
++ r = EvictEntriesForClient(nullptr, storagePolicy);
+
+ // XXX: Bloody hack until we get this notifier in FF14.0:
+ // https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsICacheListener#onCacheEntryDoomed%28%29
+ if (storagePolicy == nsICache::STORE_ANYWHERE &&
+ NS_IsMainThread() && gService && gService->mInitialized) {
-+ nsCacheServiceAutoLock lock;
++ nsCacheServiceAutoLock lock(LOCK_TELEM(NSCACHESERVICE_EVICTENTRIESFORCLIENT));
+ gService->DoomActiveEntries();
+ gService->ClearDoomList();
+ (void) SyncWithCacheIOThread();
diff --git a/src/current-patches/firefox/0016-Prevent-WebSocket-DNS-leak.patch b/src/current-patches/firefox/0016-Prevent-WebSocket-DNS-leak.patch
index bb70b17..ef61b59 100644
--- a/src/current-patches/firefox/0016-Prevent-WebSocket-DNS-leak.patch
+++ b/src/current-patches/firefox/0016-Prevent-WebSocket-DNS-leak.patch
@@ -1,7 +1,7 @@
-From 976f0d4fabb6b0b50c83192d622827357c761bd3 Mon Sep 17 00:00:00 2001
+From ac25d901493198966643d88d0541eaa2735b122f Mon Sep 17 00:00:00 2001
From: Mike Perry <mikeperry-git at torproject.org>
-Date: Wed, 2 May 2012 17:44:39 -0700
-Subject: [PATCH 16/24] Prevent WebSocket DNS leak.
+Date: Tue, 28 Aug 2012 18:07:37 -0700
+Subject: [PATCH 16/26] Prevent WebSocket DNS leak.
This is due to an improper implementation of the WebSocket spec by Mozilla.
@@ -29,10 +29,10 @@ bug can't turn up in other components or due to 3rd party addons.
3 files changed, 30 insertions(+), 3 deletions(-)
diff --git a/netwerk/dns/nsDNSService2.cpp b/netwerk/dns/nsDNSService2.cpp
-index 68ad8a5..1253b2f 100644
+index 114af2e..4d66dc5 100644
--- a/netwerk/dns/nsDNSService2.cpp
+++ b/netwerk/dns/nsDNSService2.cpp
-@@ -383,6 +383,7 @@ nsDNSService::Init()
+@@ -374,6 +374,7 @@ nsDNSService::Init()
bool enableIDN = true;
bool disableIPv6 = false;
bool disablePrefetch = false;
@@ -40,7 +40,7 @@ index 68ad8a5..1253b2f 100644
int proxyType = nsIProtocolProxyService::PROXYCONFIG_DIRECT;
nsAdoptingCString ipv4OnlyDomains;
-@@ -404,6 +405,10 @@ nsDNSService::Init()
+@@ -399,6 +400,10 @@ nsDNSService::Init()
// If a manual proxy is in use, disable prefetch implicitly
prefs->GetIntPref("network.proxy.type", &proxyType);
@@ -51,7 +51,7 @@ index 68ad8a5..1253b2f 100644
}
if (mFirstTime) {
-@@ -420,7 +425,7 @@ nsDNSService::Init()
+@@ -419,7 +424,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
@@ -68,7 +68,7 @@ index 68ad8a5..1253b2f 100644
// 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,
+@@ -573,6 +579,14 @@ nsDNSService::AsyncResolve(const nsACString &hostname,
if (mDisablePrefetch && (flags & RESOLVE_SPECULATE))
return NS_ERROR_DNS_LOOKUP_QUEUE_FULL;
@@ -82,37 +82,38 @@ index 68ad8a5..1253b2f 100644
+
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?
-+ }
-+ }
+ localDomain = mLocalDomains.GetEntry(hostname);
+@@ -669,6 +683,14 @@ nsDNSService::Resolve(const nsACString &hostname,
}
NS_ENSURE_TRUE(res, NS_ERROR_OFFLINE);
++ 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?
++ }
++ }
++
+ const nsACString *hostPtr = &hostname;
+
+ if (localDomain) {
diff --git a/netwerk/dns/nsDNSService2.h b/netwerk/dns/nsDNSService2.h
-index 1749b41..3ec8eba 100644
+index 26d0939..c62c9dd 100644
--- a/netwerk/dns/nsDNSService2.h
+++ b/netwerk/dns/nsDNSService2.h
-@@ -70,4 +70,5 @@ private:
+@@ -41,5 +41,6 @@ private:
bool mDisableIPv6;
bool mDisablePrefetch;
bool mFirstTime;
+ bool mDisableDNS;
+ nsTHashtable<nsCStringHashKey> mLocalDomains;
};
diff --git a/netwerk/protocol/websocket/WebSocketChannel.cpp b/netwerk/protocol/websocket/WebSocketChannel.cpp
-index 9e446e9..42aa6ca 100644
+index 56a71ab..345df6e 100644
--- a/netwerk/protocol/websocket/WebSocketChannel.cpp
+++ b/netwerk/protocol/websocket/WebSocketChannel.cpp
-@@ -1698,8 +1698,12 @@ WebSocketChannel::ApplyForAdmission()
+@@ -2157,8 +2157,12 @@ WebSocketChannel::ApplyForAdmission()
LOG(("WebSocketChannel::ApplyForAdmission: checking for concurrent open\n"));
nsCOMPtr<nsIThread> mainThread;
NS_GetMainThread(getter_AddRefs(mainThread));
@@ -121,8 +122,8 @@ index 9e446e9..42aa6ca 100644
+ 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);
++ mDNSRequest = nullptr;
++ OnLookupComplete(nullptr, nullptr, rv);
+ }
return NS_OK;
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
index f1814e7..118c5d6 100644
--- 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
@@ -1,7 +1,7 @@
-From 36f826e64411a74912ba1adebd1a30b84716bf84 Mon Sep 17 00:00:00 2001
+From 53ec410990f8616d5c3cf3bfbb9feaa4a83ff722 Mon Sep 17 00:00:00 2001
From: Mike Perry <mikeperry-git at torproject.org>
-Date: Wed, 6 Jun 2012 11:08:56 -0700
-Subject: [PATCH 17/24] Randomize HTTP request order and pipeline depth.
+Date: Tue, 4 Dec 2012 17:38:51 -0800
+Subject: [PATCH 17/26] Randomize HTTP request order and pipeline depth.
This is an experimental defense against
http://lorre.uni.lu/~andriy/papers/acmccs-wpes11-fingerprinting.pdf
@@ -11,241 +11,149 @@ https://blog.torproject.org/blog/experimental-defense-website-traffic-fingerprin
This defense has been improved since that blog post to additionally randomize
the order and concurrency of non-pipelined HTTP requests.
+
+This patch is also different from the 10.x ESR patch, as the pipelining
+code has changed. We may want to set network.http.pipelining.aggressive to get
+similar behavior...
+
+The good news is we now randomize SPDY request order as well as pipeline
+request order (though SPDY is still disabled by default in TBB).
---
- netwerk/protocol/http/nsHttpConnectionMgr.cpp | 136 ++++++++++++++++++++++++-
- netwerk/protocol/http/nsHttpConnectionMgr.h | 5 +
- 2 files changed, 136 insertions(+), 5 deletions(-)
+ netwerk/protocol/http/nsHttpConnectionMgr.cpp | 67 +++++++++++++++++++++++--
+ netwerk/protocol/http/nsHttpConnectionMgr.h | 3 +
+ 2 files changed, 65 insertions(+), 5 deletions(-)
diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.cpp b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
-index 23ef893..788368f 100644
+index 526df93..abae041 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();
+@@ -20,6 +20,8 @@
+ #include "prnetdb.h"
+ #include "mozilla/Telemetry.h"
+
++#include <stdlib.h>
+
-+ nsresult rv;
-+ mRandomGenerator = do_GetService("@mozilla.org/security/random-generator;1", &rv);
-+ if (NS_FAILED(rv)) {
-+ mRandomGenerator = nsnull;
-+ }
- }
+ using namespace mozilla;
+ using namespace mozilla::net;
- 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;
- }
- }
+@@ -39,15 +41,46 @@ InsertTransactionSorted(nsTArray<nsHttpTransaction*> &pendingQ, nsHttpTransactio
+ // insert into queue with smallest valued number first. search in reverse
+ // order under the assumption that many of the existing transactions will
+ // have the same priority (usually 0).
++ uint32_t len = pendingQ.Length();
++ uint32_t begin = 0, end = len+1;
++ int found_begin = 0;
+
+- for (int32_t i=pendingQ.Length()-1; i>=0; --i) {
++ if (pendingQ.IsEmpty()) {
++ pendingQ.InsertElementAt(0, trans);
++ return;
++ }
+
-+ delete [] ind;
++// #define PRESERVE_PRIORITY_ORDER
++#ifdef PRESERVE_PRIORITY_ORDER
++ // XXX: Untested
++ for (uint32_t i=0; i < len; ++i) {
+ nsHttpTransaction *t = pendingQ[i];
+- if (trans->Priority() >= t->Priority()) {
+- pendingQ.InsertElementAt(i+1, trans);
+- return;
++
++ /* As soon as we see a priority >= us, our insertion
++ * range starts there */
++ if (!found_begin && t->Priority() >= trans->Priority()) {
++ begin = i;
++ found_begin = 1;
++ }
++ /* As soon as we see a priority > us, our insertion
++ * range ends there */
++ if (t->Priority() > trans->Priority()) {
++ end = i;
++ break;
}
}
+- pendingQ.InsertElementAt(0, trans);
++
++ // XXX Verify that begin..end are all == trans->Priority()
++#endif
++
++ // Choose random destination begin..end
++ uint32_t count = end - begin;
++ if (count == 0) count = 1;
++
++ // FIXME: rand() is not crypto-secure.. but meh, this code will probably
++ // change like 2 dozen more times before merge, and rand() is probably
++ // good enough for our purposes anyways.
++ pendingQ.InsertElementAt(begin + (rand()%count), trans);
}
-@@ -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) {
+ //-----------------------------------------------------------------------------
+@@ -68,6 +101,12 @@ nsHttpConnectionMgr::nsHttpConnectionMgr()
+ mCT.Init();
+ mAlternateProtocolHash.Init(16);
+ mSpdyPreferredHash.Init();
+
-+ PRUint32* ind = new PRUint32[count];
-+ ShuffleRequestOrder(ind, count);
-+
-+ for (h=0; h<count; ++h) {
-+ i = ind[h]; // random request sequence
- trans = ent->mPendingQ[i];
++ nsresult rv;
++ mRandomGenerator = do_GetService("@mozilla.org/security/random-generator;1", &rv);
++ if (NS_FAILED(rv)) {
++ mRandomGenerator = nullptr;
++ }
+ }
- // 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"));
+ nsHttpConnectionMgr::~nsHttpConnectionMgr()
+@@ -1120,6 +1159,19 @@ nsHttpConnectionMgr::AtActiveConnectionLimit(nsConnectionEntry *ent, uint8_t cap
-@@ -694,6 +712,19 @@ nsHttpConnectionMgr::AtActiveConnectionLimit(nsConnectionEntry *ent, PRUint8 cap
- maxPersistConns = mMaxPersistConnsPerHost;
- }
+ LOG((" connection count = %d, limit %d\n", totalCount, maxPersistConns));
+ // 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
++ // end up converging on the high side of concurrent connections
+ // after a short while.
-+ PRUint8 *bytes = nsnull;
++ PRUint8 *bytes = nullptr;
+ nsresult rv = mRandomGenerator->GenerateRandomBytes(1, &bytes);
+ NS_ENSURE_SUCCESS(rv, rv);
+
-+ bytes[0] = bytes[0] % (maxConns + 1);
-+ maxConns = (maxConns/5) + bytes[0];
++ bytes[0] = bytes[0] % (maxPersistConns + 1);
++ maxPersistConns = (maxPersistConns/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;
- }
+ bool result = (totalCount >= maxPersistConns);
+ LOG((" result: %s", result ? "true" : "false"));
+@@ -1297,6 +1349,11 @@ nsHttpConnectionMgr::AddToShortestPipeline(nsConnectionEntry *ent,
-@@ -938,6 +969,101 @@ nsHttpConnectionMgr::BuildPipeline(nsConnectionEntry *ent,
- return true;
- }
+ maxdepth = PR_MIN(maxdepth, depthLimit);
-+
-+// 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++;
++ if (maxdepth/2 > 1) {
++ // This is a crazy hack to randomize pipeline depth a bit more..
++ maxdepth = 1 + maxdepth/2 + (rand() % (maxdepth/2));
+ }
+
-+ 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)
- {
+ if (maxdepth < 2)
+ return false;
+
diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.h b/netwerk/protocol/http/nsHttpConnectionMgr.h
-index cdf21a9..81b282a 100644
+index 580710a..b22c669 100644
--- a/netwerk/protocol/http/nsHttpConnectionMgr.h
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.h
-@@ -51,6 +51,7 @@
-
+@@ -23,6 +23,7 @@
#include "nsIObserver.h"
#include "nsITimer.h"
+ #include "nsIX509Cert3.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;
+@@ -585,6 +586,8 @@ private:
+ uint64_t mTimeOfNextWakeUp;
// Timer for next pruning of dead connections.
nsCOMPtr<nsITimer> mTimer;
+ // Random number generator for reordering HTTP pipeline
+ nsCOMPtr<nsIRandomGenerator> mRandomGenerator;
- //
- // the connection table
+ // A 1s tick to call nsHttpConnection::ReadTimeoutTick on
+ // active http/1 connections and check for orphaned half opens.
--
1.7.5.4
diff --git a/src/current-patches/firefox/0018-Adapt-Steven-Michaud-s-Mac-crashfix-patch.patch b/src/current-patches/firefox/0018-Adapt-Steven-Michaud-s-Mac-crashfix-patch.patch
new file mode 100644
index 0000000..7c2ddee
--- /dev/null
+++ b/src/current-patches/firefox/0018-Adapt-Steven-Michaud-s-Mac-crashfix-patch.patch
@@ -0,0 +1,545 @@
+From 4541bfb12c40ed13871503f7bb46ba8e5f27a8ed Mon Sep 17 00:00:00 2001
+From: Mike Perry <mikeperry-git at torproject.org>
+Date: Tue, 4 Dec 2012 17:48:53 -0800
+Subject: [PATCH 18/26] 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/Makefile.in | 1 +
+ widget/cocoa/nsChildView.mm | 28 +++++++++++------
+ widget/gtk2/nsDragService.cpp | 9 +++--
+ widget/nsIDragService.idl | 4 +--
+ widget/nsPIDragService.idl | 48 +++++++++++++++++++++++++++++
+ widget/qt/nsDragService.h | 2 +
+ widget/windows/Makefile.in | 4 ++
+ widget/windows/nsDragService.cpp | 13 +++++---
+ widget/windows/nsDragService.h | 12 +++---
+ widget/windows/nsNativeDragSource.cpp | 7 ++--
+ widget/windows/nsNativeDragTarget.cpp | 28 ++++++++++------
+ widget/windows/nsPIDragServiceWindows.idl | 46 +++++++++++++++++++++++++++
+ widget/xpwidgets/nsBaseDragService.cpp | 16 +++++++++-
+ widget/xpwidgets/nsBaseDragService.h | 9 ++---
+ 14 files changed, 179 insertions(+), 48 deletions(-)
+ create mode 100644 widget/nsPIDragService.idl
+ create mode 100644 widget/windows/nsPIDragServiceWindows.idl
+
+diff --git a/widget/Makefile.in b/widget/Makefile.in
+index 4ab8a48..bc5aa5c 100644
+--- a/widget/Makefile.in
++++ b/widget/Makefile.in
+@@ -106,6 +106,7 @@ XPIDLSRCS = \
+ nsIClipboardDragDropHooks.idl \
+ nsIClipboardDragDropHookList.idl \
+ nsIDragSession.idl \
++ nsPIDragService.idl \
+ nsIDragService.idl \
+ nsIFormatConverter.idl \
+ nsIClipboard.idl \
+diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm
+index aa919fa..d5fa58f 100644
+--- a/widget/cocoa/nsChildView.mm
++++ b/widget/cocoa/nsChildView.mm
+@@ -4518,11 +4518,12 @@ static int32_t RoundUp(double aDouble)
+ 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));
+ }
+ }
+
+@@ -4543,11 +4544,13 @@ static int32_t RoundUp(double aDouble)
+ }
+
+ 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"
+@@ -4558,10 +4561,15 @@ static int32_t RoundUp(double aDouble)
+ // 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));
+- if (dataTransfer)
+- dataTransfer->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) {
++ dataTransfer->SetDropEffectInt(nsIDragService::DRAGDROP_ACTION_NONE);
++ }
++ }
+ }
+
+ mDragService->EndDragSession(true);
+diff --git a/widget/gtk2/nsDragService.cpp b/widget/gtk2/nsDragService.cpp
+index 10985cc..bac4160 100644
+--- a/widget/gtk2/nsDragService.cpp
++++ b/widget/gtk2/nsDragService.cpp
+@@ -234,8 +234,8 @@ OnSourceGrabEventAfter(GtkWidget *widget, GdkEvent *event, gpointer user_data)
+ // Update the cursor position. The last of these recorded gets used for
+ // the NS_DRAGDROP_END event.
+ nsDragService *dragService = static_cast<nsDragService*>(user_data);
+- dragService->SetDragEndPoint(nsIntPoint(event->motion.x_root,
+- event->motion.y_root));
++ dragService->SetDragEndPoint(event->motion.x_root,
++ event->motion.y_root);
+ } else if (sMotionEvent && (event->type != GDK_KEY_PRESS ||
+ event->type != GDK_KEY_RELEASE)) {
+ // Update modifier state from keypress events.
+@@ -1343,7 +1343,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);
+ }
+ }
+
+@@ -1760,8 +1760,9 @@ nsDragService::ScheduleDropEvent(nsWindow *aWindow,
+ NS_WARNING("Additional drag drop ignored");
+ return FALSE;
+ }
++ nsIntPoint pt = aWindowPoint + aWindow->WidgetToScreenOffset();
+
+- SetDragEndPoint(aWindowPoint + aWindow->WidgetToScreenOffset());
++ SetDragEndPoint(pt.x, pt.y);
+
+ // We'll reply with gtk_drag_finish().
+ return TRUE;
+diff --git a/widget/nsIDragService.idl b/widget/nsIDragService.idl
+index 196761e..c0565bb 100644
+--- a/widget/nsIDragService.idl
++++ b/widget/nsIDragService.idl
+@@ -15,7 +15,7 @@ interface nsIDOMDragEvent;
+ interface nsIDOMDataTransfer;
+ interface nsISelection;
+
+-[scriptable, uuid(82B58ADA-F490-4C3D-B737-1057C4F1D052), builtinclass]
++[scriptable, uuid(82B58ADA-F490-4C3D-B737-1057C4F1D052)]
+ interface nsIDragService : nsISupports
+ {
+ const long DRAGDROP_ACTION_NONE = 0;
+@@ -112,8 +112,6 @@ interface nsIDragService : nsISupports
+ */
+ void suppress();
+ void unsuppress();
+-
+- [noscript] void dragMoved(in long aX, in long aY);
+ };
+
+
+diff --git a/widget/nsPIDragService.idl b/widget/nsPIDragService.idl
+new file mode 100644
+index 0000000..7a703c1
+--- /dev/null
++++ b/widget/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 at 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);
++
++ uint16_t getInputSource();
++
++ void setDragEndPoint(in long aX, in long aY);
++};
+diff --git a/widget/qt/nsDragService.h b/widget/qt/nsDragService.h
+index ee145ad..b03b74e 100644
+--- a/widget/qt/nsDragService.h
++++ b/widget/qt/nsDragService.h
+@@ -17,6 +17,8 @@ public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIDRAGSERVICE
+
++ NS_IMETHOD DragMoved(PRInt32 aX, PRInt32 aY);
++
+ nsDragService();
+
+ private:
+diff --git a/widget/windows/Makefile.in b/widget/windows/Makefile.in
+index ec383bd..7000ec0 100644
+--- a/widget/windows/Makefile.in
++++ b/widget/windows/Makefile.in
+@@ -88,6 +88,10 @@ ifdef MOZ_ENABLE_D3D10_LAYER
+ DEFINES += -DMOZ_ENABLE_D3D10_LAYER
+ endif
+
++XPIDLSRCS += \
++ nsPIDragServiceWindows.idl \
++ $(NULL)
++
+ SHARED_LIBRARY_LIBS = \
+ ../xpwidgets/$(LIB_PREFIX)xpwidgets_s.$(LIB_SUFFIX) \
+ $(NULL)
+diff --git a/widget/windows/nsDragService.cpp b/widget/windows/nsDragService.cpp
+index 899154a..9511457 100644
+--- a/widget/windows/nsDragService.cpp
++++ b/widget/windows/nsDragService.cpp
+@@ -60,6 +60,8 @@ nsDragService::~nsDragService()
+ NS_IF_RELEASE(mDataObject);
+ }
+
++NS_IMPL_ISUPPORTS_INHERITED1(nsDragService, nsBaseDragService, nsPIDragServiceWindows)
++
+ bool
+ nsDragService::CreateDragImage(nsIDOMNode *aDOMNode,
+ nsIScriptableRegion *aRegion,
+@@ -305,7 +307,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;
+@@ -426,25 +428,26 @@ nsDragService::GetData(nsITransferable * aTransferable, uint32_t 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/windows/nsDragService.h b/widget/windows/nsDragService.h
+index 236910a..e83167d 100644
+--- a/widget/windows/nsDragService.h
++++ b/widget/windows/nsDragService.h
+@@ -7,6 +7,7 @@
+ #define nsDragService_h__
+
+ #include "nsBaseDragService.h"
++#include "nsPIDragServiceWindows.h"
+ #include <windows.h>
+ #include <shlobj.h>
+
+@@ -20,12 +21,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,
+@@ -39,13 +43,9 @@ public:
+ NS_IMETHOD EndDragSession(bool aDoneDrag);
+
+ // native impl.
+- NS_IMETHOD SetIDataObject(IDataObject * aDataObj);
+ NS_IMETHOD StartInvokingDragSession(IDataObject * aDataObj,
+ uint32_t aActionType);
+
+- // A drop occurred within the application vs. outside of it.
+- void SetDroppedLocal();
+-
+ protected:
+ nsDataObjCollection* GetDataObjCollection(IDataObject * aDataObj);
+
+diff --git a/widget/windows/nsNativeDragSource.cpp b/widget/windows/nsNativeDragSource.cpp
+index 3acee30..3662c18 100644
+--- a/widget/windows/nsNativeDragSource.cpp
++++ b/widget/windows/nsNativeDragSource.cpp
+@@ -10,7 +10,7 @@
+ #include "nsIServiceManager.h"
+ #include "nsToolkit.h"
+ #include "nsWidgetsCID.h"
+-#include "nsIDragService.h"
++#include "nsDragService.h"
+
+ static NS_DEFINE_IID(kCDragServiceCID, NS_DRAGSERVICE_CID);
+
+@@ -69,9 +69,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/windows/nsNativeDragTarget.cpp b/widget/windows/nsNativeDragTarget.cpp
+index ec12f8e..8b72f6d 100644
+--- a/widget/windows/nsNativeDragTarget.cpp
++++ b/widget/windows/nsNativeDragTarget.cpp
+@@ -174,7 +174,11 @@ nsNativeDragTarget::DispatchDragDropEvent(uint32_t aEventType, POINTL aPT)
+ ModifierKeyState modifierKeyState;
+ modifierKeyState.InitInputEvent(event);
+
+- event.inputSource = static_cast<nsBaseDragService*>(mDragService)->GetInputSource();
++ event.inputSource = 0;
++ nsCOMPtr<nsPIDragService> dragServicePriv = do_QueryInterface(mDragService);
++ if (dragServicePriv) {
++ dragServicePriv->GetInputSource(&event.inputSource);
++ }
+
+ mWidget->DispatchEvent(&event, status);
+ }
+@@ -261,9 +265,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);
+@@ -401,8 +404,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:
+@@ -426,11 +429,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/windows/nsPIDragServiceWindows.idl b/widget/windows/nsPIDragServiceWindows.idl
+new file mode 100644
+index 0000000..c8a46dd
+--- /dev/null
++++ b/widget/windows/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 at 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/xpwidgets/nsBaseDragService.cpp b/widget/xpwidgets/nsBaseDragService.cpp
+index 805d83f..9b69793 100644
+--- a/widget/xpwidgets/nsBaseDragService.cpp
++++ b/widget/xpwidgets/nsBaseDragService.cpp
+@@ -55,7 +55,7 @@ nsBaseDragService::~nsBaseDragService()
+ {
+ }
+
+-NS_IMPL_ISUPPORTS2(nsBaseDragService, nsIDragService, nsIDragSession)
++NS_IMPL_ISUPPORTS3(nsBaseDragService, nsIDragService, nsPIDragService, nsIDragSession)
+
+ //---------------------------------------------------------
+ NS_IMETHODIMP
+@@ -403,6 +403,20 @@ nsBaseDragService::DragMoved(int32_t aX, int32_t 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/xpwidgets/nsBaseDragService.h b/widget/xpwidgets/nsBaseDragService.h
+index cb00f8e..741c287 100644
+--- a/widget/xpwidgets/nsBaseDragService.h
++++ b/widget/xpwidgets/nsBaseDragService.h
+@@ -7,6 +7,7 @@
+ #define nsBaseDragService_h__
+
+ #include "nsIDragService.h"
++#include "nsPIDragService.h"
+ #include "nsIDragSession.h"
+ #include "nsITransferable.h"
+ #include "nsISupportsArray.h"
+@@ -32,6 +33,7 @@ class nsICanvasElementExternal;
+ */
+
+ class nsBaseDragService : public nsIDragService,
++ public nsPIDragService,
+ public nsIDragSession
+ {
+
+@@ -42,14 +44,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; }
+-
+- uint16_t GetInputSource() { return mInputSource; }
+-
+ protected:
+
+ /**
+--
+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
deleted file mode 100644
index 46cf611..0000000
--- a/src/current-patches/firefox/0018-Add-HTTP-auth-headers-before-the-modify-request-obse.patch
+++ /dev/null
@@ -1,52 +0,0 @@
-From c1e26c8a294abe426fd6fb84508db6074ef23379 Mon Sep 17 00:00:00 2001
-From: Mike Perry <mikeperry-git at 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
deleted file mode 100644
index 7f3869c..0000000
--- a/src/current-patches/firefox/0019-Adapt-Steven-Michaud-s-Mac-crashfix-patch.patch
+++ /dev/null
@@ -1,532 +0,0 @@
-From 49cccdba3e6fc10e0e376d423b3ba1b6135f62e1 Mon Sep 17 00:00:00 2001
-From: Mike Perry <mikeperry-git at 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 at 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 at 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/0019-Add-mozIThirdPartyUtil.getFirstPartyURI-API.patch b/src/current-patches/firefox/0019-Add-mozIThirdPartyUtil.getFirstPartyURI-API.patch
new file mode 100644
index 0000000..ab855cf
--- /dev/null
+++ b/src/current-patches/firefox/0019-Add-mozIThirdPartyUtil.getFirstPartyURI-API.patch
@@ -0,0 +1,154 @@
+From 4ea73b19b21764c10019e9af1cc68664ed7f7394 Mon Sep 17 00:00:00 2001
+From: Kathleen Brade <brade at pearlcrescent.com>
+Date: Wed, 28 Nov 2012 17:08:29 -0500
+Subject: [PATCH 19/26] Add mozIThirdPartyUtil.getFirstPartyURI API
+
+API allows you to get the url bar URI for a channel or nsIDocument.
+---
+ content/base/src/ThirdPartyUtil.cpp | 58 ++++++++++++++++++++++++++++
+ content/base/src/ThirdPartyUtil.h | 2 +
+ netwerk/base/public/mozIThirdPartyUtil.idl | 21 ++++++++++
+ 3 files changed, 81 insertions(+), 0 deletions(-)
+
+diff --git a/content/base/src/ThirdPartyUtil.cpp b/content/base/src/ThirdPartyUtil.cpp
+index 97a000e..ae4fa70 100644
+--- a/content/base/src/ThirdPartyUtil.cpp
++++ b/content/base/src/ThirdPartyUtil.cpp
+@@ -7,6 +7,9 @@
+ #include "nsIServiceManager.h"
+ #include "nsIHttpChannelInternal.h"
+ #include "nsIDOMWindow.h"
++#include "nsICookiePermission.h"
++#include "nsIDOMDocument.h"
++#include "nsIDocument.h"
+ #include "nsILoadContext.h"
+ #include "nsIPrincipal.h"
+ #include "nsIScriptObjectPrincipal.h"
+@@ -21,6 +24,7 @@ ThirdPartyUtil::Init()
+
+ nsresult rv;
+ mTLDService = do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID, &rv);
++ mCookiePermissions = do_GetService(NS_COOKIEPERMISSION_CONTRACTID);
+ return rv;
+ }
+
+@@ -282,3 +286,57 @@ ThirdPartyUtil::GetBaseDomain(nsIURI* aHostURI,
+
+ return NS_OK;
+ }
++
++NS_IMETHODIMP
++ThirdPartyUtil::GetFirstPartyURI(nsIChannel *aChannel,
++ nsIDocument *aDoc,
++ nsIURI **aOutput)
++{
++ nsresult rv = NS_ERROR_NULL_POINTER;
++
++ if (!aChannel && aDoc) {
++ aChannel = aDoc->GetChannel();
++ }
++
++ // If aChannel is specified or available, use the official route
++ // for sure
++ if (aChannel) {
++ rv = mCookiePermissions->GetOriginatingURI(aChannel, aOutput);
++ }
++
++ // If the channel was missing, closed or broken, try the
++ // window hierarchy directly.
++ //
++ // This might fail to work for first-party loads themselves, but
++ // we don't need this codepath for that case.
++ if (NS_FAILED(rv) && aDoc) {
++ nsCOMPtr<nsIDOMWindow> top;
++ nsCOMPtr<nsIDOMDocument> topDDoc;
++
++ if (aDoc->GetWindow()) {
++ aDoc->GetWindow()->GetTop(getter_AddRefs(top));
++ top->GetDocument(getter_AddRefs(topDDoc));
++
++ 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;
++ }
++
++ // TODO: We could provide a route through the loadgroup + notification
++ // callbacks too, but either channel or document was always available
++ // in the cases where this function was originally needed (the image cache).
++ // The notification callbacks also appear to suffers from the same limitation
++ // as the document path. See nsICookiePermissions.GetOriginatingURI() for
++ // details.
++
++ return rv;
++}
++
+diff --git a/content/base/src/ThirdPartyUtil.h b/content/base/src/ThirdPartyUtil.h
+index 3f50ac3..fe7b214 100644
+--- a/content/base/src/ThirdPartyUtil.h
++++ b/content/base/src/ThirdPartyUtil.h
+@@ -9,6 +9,7 @@
+ #include "nsString.h"
+ #include "mozIThirdPartyUtil.h"
+ #include "nsIEffectiveTLDService.h"
++#include "nsICookiePermission.h"
+ #include "mozilla/Attributes.h"
+
+ class nsIURI;
+@@ -29,6 +30,7 @@ private:
+ static already_AddRefed<nsIURI> GetURIFromWindow(nsIDOMWindow* aWin);
+
+ nsCOMPtr<nsIEffectiveTLDService> mTLDService;
++ nsCOMPtr<nsICookiePermission> mCookiePermissions;
+ };
+
+ #endif
+diff --git a/netwerk/base/public/mozIThirdPartyUtil.idl b/netwerk/base/public/mozIThirdPartyUtil.idl
+index 578d8db..963385c 100644
+--- a/netwerk/base/public/mozIThirdPartyUtil.idl
++++ b/netwerk/base/public/mozIThirdPartyUtil.idl
+@@ -7,6 +7,7 @@
+ interface nsIURI;
+ interface nsIDOMWindow;
+ interface nsIChannel;
++interface nsIDocument;
+
+ /**
+ * Utility functions for determining whether a given URI, channel, or window
+@@ -140,6 +141,26 @@ interface mozIThirdPartyUtil : nsISupports
+ * @return the base domain.
+ */
+ AUTF8String getBaseDomain(in nsIURI aHostURI);
++
++
++ /**
++ * getFirstPartyURI
++ *
++ * Obtain the top-level url bar URI for either a channel or a document.
++ * Either parameter may be null (but not both).
++ *
++ * @param aChannel
++ * An arbitrary channel for some content element of a first party
++ * load. Can be null.
++ *
++ * @param aDoc
++ * An arbitrary third party document. Can be null.
++ *
++ * @return the first party url bar URI for the load.
++ */
++ nsIURI getFirstPartyURI(in nsIChannel aChannel,
++ in nsIDocument aDoc);
++
+ };
+
+ %{ C++
+--
+1.7.5.4
+
diff --git a/src/current-patches/firefox/0020-Add-canvas-image-extraction-prompt.patch b/src/current-patches/firefox/0020-Add-canvas-image-extraction-prompt.patch
new file mode 100644
index 0000000..802dc3f
--- /dev/null
+++ b/src/current-patches/firefox/0020-Add-canvas-image-extraction-prompt.patch
@@ -0,0 +1,548 @@
+From 924f0fb25804b75289f18fe5b5cfe02667aad58f Mon Sep 17 00:00:00 2001
+From: Kathleen Brade <brade at pearlcrescent.com>
+Date: Tue, 27 Nov 2012 13:13:40 -0500
+Subject: [PATCH 20/26] Add canvas image extraction prompt.
+
+---
+ browser/base/content/browser.js | 102 ++++++++++++++++++++
+ browser/base/content/browser.xul | 1 +
+ .../en-US/chrome/browser/browser.properties | 7 ++
+ browser/themes/gnomestripe/browser.css | 2 +
+ browser/themes/pinstripe/browser.css | 2 +
+ browser/themes/winstripe/browser.css | 2 +
+ content/canvas/src/CanvasUtils.cpp | 65 +++++++++++++
+ content/canvas/src/CanvasUtils.h | 2 +
+ content/canvas/src/nsCanvasRenderingContext2D.cpp | 16 +++
+ .../canvas/src/nsCanvasRenderingContext2DAzure.cpp | 16 +++
+ content/html/content/public/nsHTMLCanvasElement.h | 3 +
+ content/html/content/src/Makefile.in | 1 +
+ content/html/content/src/nsHTMLCanvasElement.cpp | 40 ++++++--
+ 13 files changed, 249 insertions(+), 10 deletions(-)
+
+diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
+index 1fc137c..e95cebc 100644
+--- a/browser/base/content/browser.js
++++ b/browser/base/content/browser.js
+@@ -1282,6 +1282,7 @@ var gBrowserInit = {
+ BrowserOffline.init();
+ OfflineApps.init();
+ IndexedDBPromptHelper.init();
++ CanvasPermissionPromptHelper.init();
+ gFormSubmitObserver.init();
+ SocialUI.init();
+ AddonManager.addAddonListener(AddonsMgrListener);
+@@ -1639,6 +1640,7 @@ var gBrowserInit = {
+ BrowserOffline.uninit();
+ OfflineApps.uninit();
+ IndexedDBPromptHelper.uninit();
++ CanvasPermissionPromptHelper.uninit();
+ AddonManager.removeAddonListener(AddonsMgrListener);
+ SocialUI.uninit();
+ }
+@@ -6129,6 +6131,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 5bf156e..8699a62 100644
+--- a/browser/base/content/browser.xul
++++ b/browser/base/content/browser.xul
+@@ -573,6 +573,7 @@
+ <image id="identity-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"/>
+ <image id="webapps-notification-icon" class="notification-anchor-icon" role="button"/>
+diff --git a/browser/locales/en-US/chrome/browser/browser.properties b/browser/locales/en-US/chrome/browser/browser.properties
+index 1a9f457..4e61cb9 100644
+--- a/browser/locales/en-US/chrome/browser/browser.properties
++++ b/browser/locales/en-US/chrome/browser/browser.properties
+@@ -218,6 +218,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. Since canvas image data can be used to discover information about your computer, blank 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.css b/browser/themes/gnomestripe/browser.css
+index aff8ae1..f69f553 100644
+--- a/browser/themes/gnomestripe/browser.css
++++ b/browser/themes/gnomestripe/browser.css
+@@ -1185,6 +1185,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);
+@@ -1250,6 +1251,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.css b/browser/themes/pinstripe/browser.css
+index a44c6b9..ff581ab 100644
+--- a/browser/themes/pinstripe/browser.css
++++ b/browser/themes/pinstripe/browser.css
+@@ -2403,10 +2403,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.css b/browser/themes/winstripe/browser.css
+index 470c344..770245b 100644
+--- a/browser/themes/winstripe/browser.css
++++ b/browser/themes/winstripe/browser.css
+@@ -2319,6 +2319,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);
+@@ -2382,6 +2383,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 4173891..2ec463f 100644
+--- a/content/canvas/src/CanvasUtils.cpp
++++ b/content/canvas/src/CanvasUtils.cpp
+@@ -24,9 +24,74 @@
+ #include "CanvasUtils.h"
+ #include "mozilla/gfx/Matrix.h"
+
++#include "nsIScriptObjectPrincipal.h"
++#include "nsIPermissionManager.h"
++#include "nsIObserverService.h"
++#include "mozilla/Services.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 {
+
++// 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
+ DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement,
+ nsIPrincipal *aPrincipal,
+diff --git a/content/canvas/src/CanvasUtils.h b/content/canvas/src/CanvasUtils.h
+index d464d0b..f266de6 100644
+--- a/content/canvas/src/CanvasUtils.h
++++ b/content/canvas/src/CanvasUtils.h
+@@ -45,6 +45,8 @@ void DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement,
+ bool forceWriteOnly,
+ bool CORSUsed);
+
++bool IsImageExtractionAllowed(nsIDocument *aDocument);
++
+ // Make a double out of |v|, treating undefined values as 0.0 (for
+ // the sake of sparse arrays). Return true iff coercion
+ // succeeded.
+diff --git a/content/canvas/src/nsCanvasRenderingContext2D.cpp b/content/canvas/src/nsCanvasRenderingContext2D.cpp
+index 1ee7a02..0dec654 100644
+--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
++++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
+@@ -3946,6 +3946,22 @@ nsCanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
+
+ uint8_t* data = JS_GetUint8ClampedArrayData(darray, aCx);
+
++ // 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 = mCanvasElement->OwnerDoc();
++ usePlaceholder = !ownerDoc ||
++ !CanvasUtils::IsImageExtractionAllowed(ownerDoc);
++ }
++
++ if (usePlaceholder) {
++ memset(data, 0xFF, len.value());
++ *aRetval = darray;
++ return NS_OK;
++ }
++
+ /* Copy the surface contents to the buffer */
+ nsRefPtr<gfxImageSurface> tmpsurf =
+ new gfxImageSurface(data,
+diff --git a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+index 07b5236..d86ba32 100644
+--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
++++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+@@ -4251,6 +4251,22 @@ nsCanvasRenderingContext2DAzure::GetImageDataArray(JSContext* aCx,
+
+ uint8_t* data = JS_GetUint8ClampedArrayData(darray, aCx);
+
++ // 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 = mCanvasElement->OwnerDoc();
++ usePlaceholder = !ownerDoc ||
++ !CanvasUtils::IsImageExtractionAllowed(ownerDoc);
++ }
++
++ if (usePlaceholder) {
++ memset(data, 0xFF, len.value());
++ *aRetval = darray;
++ return NS_OK;
++ }
++
+ IntRect srcRect(0, 0, mWidth, mHeight);
+ IntRect destRect(aX, aY, aWidth, aHeight);
+
+diff --git a/content/html/content/public/nsHTMLCanvasElement.h b/content/html/content/public/nsHTMLCanvasElement.h
+index 2c11600..65da344 100644
+--- a/content/html/content/public/nsHTMLCanvasElement.h
++++ b/content/html/content/public/nsHTMLCanvasElement.h
+@@ -157,13 +157,16 @@ protected:
+ nsresult UpdateContext(nsIPropertyBag *aNewContextOptions = nullptr);
+ 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 9466587..86368a2 100644
+--- a/content/html/content/src/Makefile.in
++++ b/content/html/content/src/Makefile.in
+@@ -113,6 +113,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 961ebf1..13a6910 100644
+--- a/content/html/content/src/nsHTMLCanvasElement.cpp
++++ b/content/html/content/src/nsHTMLCanvasElement.cpp
+@@ -31,6 +31,8 @@
+
+ #include "nsIWritablePropertyBag2.h"
+
++#include "CanvasUtils.h"
++
+ #define DEFAULT_CANVAS_WIDTH 300
+ #define DEFAULT_CANVAS_HEIGHT 150
+
+@@ -184,7 +186,10 @@ 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);
+ }
+
+ // nsHTMLCanvasElement::mozFetchAsStream
+@@ -200,7 +205,7 @@ nsHTMLCanvasElement::MozFetchAsStream(nsIInputStreamCallback *aCallback,
+ bool fellBackToPNG = false;
+ nsCOMPtr<nsIInputStream> inputData;
+
+- rv = ExtractData(aType, EmptyString(), getter_AddRefs(inputData), fellBackToPNG);
++ rv = ExtractData(aType, EmptyString(), false, getter_AddRefs(inputData), fellBackToPNG);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIAsyncInputStream> asyncData = do_QueryInterface(inputData, &rv);
+@@ -220,19 +225,26 @@ nsHTMLCanvasElement::MozFetchAsStream(nsIInputStreamCallback *aCallback,
+ 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;
+@@ -242,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;
+
+@@ -285,6 +298,7 @@ nsHTMLCanvasElement::ExtractData(const nsAString& aType,
+ nsresult
+ nsHTMLCanvasElement::ToDataURLImpl(const nsAString& aMimeType,
+ nsIVariant* aEncoderOptions,
++ bool aUsePlaceholder,
+ nsAString& aDataURL)
+ {
+ bool fallbackToPNG = false;
+@@ -340,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);
+@@ -378,19 +394,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/0020-Add-mozIThirdPartyUtil.getFirstPartyURI-API.patch b/src/current-patches/firefox/0020-Add-mozIThirdPartyUtil.getFirstPartyURI-API.patch
deleted file mode 100644
index 114301d..0000000
--- a/src/current-patches/firefox/0020-Add-mozIThirdPartyUtil.getFirstPartyURI-API.patch
+++ /dev/null
@@ -1,155 +0,0 @@
-From 36d57455893bcf6dc08e91a2784970f285c5e84b Mon Sep 17 00:00:00 2001
-From: Mike Perry <mikeperry-git at torproject.org>
-Date: Tue, 28 Aug 2012 18:35:33 -0700
-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 | 59 ++++++++++++++++++++++++++++
- content/base/src/ThirdPartyUtil.h | 2 +
- 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..52b3dab 100644
---- a/content/base/src/ThirdPartyUtil.cpp
-+++ b/content/base/src/ThirdPartyUtil.cpp
-@@ -40,6 +40,9 @@
- #include "nsIServiceManager.h"
- #include "nsIHttpChannelInternal.h"
- #include "nsIDOMWindow.h"
-+#include "nsICookiePermission.h"
-+#include "nsIDOMDocument.h"
-+#include "nsIDocument.h"
- #include "nsILoadContext.h"
- #include "nsIPrincipal.h"
- #include "nsIScriptObjectPrincipal.h"
-@@ -54,6 +57,7 @@ ThirdPartyUtil::Init()
-
- nsresult rv;
- mTLDService = do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID, &rv);
-+ mCookiePermissions = do_GetService(NS_COOKIEPERMISSION_CONTRACTID);
- return rv;
- }
-
-@@ -315,3 +319,58 @@ ThirdPartyUtil::GetBaseDomain(nsIURI* aHostURI,
-
- return NS_OK;
- }
-+
-+NS_IMETHODIMP
-+ThirdPartyUtil::GetFirstPartyURI(nsIChannel *aChannel,
-+ nsIDocument *aDoc,
-+ nsIURI **aOutput)
-+{
-+ nsresult rv = NS_ERROR_NULL_POINTER;
-+
-+ if (!aChannel && aDoc) {
-+ aChannel = aDoc->GetChannel();
-+ }
-+
-+ // If aChannel is specified or available, use the official route
-+ // for sure
-+ if (aChannel) {
-+ rv = mCookiePermissions->GetOriginatingURI(aChannel, aOutput);
-+ }
-+
-+ // If the channel was missing, closed or broken, try the
-+ // window hierarchy directly.
-+ //
-+ // This might fail to work for first-party loads themselves, but
-+ // we don't need this codepath for that case.
-+ if (NS_FAILED(rv) && aDoc) {
-+ nsCOMPtr<nsIDOMWindow> top;
-+ nsCOMPtr<nsIDOMDocument> topDDoc;
-+
-+ if (aDoc->GetWindow()) {
-+ aDoc->GetWindow()->GetTop(getter_AddRefs(top));
-+ top->GetDocument(getter_AddRefs(topDDoc));
-+
-+ 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;
-+ }
-+
-+ // TODO: We could provide a route through the loadgroup + notification
-+ // callbacks too, but either channel or document was always available
-+ // in the cases where this function was originally needed (the image cache).
-+ // The notification callbacks also appear to suffers from the same limitation
-+ // as the document path. See nsICookiePermissions.GetOriginatingURI() for
-+ // details.
-+
-+ return rv;
-+}
-+
-+
-diff --git a/content/base/src/ThirdPartyUtil.h b/content/base/src/ThirdPartyUtil.h
-index 58ddb15..c8eab11 100644
---- a/content/base/src/ThirdPartyUtil.h
-+++ b/content/base/src/ThirdPartyUtil.h
-@@ -42,6 +42,7 @@
- #include "nsString.h"
- #include "mozIThirdPartyUtil.h"
- #include "nsIEffectiveTLDService.h"
-+#include "nsICookiePermission.h"
-
- class nsIURI;
- class nsIChannel;
-@@ -61,6 +62,7 @@ private:
- static already_AddRefed<nsIURI> GetURIFromWindow(nsIDOMWindow* aWin);
-
- nsCOMPtr<nsIEffectiveTLDService> mTLDService;
-+ nsCOMPtr<nsICookiePermission> mCookiePermissions;
- };
-
- #endif
-diff --git a/netwerk/base/public/mozIThirdPartyUtil.idl b/netwerk/base/public/mozIThirdPartyUtil.idl
-index ad41985..fd2cb38 100644
---- a/netwerk/base/public/mozIThirdPartyUtil.idl
-+++ b/netwerk/base/public/mozIThirdPartyUtil.idl
-@@ -40,6 +40,7 @@
- interface nsIURI;
- interface nsIDOMWindow;
- interface nsIChannel;
-+interface nsIDocument;
-
- /**
- * Utility functions for determining whether a given URI, channel, or window
-@@ -173,6 +174,26 @@ interface mozIThirdPartyUtil : nsISupports
- * @return the base domain.
- */
- AUTF8String getBaseDomain(in nsIURI aHostURI);
-+
-+
-+ /**
-+ * getFirstPartyURI
-+ *
-+ * Obtain the top-level url bar URI for either a channel or a document.
-+ * Either parameter may be null (but not both).
-+ *
-+ * @param aChannel
-+ * An arbitrary channel for some content element of a first party
-+ * load. Can be null.
-+ *
-+ * @param aDoc
-+ * An arbitrary third party document. Can be null.
-+ *
-+ * @return the first party url bar URI for the load.
-+ */
-+ nsIURI getFirstPartyURI(in nsIChannel aChannel,
-+ in nsIDocument aDoc);
-+
- };
-
- %{ C++
---
-1.7.5.4
-
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
deleted file mode 100644
index cf5dd61..0000000
--- a/src/current-patches/firefox/0021-Add-canvas-image-extraction-prompt.patch
+++ /dev/null
@@ -1,551 +0,0 @@
-From 29ce940434ebbb8e54c0d9b8f84ccf6ec6bd71bc Mon Sep 17 00:00:00 2001
-From: Kathleen Brade <brade at 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/0021-Return-client-window-coordinates-for-mouse-event-scr.patch b/src/current-patches/firefox/0021-Return-client-window-coordinates-for-mouse-event-scr.patch
new file mode 100644
index 0000000..d927f02
--- /dev/null
+++ b/src/current-patches/firefox/0021-Return-client-window-coordinates-for-mouse-event-scr.patch
@@ -0,0 +1,77 @@
+From 5db96e68af26dfbfa2085d76efab8ddc09aaa45c Mon Sep 17 00:00:00 2001
+From: Kathleen Brade <brade at pearlcrescent.com>
+Date: Wed, 28 Nov 2012 10:49:09 -0500
+Subject: [PATCH 21/26] Return client window coordinates for mouse event
+ screenX/Y (for dragend, 0,0 is returned).
+
+---
+ content/events/src/nsDOMMouseEvent.cpp | 22 ++++++++++++++++++++++
+ content/events/src/nsDOMTouchEvent.cpp | 6 ++++--
+ 2 files changed, 26 insertions(+), 2 deletions(-)
+
+diff --git a/content/events/src/nsDOMMouseEvent.cpp b/content/events/src/nsDOMMouseEvent.cpp
+index c1784c9..9718a90 100644
+--- a/content/events/src/nsDOMMouseEvent.cpp
++++ b/content/events/src/nsDOMMouseEvent.cpp
+@@ -301,6 +301,20 @@ nsDOMMouseEvent::GetMozMovementY(int32_t* aMovementY)
+ NS_METHOD nsDOMMouseEvent::GetScreenX(int32_t* aScreenX)
+ {
+ NS_ENSURE_ARG_POINTER(aScreenX);
++ bool isChrome = nsContentUtils::IsCallerChrome();
++ if (!isChrome)
++ {
++ // For non-chrome callers, return client coordinates instead.
++ // For some events, the result will be zero; specifically, for dragend
++ // events (there is no widget associated with dragend events, which
++ // causes GetClientX() to return zero). 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 should not break
++ // many web pages. Also, a few years ago Firefox returned 0.
++ // See: https://bugzilla.mozilla.org/show_bug.cgi?id=466379
++ return GetClientX(aScreenX);
++ }
++
+ *aScreenX = nsDOMEvent::GetScreenCoords(mPresContext,
+ mEvent,
+ mEvent->refPoint).x;
+@@ -311,6 +325,14 @@ NS_IMETHODIMP
+ nsDOMMouseEvent::GetScreenY(int32_t* aScreenY)
+ {
+ NS_ENSURE_ARG_POINTER(aScreenY);
++ bool isChrome = nsContentUtils::IsCallerChrome();
++ if (!isChrome)
++ {
++ // For non-chrome callers, return client coordinates instead.
++ // See also the comment in nsDOMMouseEvent::GetScreenX().
++ return GetClientY(aScreenY);
++ }
++
+ *aScreenY = nsDOMEvent::GetScreenCoords(mPresContext,
+ mEvent,
+ mEvent->refPoint).y;
+diff --git a/content/events/src/nsDOMTouchEvent.cpp b/content/events/src/nsDOMTouchEvent.cpp
+index ccf4864..64ab0e8 100644
+--- a/content/events/src/nsDOMTouchEvent.cpp
++++ b/content/events/src/nsDOMTouchEvent.cpp
+@@ -44,14 +44,16 @@ nsDOMTouch::GetTarget(nsIDOMEventTarget** aTarget)
+ NS_IMETHODIMP
+ nsDOMTouch::GetScreenX(int32_t* aScreenX)
+ {
+- *aScreenX = mScreenPoint.x;
++ bool isChrome = nsContentUtils::IsCallerChrome();
++ *aScreenX = isChrome ? mScreenPoint.x : mClientPoint.x;
+ return NS_OK;
+ }
+
+ NS_IMETHODIMP
+ nsDOMTouch::GetScreenY(int32_t* aScreenY)
+ {
+- *aScreenY = mScreenPoint.y;
++ bool isChrome = nsContentUtils::IsCallerChrome();
++ *aScreenY = isChrome ? mScreenPoint.y : mClientPoint.y;
+ return NS_OK;
+ }
+
+--
+1.7.5.4
+
diff --git a/src/current-patches/firefox/0022-Do-not-expose-physical-screen-info.-via-window-and-w.patch b/src/current-patches/firefox/0022-Do-not-expose-physical-screen-info.-via-window-and-w.patch
new file mode 100644
index 0000000..13551af
--- /dev/null
+++ b/src/current-patches/firefox/0022-Do-not-expose-physical-screen-info.-via-window-and-w.patch
@@ -0,0 +1,310 @@
+From c4e1460f46fc04d81ec643fa9680b8fad8bc2b29 Mon Sep 17 00:00:00 2001
+From: Kathleen Brade <brade at pearlcrescent.com>
+Date: Wed, 28 Nov 2012 11:25:14 -0500
+Subject: [PATCH 22/26] 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 | 90 +++++++++++++++++++++++++++++++++++++++++++
+ dom/base/nsScreen.h | 3 +
+ 4 files changed, 141 insertions(+), 0 deletions(-)
+
+diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp
+index 6acd80a..3a370c9 100644
+--- a/dom/base/nsGlobalWindow.cpp
++++ b/dom/base/nsGlobalWindow.cpp
+@@ -3742,6 +3742,10 @@ nsGlobalWindow::GetOuterWidth(int32_t* 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);
+@@ -3755,6 +3759,10 @@ nsGlobalWindow::GetOuterHeight(int32_t* 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);
+@@ -3817,6 +3825,12 @@ nsGlobalWindow::GetScreenX(int32_t* 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);
+@@ -3858,6 +3872,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;
+@@ -3868,6 +3888,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;
+@@ -4025,6 +4051,12 @@ nsGlobalWindow::GetScreenY(int32_t* 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);
+@@ -4071,6 +4103,20 @@ nsGlobalWindow::SetScreenY(int32_t 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 9acc1ea..4cb6938 100644
+--- a/dom/base/nsGlobalWindow.h
++++ b/dom/base/nsGlobalWindow.h
+@@ -827,6 +827,8 @@ protected:
+ nsresult SetOuterSize(int32_t aLengthCSSPixels, bool aIsWidth);
+ nsRect GetInnerScreenRect();
+
++ bool IsChrome();
++
+ bool IsFrame()
+ {
+ return GetParentInternal() != nullptr;
+diff --git a/dom/base/nsScreen.cpp b/dom/base/nsScreen.cpp
+index 41c32ad..4f3904d 100644
+--- a/dom/base/nsScreen.cpp
++++ b/dom/base/nsScreen.cpp
+@@ -115,6 +115,12 @@ NS_IMPL_EVENT_HANDLER(nsScreen, mozorientationchange)
+ NS_IMETHODIMP
+ nsScreen::GetTop(int32_t* aTop)
+ {
++ // For non-chrome callers, always return 0 to prevent fingerprinting.
++ if (!IsChrome()) {
++ *aTop = 0;
++ return NS_OK;
++ }
++
+ nsRect rect;
+ nsresult rv = GetRect(rect);
+
+@@ -127,6 +133,12 @@ nsScreen::GetTop(int32_t* aTop)
+ NS_IMETHODIMP
+ nsScreen::GetLeft(int32_t* aLeft)
+ {
++ // For non-chrome callers, always return 0 to prevent fingerprinting.
++ if (!IsChrome()) {
++ *aLeft = 0;
++ return NS_OK;
++ }
++
+ nsRect rect;
+ nsresult rv = GetRect(rect);
+
+@@ -139,6 +151,14 @@ nsScreen::GetLeft(int32_t* aLeft)
+ NS_IMETHODIMP
+ nsScreen::GetWidth(int32_t* 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);
+
+@@ -150,6 +170,14 @@ nsScreen::GetWidth(int32_t* aWidth)
+ NS_IMETHODIMP
+ nsScreen::GetHeight(int32_t* 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);
+
+@@ -161,6 +189,12 @@ nsScreen::GetHeight(int32_t* aHeight)
+ NS_IMETHODIMP
+ nsScreen::GetPixelDepth(int32_t* aPixelDepth)
+ {
++ // For non-chrome callers, always return 24 to prevent fingerprinting.
++ if (!IsChrome()) {
++ *aPixelDepth = 24;
++ return NS_OK;
++ }
++
+ nsDeviceContext* context = GetDeviceContext();
+
+ if (!context) {
+@@ -186,6 +220,14 @@ nsScreen::GetColorDepth(int32_t* aColorDepth)
+ NS_IMETHODIMP
+ nsScreen::GetAvailWidth(int32_t* 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);
+
+@@ -197,6 +239,14 @@ nsScreen::GetAvailWidth(int32_t* aAvailWidth)
+ NS_IMETHODIMP
+ nsScreen::GetAvailHeight(int32_t* 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);
+
+@@ -208,6 +258,12 @@ nsScreen::GetAvailHeight(int32_t* aAvailHeight)
+ NS_IMETHODIMP
+ nsScreen::GetAvailLeft(int32_t* aAvailLeft)
+ {
++ // For non-chrome callers, always return 0 to prevent fingerprinting.
++ if (!IsChrome()) {
++ *aAvailLeft = 0;
++ return NS_OK;
++ }
++
+ nsRect rect;
+ nsresult rv = GetAvailRect(rect);
+
+@@ -219,6 +275,12 @@ nsScreen::GetAvailLeft(int32_t* aAvailLeft)
+ NS_IMETHODIMP
+ nsScreen::GetAvailTop(int32_t* aAvailTop)
+ {
++ // For non-chrome callers, always return 0 to prevent fingerprinting.
++ if (!IsChrome()) {
++ *aAvailTop = 0;
++ return NS_OK;
++ }
++
+ nsRect rect;
+ nsresult rv = GetAvailRect(rect);
+
+@@ -458,3 +520,31 @@ nsScreen::FullScreenEventListener::HandleEvent(nsIDOMEvent* aEvent)
+
+ return NS_OK;
+ }
++
++bool
++nsScreen::IsChrome()
++{
++ bool isChrome = false;
++ nsCOMPtr<nsPIDOMWindow> owner = GetOwner();
++ if (owner)
++ isChrome = IsChromeType(owner->GetDocShell());
++
++ return isChrome;
++}
++
++nsresult
++nsScreen::GetDOMWindow(nsIDOMWindow **aResult)
++{
++ NS_ENSURE_ARG_POINTER(aResult);
++ *aResult = NULL;
++
++ nsCOMPtr<nsPIDOMWindow> owner = GetOwner();
++ if (!owner)
++ return NS_ERROR_FAILURE;
++
++ nsCOMPtr<nsIDOMWindow> win = do_QueryInterface(owner);
++ NS_ENSURE_STATE(win);
++ win.swap(*aResult);
++
++ return NS_OK;
++}
+diff --git a/dom/base/nsScreen.h b/dom/base/nsScreen.h
+index 869d4fd..de18504 100644
+--- a/dom/base/nsScreen.h
++++ b/dom/base/nsScreen.h
+@@ -16,6 +16,7 @@
+
+ class nsIDocShell;
+ class nsDeviceContext;
++class nsIDOMWindow;
+ struct nsRect;
+
+ // Script "screen" object
+@@ -41,6 +42,8 @@ protected:
+ nsDeviceContext* GetDeviceContext();
+ nsresult GetRect(nsRect& aRect);
+ nsresult GetAvailRect(nsRect& aRect);
++ bool IsChrome();
++ nsresult GetDOMWindow(nsIDOMWindow **aResult);
+
+ mozilla::dom::ScreenOrientation mOrientation;
+
+--
+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
deleted file mode 100644
index 6da9c72..0000000
--- a/src/current-patches/firefox/0022-Return-client-window-coordinates-for-mouse-event-scr.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-From 74215e38ba60b74df59216122c4f2cc068e33216 Mon Sep 17 00:00:00 2001
-From: Kathleen Brade <brade at 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
deleted file mode 100644
index 1b925e0..0000000
--- a/src/current-patches/firefox/0023-Do-not-expose-physical-screen-info.-via-window-and-w.patch
+++ /dev/null
@@ -1,312 +0,0 @@
-From d944531b020848e09ac280af11d039d992ab6461 Mon Sep 17 00:00:00 2001
-From: Kathleen Brade <brade at 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/0023-Do-not-expose-system-colors-to-CSS-or-canvas.patch b/src/current-patches/firefox/0023-Do-not-expose-system-colors-to-CSS-or-canvas.patch
new file mode 100644
index 0000000..ea6ee8f
--- /dev/null
+++ b/src/current-patches/firefox/0023-Do-not-expose-system-colors-to-CSS-or-canvas.patch
@@ -0,0 +1,466 @@
+From 0b97e36981bb26406087bbd502a4d9e91e33a150 Mon Sep 17 00:00:00 2001
+From: Kathleen Brade <brade at pearlcrescent.com>
+Date: Wed, 28 Nov 2012 15:08:40 -0500
+Subject: [PATCH 23/26] Do not expose system colors to CSS or canvas.
+
+---
+ content/canvas/src/nsCanvasRenderingContext2D.cpp | 28 +++-
+ .../canvas/src/nsCanvasRenderingContext2DAzure.cpp | 34 +++-
+ .../canvas/src/nsCanvasRenderingContext2DAzure.h | 5 +-
+ layout/style/nsRuleNode.cpp | 5 +-
+ widget/LookAndFeel.h | 9 +
+ widget/xpwidgets/nsXPLookAndFeel.cpp | 173 +++++++++++++++++++-
+ widget/xpwidgets/nsXPLookAndFeel.h | 5 +-
+ 7 files changed, 239 insertions(+), 20 deletions(-)
+
+diff --git a/content/canvas/src/nsCanvasRenderingContext2D.cpp b/content/canvas/src/nsCanvasRenderingContext2D.cpp
+index 0dec654..7132e4f 100644
+--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
++++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
+@@ -32,6 +32,7 @@
+ #include "nsCSSParser.h"
+ #include "mozilla/css/StyleRule.h"
+ #include "mozilla/css/Declaration.h"
++#include "mozilla/css/Loader.h"
+ #include "nsComputedDOMStyle.h"
+ #include "nsStyleSet.h"
+
+@@ -159,8 +160,9 @@ class nsCanvasGradient MOZ_FINAL : 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)
+ {
+ }
+
+@@ -181,8 +183,17 @@ public:
+ return NS_ERROR_DOM_SYNTAX_ERR;
+ }
+
++ nsIPresShell* presShell = nullptr;
++ if (mCSSLoader) {
++ nsIDocument *doc = mCSSLoader->GetDocument();
++ if (doc)
++ presShell = doc->GetShell();
++ }
++
+ nscolor color;
+- if (!nsRuleNode::ComputeColor(value, nullptr, nullptr, color)) {
++ if (!nsRuleNode::ComputeColor(value,
++ presShell ? presShell->GetPresContext() : nullptr,
++ nullptr, color)) {
+ return NS_ERROR_DOM_SYNTAX_ERR;
+ }
+
+@@ -194,6 +205,7 @@ public:
+ NS_DECL_ISUPPORTS
+
+ protected:
++ mozilla::css::Loader* mCSSLoader; // not ref counted, it owns us
+ nsRefPtr<gfxPattern> mPattern;
+ };
+
+@@ -1814,7 +1826,10 @@ nsCanvasRenderingContext2D::CreateLinearGradient(float x0, float y0, float x1, f
+ if (!gradpat)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+- nsRefPtr<nsIDOMCanvasGradient> grad = new nsCanvasGradient(gradpat);
++ nsIDocument* doc = mCanvasElement ? mCanvasElement->OwnerDoc() : nullptr;
++ mozilla::css::Loader* cssLoader = doc ? doc->CSSLoader() : nullptr;
++ nsRefPtr<nsIDOMCanvasGradient> grad = new nsCanvasGradient(cssLoader,
++ gradpat);
+ if (!grad)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+@@ -1836,7 +1851,10 @@ nsCanvasRenderingContext2D::CreateRadialGradient(float x0, float y0, float r0, f
+ if (!gradpat)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+- nsRefPtr<nsIDOMCanvasGradient> grad = new nsCanvasGradient(gradpat);
++ nsIDocument* doc = mCanvasElement ? mCanvasElement->OwnerDoc() : nullptr;
++ mozilla::css::Loader* cssLoader = doc ? doc->CSSLoader() : nullptr;
++ nsRefPtr<nsIDOMCanvasGradient> grad = new nsCanvasGradient(cssLoader,
++ gradpat);
+ if (!grad)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+diff --git a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+index d86ba32..84c1927 100644
+--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
++++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+@@ -31,6 +31,7 @@
+ #include "nsCSSParser.h"
+ #include "mozilla/css/StyleRule.h"
+ #include "mozilla/css/Declaration.h"
++#include "mozilla/css/Loader.h"
+ #include "nsComputedDOMStyle.h"
+ #include "nsStyleSet.h"
+
+@@ -140,9 +141,10 @@ NS_MEMORY_REPORTER_IMPLEMENT(CanvasAzureMemory,
+ 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)
+@@ -159,8 +161,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)
+ {
+@@ -363,8 +366,17 @@ nsCanvasGradientAzure::AddColorStop(float offset, const nsAString& colorstr)
+ return NS_ERROR_DOM_SYNTAX_ERR;
+ }
+
++ nsIPresShell* presShell = nullptr;
++ if (mCSSLoader) {
++ nsIDocument *doc = mCSSLoader->GetDocument();
++ if (doc)
++ presShell = doc->GetShell();
++ }
++
+ nscolor color;
+- if (!nsRuleNode::ComputeColor(value, nullptr, nullptr, color)) {
++ if (!nsRuleNode::ComputeColor(value,
++ presShell ? presShell->GetPresContext() : nullptr,
++ nullptr, color)) {
+ return NS_ERROR_DOM_SYNTAX_ERR;
+ }
+
+@@ -1788,8 +1800,10 @@ nsCanvasRenderingContext2DAzure::CreateLinearGradient(double x0, double y0, doub
+ return nullptr;
+ }
+
+- nsRefPtr<nsIDOMCanvasGradient> grad =
+- new nsCanvasLinearGradientAzure(Point(x0, y0), Point(x1, y1));
++ nsIDocument* doc = mCanvasElement ? mCanvasElement->OwnerDoc() : nullptr;
++ mozilla::css::Loader* cssLoader = doc ? doc->CSSLoader() : nullptr;
++ nsRefPtr<nsIDOMCanvasGradient> grad = new nsCanvasLinearGradientAzure(
++ cssLoader, Point(x0, y0), Point(x1, y1));
+
+ return grad.forget();
+ }
+@@ -1818,8 +1832,10 @@ nsCanvasRenderingContext2DAzure::CreateRadialGradient(double x0, double y0, doub
+ return nullptr;
+ }
+
+- nsRefPtr<nsIDOMCanvasGradient> grad =
+- new nsCanvasRadialGradientAzure(Point(x0, y0), r0, Point(x1, y1), r1);
++ nsIDocument* doc = mCanvasElement ? mCanvasElement->OwnerDoc() : nullptr;
++ mozilla::css::Loader* cssLoader = doc ? doc->CSSLoader() : nullptr;
++ nsRefPtr<nsIDOMCanvasGradient> grad = new nsCanvasRadialGradientAzure(
++ cssLoader, Point(x0, y0), r0, Point(x1, y1), r1);
+
+ return grad.forget();
+ }
+diff --git a/content/canvas/src/nsCanvasRenderingContext2DAzure.h b/content/canvas/src/nsCanvasRenderingContext2DAzure.h
+index 05ccf61..629d78a 100644
+--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.h
++++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.h
+@@ -71,11 +71,14 @@ public:
+ NS_IMETHOD AddColorStop(float offset, const nsAString& colorstr);
+
+ protected:
+- nsCanvasGradientAzure(Type aType) : mType(aType)
++ nsCanvasGradientAzure(mozilla::css::Loader* aLoader, Type aType)
++ : mCSSLoader(aLoader)
++ , mType(aType)
+ {}
+
+ nsTArray<mozilla::gfx::GradientStop> mRawStops;
+ mozilla::RefPtr<mozilla::gfx::GradientStops> mStops;
++ mozilla::css::Loader* mCSSLoader; // not ref counted, it owns us
+ Type mType;
+ virtual ~nsCanvasGradientAzure() {}
+ };
+diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp
+index 33ce21e..078af3e 100644
+--- a/layout/style/nsRuleNode.cpp
++++ b/layout/style/nsRuleNode.cpp
+@@ -746,7 +746,10 @@ static bool SetColor(const nsCSSValue& aValue, const nscolor aParentColor,
+ int32_t intValue = aValue.GetIntValue();
+ if (0 <= intValue) {
+ LookAndFeel::ColorID colorID = (LookAndFeel::ColorID) intValue;
+- if (NS_SUCCEEDED(LookAndFeel::GetColor(colorID, &aResult))) {
++ bool useStandinsForNativeColors = aPresContext &&
++ !aPresContext->IsChrome();
++ if (NS_SUCCEEDED(LookAndFeel::GetColor(colorID,
++ useStandinsForNativeColors, &aResult))) {
+ result = true;
+ }
+ }
+diff --git a/widget/LookAndFeel.h b/widget/LookAndFeel.h
+index e46bb13..59f00f5 100644
+--- a/widget/LookAndFeel.h
++++ b/widget/LookAndFeel.h
+@@ -446,6 +446,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/xpwidgets/nsXPLookAndFeel.cpp b/widget/xpwidgets/nsXPLookAndFeel.cpp
+index 50c2c86..20ccfef 100644
+--- a/widget/xpwidgets/nsXPLookAndFeel.cpp
++++ b/widget/xpwidgets/nsXPLookAndFeel.cpp
+@@ -476,6 +476,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;
+@@ -483,7 +632,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();
+@@ -569,7 +719,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;
+ }
+@@ -603,6 +756,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)) {
+@@ -693,7 +852,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/xpwidgets/nsXPLookAndFeel.h b/widget/xpwidgets/nsXPLookAndFeel.h
+index 69627d2..2729803 100644
+--- a/widget/xpwidgets/nsXPLookAndFeel.h
++++ b/widget/xpwidgets/nsXPLookAndFeel.h
+@@ -52,7 +52,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, int32_t &aResult);
+ virtual nsresult GetFloatImpl(FloatID aID, float &aResult);
+
+@@ -89,6 +90,8 @@ protected:
+ void InitColorFromPref(int32_t 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
+
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
deleted file mode 100644
index 629a759..0000000
--- a/src/current-patches/firefox/0024-Do-not-expose-system-colors-to-CSS-or-canvas.patch
+++ /dev/null
@@ -1,537 +0,0 @@
-From 38a469e05779315cb2990be60c13fb167812e54d Mon Sep 17 00:00:00 2001
-From: Kathleen Brade <brade at 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
-
diff --git a/src/current-patches/firefox/0024-Isolate-the-Image-Cache-per-url-bar-domain.patch b/src/current-patches/firefox/0024-Isolate-the-Image-Cache-per-url-bar-domain.patch
new file mode 100644
index 0000000..0f1a702
--- /dev/null
+++ b/src/current-patches/firefox/0024-Isolate-the-Image-Cache-per-url-bar-domain.patch
@@ -0,0 +1,912 @@
+From 56d3f40086757ecefe1efbeca00b285a13bde5d4 Mon Sep 17 00:00:00 2001
+From: Mike Perry <mikeperry-git at torproject.org>
+Date: Thu, 6 Dec 2012 14:19:34 -0800
+Subject: [PATCH 24/26] Isolate the Image Cache per url bar domain.
+
+The image cache maintains its own table outside of the main cache, and does
+not obey cacheKeys by default.
+---
+ content/base/src/nsContentUtils.cpp | 13 +-
+ embedding/browser/webBrowser/nsContextMenuInfo.cpp | 27 ++-
+ extensions/cookie/nsCookiePermission.cpp | 3 +
+ image/public/imgILoader.idl | 4 +-
+ image/src/imgLoader.cpp | 256 +++++++++++++-------
+ image/src/imgLoader.h | 20 +-
+ image/src/imgRequest.cpp | 11 +-
+ image/src/imgRequest.h | 3 +
+ layout/generic/nsImageFrame.cpp | 14 +-
+ netwerk/cookie/nsICookiePermission.idl | 1 +
+ toolkit/system/gnome/nsAlertsIconListener.cpp | 3 +-
+ widget/cocoa/nsMenuItemIconX.mm | 9 +-
+ 12 files changed, 246 insertions(+), 118 deletions(-)
+
+diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp
+index fe3c8a0..43f8f69 100644
+--- a/content/base/src/nsContentUtils.cpp
++++ b/content/base/src/nsContentUtils.cpp
+@@ -121,6 +121,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
+ #include "nsIWebNavigation.h"
+ #include "nsTextFragment.h"
+ #include "mozilla/Selection.h"
++#include "mozIThirdPartyUtil.h"
+
+ #ifdef IBMBIDI
+ #include "nsIBidiKeyboard.h"
+@@ -2743,8 +2744,6 @@ nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,
+ nsCOMPtr<nsILoadGroup> loadGroup = aLoadingDocument->GetDocumentLoadGroup();
+ NS_ASSERTION(loadGroup, "Could not get loadgroup; onload may fire too early");
+
+- nsIURI *documentURI = aLoadingDocument->GetDocumentURI();
+-
+ // check for a Content Security Policy to pass down to the channel that
+ // will get created to load the image
+ nsCOMPtr<nsIChannelPolicy> channelPolicy;
+@@ -2761,11 +2760,15 @@ nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,
+
+ // Make the URI immutable so people won't change it under us
+ NS_TryToSetImmutable(aURI);
++
++ nsCOMPtr<nsIURI> firstPartyURI;
++ nsCOMPtr<mozIThirdPartyUtil> thirdPartySvc
++ = do_GetService(THIRDPARTYUTIL_CONTRACTID);
++ thirdPartySvc->GetFirstPartyURI(nullptr, aLoadingDocument,
++ getter_AddRefs(firstPartyURI));
+
+- // XXXbz using "documentURI" for the initialDocumentURI is not quite
+- // right, but the best we can do here...
+ return imgLoader->LoadImage(aURI, /* uri to load */
+- documentURI, /* initialDocumentURI */
++ firstPartyURI, /* firstPartyURI */
+ aReferrer, /* referrer */
+ aLoadingPrincipal, /* loading principal */
+ loadGroup, /* loadgroup */
+diff --git a/embedding/browser/webBrowser/nsContextMenuInfo.cpp b/embedding/browser/webBrowser/nsContextMenuInfo.cpp
+index 0a99427..02cd634 100644
+--- a/embedding/browser/webBrowser/nsContextMenuInfo.cpp
++++ b/embedding/browser/webBrowser/nsContextMenuInfo.cpp
+@@ -26,6 +26,7 @@
+ #include "nsIChannelPolicy.h"
+ #include "nsIContentSecurityPolicy.h"
+ #include "nsIContentPolicy.h"
++#include "mozIThirdPartyUtil.h"
+
+ //*****************************************************************************
+ // class nsContextMenuInfo
+@@ -269,15 +270,15 @@ nsContextMenuInfo::GetBackgroundImageRequestInternal(nsIDOMNode *aDOMNode, imgIR
+ nsCOMPtr<nsIPrincipal> principal;
+ nsCOMPtr<nsIChannelPolicy> channelPolicy;
+ nsCOMPtr<nsIContentSecurityPolicy> csp;
+- if (doc) {
+- principal = doc->NodePrincipal();
+- nsresult rv = principal->GetCsp(getter_AddRefs(csp));
+- NS_ENSURE_SUCCESS(rv, rv);
+- if (csp) {
+- channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
+- channelPolicy->SetContentSecurityPolicy(csp);
+- channelPolicy->SetLoadType(nsIContentPolicy::TYPE_IMAGE);
+- }
++ NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
++
++ principal = doc->NodePrincipal();
++ nsresult rv = principal->GetCsp(getter_AddRefs(csp));
++ NS_ENSURE_SUCCESS(rv, rv);
++ if (csp) {
++ channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
++ channelPolicy->SetContentSecurityPolicy(csp);
++ channelPolicy->SetLoadType(nsIContentPolicy::TYPE_IMAGE);
+ }
+
+ while (true) {
+@@ -305,7 +306,13 @@ nsContextMenuInfo::GetBackgroundImageRequestInternal(nsIDOMNode *aDOMNode, imgIR
+ "@mozilla.org/image/loader;1"));
+ NS_ENSURE_TRUE(il, NS_ERROR_FAILURE);
+
+- return il->LoadImage(bgUri, nullptr, nullptr, principal, nullptr,
++ nsCOMPtr<nsIURI> firstPartyURI;
++ nsCOMPtr<mozIThirdPartyUtil> thirdPartySvc
++ = do_GetService(THIRDPARTYUTIL_CONTRACTID);
++ thirdPartySvc->GetFirstPartyURI(nullptr, doc,
++ getter_AddRefs(firstPartyURI));
++
++ return il->LoadImage(bgUri, firstPartyURI, nullptr, principal, nullptr,
+ nullptr, nullptr, nsIRequest::LOAD_NORMAL, nullptr,
+ nullptr, channelPolicy, aRequest);
+ }
+diff --git a/extensions/cookie/nsCookiePermission.cpp b/extensions/cookie/nsCookiePermission.cpp
+index befa81a..e0b6e12 100644
+--- a/extensions/cookie/nsCookiePermission.cpp
++++ b/extensions/cookie/nsCookiePermission.cpp
+@@ -407,6 +407,9 @@ nsCookiePermission::GetOriginatingURI(nsIChannel *aChannel,
+
+ return NS_OK;
+ }
++
++ // TODO: Why don't we just use this here:
++ // httpChannelInternal->GetDocumentURI(aURI);
+ }
+
+ // find the associated window and its top window
+diff --git a/image/public/imgILoader.idl b/image/public/imgILoader.idl
+index da26463..ecff309 100644
+--- a/image/public/imgILoader.idl
++++ b/image/public/imgILoader.idl
+@@ -38,7 +38,7 @@ interface imgILoader : nsISupports
+ /**
+ * Start the load and decode of an image.
+ * @param aURI the URI to load
+- * @param aInitialDocumentURI the URI that 'initiated' the load -- used for 3rd party cookie blocking
++ * @param aFirstPartyURI the urlbar URI that 'initiated' the load -- used for 3rd party blocking
+ * @param aReferrerURI the 'referring' URI
+ * @param aLoadingPrincipal the principal of the loading document
+ * @param aLoadGroup Loadgroup to put the image load into
+@@ -57,7 +57,7 @@ interface imgILoader : nsISupports
+ * goes away.
+ */
+ imgIRequest loadImage(in nsIURI aURI,
+- in nsIURI aInitialDocumentURL,
++ in nsIURI aFirstPartyURI,
+ in nsIURI aReferrerURI,
+ in nsIPrincipal aLoadingPrincipal,
+ in nsILoadGroup aLoadGroup,
+diff --git a/image/src/imgLoader.cpp b/image/src/imgLoader.cpp
+index ea51e8d..88e367c 100644
+--- a/image/src/imgLoader.cpp
++++ b/image/src/imgLoader.cpp
+@@ -39,6 +39,7 @@
+ #include "nsCRT.h"
+ #include "nsIDocument.h"
+ #include "nsPIDOMWindow.h"
++#include "nsIConsoleService.h"
+
+ #include "netCore.h"
+
+@@ -58,6 +59,7 @@
+ #include "nsIHttpChannelInternal.h"
+ #include "nsIContentSecurityPolicy.h"
+ #include "nsIChannelPolicy.h"
++#include "mozIThirdPartyUtil.h"
+
+ #include "nsContentUtils.h"
+
+@@ -432,7 +434,7 @@ static nsresult NewImageChannel(nsIChannel **aResult,
+ // aLoadingPrincipal and false otherwise.
+ bool *aForcePrincipalCheckForCacheEntry,
+ nsIURI *aURI,
+- nsIURI *aInitialDocumentURI,
++ nsIURI *aFirstPartyURI,
+ nsIURI *aReferringURI,
+ nsILoadGroup *aLoadGroup,
+ const nsCString& aAcceptHeader,
+@@ -484,7 +486,7 @@ static nsresult NewImageChannel(nsIChannel **aResult,
+
+ nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal = do_QueryInterface(newHttpChannel);
+ NS_ENSURE_TRUE(httpChannelInternal, NS_ERROR_UNEXPECTED);
+- httpChannelInternal->SetDocumentURI(aInitialDocumentURI);
++ httpChannelInternal->SetDocumentURI(aFirstPartyURI);
+ newHttpChannel->SetReferrer(aReferringURI);
+ }
+
+@@ -925,34 +927,62 @@ NS_IMETHODIMP imgLoader::ClearCache(bool chrome)
+ /* void removeEntry(in nsIURI uri); */
+ NS_IMETHODIMP imgLoader::RemoveEntry(nsIURI *uri)
+ {
+- if (RemoveFromCache(uri))
++ if (RemoveMatchingUrlsFromCache(uri))
+ return NS_OK;
+
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
++static PLDHashOperator EnumAllEntries(const nsACString&,
++ nsRefPtr<imgCacheEntry> &aData,
++ void *data)
++{
++ nsTArray<nsRefPtr<imgCacheEntry> > *entries =
++ reinterpret_cast<nsTArray<nsRefPtr<imgCacheEntry> > *>(data);
++
++ entries->AppendElement(aData);
++
++ return PL_DHASH_NEXT;
++}
++
+ /* imgIRequest findEntry(in nsIURI uri); */
+ NS_IMETHODIMP imgLoader::FindEntryProperties(nsIURI *uri, nsIProperties **_retval)
+ {
+ nsRefPtr<imgCacheEntry> entry;
+- nsCAutoString spec;
+ imgCacheTable &cache = GetCache(uri);
+-
+- uri->GetSpec(spec);
+ *_retval = nullptr;
+
+- if (cache.Get(spec, getter_AddRefs(entry)) && entry) {
+- if (gCacheTracker && entry->HasNoProxies())
+- gCacheTracker->MarkUsed(entry);
++ // We must traverse the whole cache in O(N) looking for the first
++ // matching URI.
++ //
++ // TODO: For now, it's ok to pick at random here. The images should be
++ // identical unless there is a cache-tracking attack. And even if they
++ // are not identical due to attack, this code is only used for save
++ // dialogs at this point, so no differentiating info is leaked to
++ // content.
++ nsTArray<nsRefPtr<imgCacheEntry> > entries;
++ cache.Enumerate(EnumAllEntries, &entries);
+
+- nsRefPtr<imgRequest> request = getter_AddRefs(entry->GetRequest());
++ for (uint32_t i = 0; i < entries.Length(); ++i) {
++ bool isEqual = false;
++
++ nsRefPtr<imgRequest> request = getter_AddRefs(entries[i]->GetRequest());
+ if (request) {
+- *_retval = request->Properties();
+- NS_ADDREF(*_retval);
++ request->mURI->Equals(uri, &isEqual);
++ if (isEqual) {
++ if (gCacheTracker && entries[i]->HasNoProxies())
++ gCacheTracker->MarkUsed(entries[i]);
++
++ *_retval = request->Properties();
++ NS_ADDREF(*_retval);
++ }
+ }
+ }
+
+- return NS_OK;
++ if (*_retval)
++ return NS_OK;
++
++ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ void imgLoader::Shutdown()
+@@ -980,20 +1010,18 @@ void imgLoader::MinimizeCaches()
+ EvictEntries(sChromeCacheQueue);
+ }
+
+-bool imgLoader::PutIntoCache(nsIURI *key, imgCacheEntry *entry)
++bool imgLoader::PutIntoCache(nsCAutoString key,
++ imgCacheEntry *entry)
+ {
+- imgCacheTable &cache = GetCache(key);
+-
+- nsCAutoString spec;
+- key->GetSpec(spec);
+-
+- LOG_STATIC_FUNC_WITH_PARAM(gImgLog, "imgLoader::PutIntoCache", "uri", spec.get());
++ LOG_STATIC_FUNC_WITH_PARAM(gImgLog, "imgLoader::PutIntoCache", "uri", key.get());
++ imgCacheTable &cache = GetCache(entry->mRequest->mURI);
++ imgCacheQueue &queue = GetCacheQueue(entry->mRequest->mURI);
+
+ // Check to see if this request already exists in the cache and is being
+ // loaded on a different thread. If so, don't allow this entry to be added to
+ // the cache.
+ nsRefPtr<imgCacheEntry> tmpCacheEntry;
+- if (cache.Get(spec, getter_AddRefs(tmpCacheEntry)) && tmpCacheEntry) {
++ if (cache.Get(key, getter_AddRefs(tmpCacheEntry)) && tmpCacheEntry) {
+ PR_LOG(gImgLog, PR_LOG_DEBUG,
+ ("[this=%p] imgLoader::PutIntoCache -- Element already in the cache", nullptr));
+ nsRefPtr<imgRequest> tmpRequest = getter_AddRefs(tmpCacheEntry->GetRequest());
+@@ -1003,13 +1031,13 @@ bool imgLoader::PutIntoCache(nsIURI *key, imgCacheEntry *entry)
+ PR_LOG(gImgLog, PR_LOG_DEBUG,
+ ("[this=%p] imgLoader::PutIntoCache -- Replacing cached element", nullptr));
+
+- RemoveFromCache(key);
++ RemoveKeyFromCache(cache, queue, key);
+ } else {
+ PR_LOG(gImgLog, PR_LOG_DEBUG,
+ ("[this=%p] imgLoader::PutIntoCache -- Element NOT already in the cache", nullptr));
+ }
+
+- cache.Put(spec, entry);
++ cache.Put(key, entry);
+
+ // We can be called to resurrect an evicted entry.
+ if (entry->Evicted())
+@@ -1024,7 +1052,6 @@ bool imgLoader::PutIntoCache(nsIURI *key, imgCacheEntry *entry)
+ addrv = gCacheTracker->AddObject(entry);
+
+ if (NS_SUCCEEDED(addrv)) {
+- imgCacheQueue &queue = GetCacheQueue(key);
+ queue.Push(entry);
+ }
+ }
+@@ -1035,11 +1062,11 @@ bool imgLoader::PutIntoCache(nsIURI *key, imgCacheEntry *entry)
+ return true;
+ }
+
+-bool imgLoader::SetHasNoProxies(nsIURI *key, imgCacheEntry *entry)
++bool imgLoader::SetHasNoProxies(nsIURI *imgURI, imgCacheEntry *entry)
+ {
+ #if defined(PR_LOGGING)
+ nsCAutoString spec;
+- key->GetSpec(spec);
++ imgURI->GetSpec(spec);
+
+ LOG_STATIC_FUNC_WITH_PARAM(gImgLog, "imgLoader::SetHasNoProxies", "uri", spec.get());
+ #endif
+@@ -1047,7 +1074,7 @@ bool imgLoader::SetHasNoProxies(nsIURI *key, imgCacheEntry *entry)
+ if (entry->Evicted())
+ return false;
+
+- imgCacheQueue &queue = GetCacheQueue(key);
++ imgCacheQueue &queue = GetCacheQueue(imgURI);
+
+ nsresult addrv = NS_OK;
+
+@@ -1059,26 +1086,27 @@ bool imgLoader::SetHasNoProxies(nsIURI *key, imgCacheEntry *entry)
+ entry->SetHasNoProxies(true);
+ }
+
+- imgCacheTable &cache = GetCache(key);
++ imgCacheTable &cache = GetCache(imgURI);
+ CheckCacheLimits(cache, queue);
+
+ return true;
+ }
+
+-bool imgLoader::SetHasProxies(nsIURI *key)
++bool imgLoader::SetHasProxies(nsIURI *firstPartyURI, nsIURI *imgURI)
+ {
+ VerifyCacheSizes();
+
+- imgCacheTable &cache = GetCache(key);
++ imgCacheTable &cache = GetCache(imgURI);
+
+ nsCAutoString spec;
+- key->GetSpec(spec);
++ imgURI->GetSpec(spec);
+
+ LOG_STATIC_FUNC_WITH_PARAM(gImgLog, "imgLoader::SetHasProxies", "uri", spec.get());
+
++ nsCAutoString key = GetCacheKey(firstPartyURI, imgURI);
+ nsRefPtr<imgCacheEntry> entry;
+- if (cache.Get(spec, getter_AddRefs(entry)) && entry && entry->HasNoProxies()) {
+- imgCacheQueue &queue = GetCacheQueue(key);
++ if (cache.Get(key, getter_AddRefs(entry)) && entry && entry->HasNoProxies()) {
++ imgCacheQueue &queue = GetCacheQueue(imgURI);
+ queue.Remove(entry);
+
+ if (gCacheTracker)
+@@ -1130,7 +1158,7 @@ void imgLoader::CheckCacheLimits(imgCacheTable &cache, imgCacheQueue &queue)
+
+ bool imgLoader::ValidateRequestWithNewChannel(imgRequest *request,
+ nsIURI *aURI,
+- nsIURI *aInitialDocumentURI,
++ nsIURI *aFirstPartyURI,
+ nsIURI *aReferrerURI,
+ nsILoadGroup *aLoadGroup,
+ imgIDecoderObserver *aObserver,
+@@ -1182,7 +1210,7 @@ bool imgLoader::ValidateRequestWithNewChannel(imgRequest *request,
+ rv = NewImageChannel(getter_AddRefs(newChannel),
+ &forcePrincipalCheck,
+ aURI,
+- aInitialDocumentURI,
++ aFirstPartyURI,
+ aReferrerURI,
+ aLoadGroup,
+ mAcceptHeader,
+@@ -1251,7 +1279,7 @@ bool imgLoader::ValidateRequestWithNewChannel(imgRequest *request,
+
+ bool imgLoader::ValidateEntry(imgCacheEntry *aEntry,
+ nsIURI *aURI,
+- nsIURI *aInitialDocumentURI,
++ nsIURI *aFirstPartyURI,
+ nsIURI *aReferrerURI,
+ nsILoadGroup *aLoadGroup,
+ imgIDecoderObserver *aObserver,
+@@ -1357,7 +1385,7 @@ bool imgLoader::ValidateEntry(imgCacheEntry *aEntry,
+ if (validateRequest && aCanMakeNewChannel) {
+ LOG_SCOPE(gImgLog, "imgLoader::ValidateRequest |cache hit| must validate");
+
+- return ValidateRequestWithNewChannel(request, aURI, aInitialDocumentURI,
++ return ValidateRequestWithNewChannel(request, aURI, aFirstPartyURI,
+ aReferrerURI, aLoadGroup, aObserver,
+ aCX, aLoadFlags, aExistingRequest,
+ aProxyRequest, aPolicy,
+@@ -1367,22 +1395,40 @@ bool imgLoader::ValidateEntry(imgCacheEntry *aEntry,
+ return !validateRequest;
+ }
+
+-
+-bool imgLoader::RemoveFromCache(nsIURI *aKey)
++bool imgLoader::RemoveMatchingUrlsFromCache(nsIURI *aImgURI)
+ {
+- if (!aKey) return false;
++ if (!aImgURI) return false;
+
+- imgCacheTable &cache = GetCache(aKey);
+- imgCacheQueue &queue = GetCacheQueue(aKey);
++ bool rv = true;
++ imgCacheTable &cache = GetCache(aImgURI);
+
+- nsCAutoString spec;
+- aKey->GetSpec(spec);
++ // We have to make a temporary, since RemoveFromCache removes the element
++ // from the queue, invalidating iterators.
++ nsTArray<nsRefPtr<imgCacheEntry> > entries;
++ cache.Enumerate(EnumAllEntries, &entries);
++
++ for (uint32_t i = 0; i < entries.Length(); ++i) {
++ bool isEqual = false;
++
++ entries[i]->mRequest->mURI->Equals(aImgURI, &isEqual);
++ if (isEqual && !RemoveFromCache(entries[i]))
++ rv = false;
++ }
++
++ return rv;
++}
+
+- LOG_STATIC_FUNC_WITH_PARAM(gImgLog, "imgLoader::RemoveFromCache", "uri", spec.get());
++bool imgLoader::RemoveKeyFromCache(imgCacheTable &cache,
++ imgCacheQueue &queue,
++ nsCAutoString key)
++{
++ if (key.IsEmpty()) return false;
++
++ LOG_STATIC_FUNC_WITH_PARAM(gImgLog, "imgLoader::RemoveKeyFromCache", "uri", key.get());
+
+ nsRefPtr<imgCacheEntry> entry;
+- if (cache.Get(spec, getter_AddRefs(entry)) && entry) {
+- cache.Remove(spec);
++ if (cache.Get(key, getter_AddRefs(entry)) && entry) {
++ cache.Remove(key);
+
+ NS_ABORT_IF_FALSE(!entry->Evicted(), "Evicting an already-evicted cache entry!");
+
+@@ -1410,12 +1456,13 @@ bool imgLoader::RemoveFromCache(imgCacheEntry *entry)
+
+ nsRefPtr<imgRequest> request(getter_AddRefs(entry->GetRequest()));
+ if (request) {
+- nsCOMPtr<nsIURI> key;
+- if (NS_SUCCEEDED(request->GetURI(getter_AddRefs(key))) && key) {
+- imgCacheTable &cache = GetCache(key);
+- imgCacheQueue &queue = GetCacheQueue(key);
+- nsCAutoString spec;
+- key->GetSpec(spec);
++ nsCOMPtr<nsIURI> imgURI = request->mURI;
++ nsCOMPtr<nsIURI> firstPartyURI = request->mFirstPartyURI;
++
++ if (imgURI && firstPartyURI) {
++ imgCacheTable &cache = GetCache(imgURI);
++ imgCacheQueue &queue = GetCacheQueue(imgURI);
++ nsCAutoString spec = GetCacheKey(firstPartyURI, imgURI);
+
+ LOG_STATIC_FUNC_WITH_PARAM(gImgLog, "imgLoader::RemoveFromCache", "entry's uri", spec.get());
+
+@@ -1438,18 +1485,6 @@ bool imgLoader::RemoveFromCache(imgCacheEntry *entry)
+ return false;
+ }
+
+-static PLDHashOperator EnumEvictEntries(const nsACString&,
+- nsRefPtr<imgCacheEntry> &aData,
+- void *data)
+-{
+- nsTArray<nsRefPtr<imgCacheEntry> > *entries =
+- reinterpret_cast<nsTArray<nsRefPtr<imgCacheEntry> > *>(data);
+-
+- entries->AppendElement(aData);
+-
+- return PL_DHASH_NEXT;
+-}
+-
+ nsresult imgLoader::EvictEntries(imgCacheTable &aCacheToClear)
+ {
+ LOG_STATIC_FUNC(gImgLog, "imgLoader::EvictEntries table");
+@@ -1457,7 +1492,7 @@ nsresult imgLoader::EvictEntries(imgCacheTable &aCacheToClear)
+ // We have to make a temporary, since RemoveFromCache removes the element
+ // from the queue, invalidating iterators.
+ nsTArray<nsRefPtr<imgCacheEntry> > entries;
+- aCacheToClear.Enumerate(EnumEvictEntries, &entries);
++ aCacheToClear.Enumerate(EnumAllEntries, &entries);
+
+ for (uint32_t i = 0; i < entries.Length(); ++i)
+ if (!RemoveFromCache(entries[i]))
+@@ -1490,11 +1525,10 @@ nsresult imgLoader::EvictEntries(imgCacheQueue &aQueueToClear)
+ nsIRequest::VALIDATE_NEVER | \
+ nsIRequest::VALIDATE_ONCE_PER_SESSION)
+
+-
+-/* imgIRequest loadImage (in nsIURI aURI, in nsIURI initialDocumentURI, in nsIPrincipal loadingPrincipal, in nsILoadGroup aLoadGroup, in imgIDecoderObserver aObserver, in nsISupports aCX, in nsLoadFlags aLoadFlags, in nsISupports cacheKey, in imgIRequest aRequest); */
++/* imgIRequest loadImage (in nsIURI aURI, in nsIURI aUrlBarURI, in nsIPrincipal loadingPrincipal, in nsILoadGroup aLoadGroup, in imgIDecoderObserver aObserver, in nsISupports aCX, in nsLoadFlags aLoadFlags, in nsISupports cacheKey, in imgIRequest aRequest); */
+
+ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI,
+- nsIURI *aInitialDocumentURI,
++ nsIURI *aFirstPartyURI,
+ nsIURI *aReferrerURI,
+ nsIPrincipal* aLoadingPrincipal,
+ nsILoadGroup *aLoadGroup,
+@@ -1513,8 +1547,8 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI,
+ if (!aURI)
+ return NS_ERROR_NULL_POINTER;
+
+- nsCAutoString spec;
+- aURI->GetSpec(spec);
++ nsCAutoString spec = GetCacheKey(aFirstPartyURI, aURI);
++
+ LOG_SCOPE_WITH_PARAM(gImgLog, "imgLoader::LoadImage", "aURI", spec.get());
+
+ *_retval = nullptr;
+@@ -1566,7 +1600,7 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI,
+ imgCacheTable &cache = GetCache(aURI);
+
+ if (cache.Get(spec, getter_AddRefs(entry)) && entry) {
+- if (ValidateEntry(entry, aURI, aInitialDocumentURI, aReferrerURI,
++ if (ValidateEntry(entry, aURI, aFirstPartyURI, aReferrerURI,
+ aLoadGroup, aObserver, aCX, requestFlags, true,
+ aRequest, _retval, aPolicy, aLoadingPrincipal, corsmode)) {
+ request = getter_AddRefs(entry->GetRequest());
+@@ -1605,7 +1639,7 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI,
+ rv = NewImageChannel(getter_AddRefs(newChannel),
+ &forcePrincipalCheck,
+ aURI,
+- aInitialDocumentURI,
++ aFirstPartyURI,
+ aReferrerURI,
+ aLoadGroup,
+ mAcceptHeader,
+@@ -1627,8 +1661,8 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI,
+ do_CreateInstance(NS_LOADGROUP_CONTRACTID);
+ newChannel->SetLoadGroup(loadGroup);
+
+- request->Init(aURI, aURI, loadGroup, newChannel, entry, aCX,
+- aLoadingPrincipal, corsmode);
++ request->Init(aURI, aURI, aFirstPartyURI, loadGroup, newChannel, entry,
++ aCX, aLoadingPrincipal, corsmode);
+
+ // Pass the inner window ID of the loading document, if possible.
+ nsCOMPtr<nsIDocument> doc = do_QueryInterface(aCX);
+@@ -1676,7 +1710,7 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI,
+ }
+
+ // Try to add the new request into the cache.
+- PutIntoCache(aURI, entry);
++ PutIntoCache(spec, entry);
+ } else {
+ LOG_MSG_WITH_PARAM(gImgLog,
+ "imgLoader::LoadImage |cache hit|", "request", request);
+@@ -1736,6 +1770,48 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI,
+ return NS_OK;
+ }
+
++nsCAutoString imgLoader::GetCacheKey(nsIURI *firstPartyURI, nsIURI *imgURI)
++{
++ NS_ASSERTION(imgURI, "imgLoader::GetCacheKey -- NULL imgURI");
++
++ nsCAutoString spec, hostKey;
++ if (imgURI)
++ imgURI->GetSpec(spec);
++
++#if 0
++ bool isChrome = false;
++ if (imgURI)
++ imgURI->SchemeIs("chrome", &isChrome);
++ if (isChrome)
++ return spec; // No partitioning needed for chrome; just use a simple key.
++#endif
++
++ // FIXME: Should we use mozIThirdPartyUtil to get a domain from this?
++ if (firstPartyURI)
++ firstPartyURI->GetHost(hostKey);
++ else {
++ hostKey = "--NoFirstParty--";
++ nsCOMPtr<nsIConsoleService> consoleSvc =
++ do_GetService(NS_CONSOLESERVICE_CONTRACTID);
++ if (consoleSvc) {
++ nsAutoString msg(NS_LITERAL_STRING("imgLoader::GetCacheKey: NULL"
++ " firstPartyURI for ").get());
++ msg.AppendASCII(spec.get());
++ consoleSvc->LogStringMessage(msg.get());
++ }
++
++#ifdef DEBUG
++ printf("imgLoader::GetCacheKey: NULL firstPartyURI for %s\n", spec.get());
++#endif
++ }
++
++ // Make a new key using host
++ // FIXME: This might involve a couple more copies than necessary..
++ // But man, 18 string types? Who knows which one I need to use to do
++ // this cheaply..
++ return hostKey + nsCAutoString("&") + spec;
++}
++
+ /* imgIRequest loadImageWithChannel(in nsIChannel channel, in imgIDecoderObserver aObserver, in nsISupports cx, out nsIStreamListener); */
+ NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderObserver *aObserver, nsISupports *aCX, nsIStreamListener **listener, imgIRequest **_retval)
+ {
+@@ -1746,22 +1822,27 @@ NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderOb
+ nsCOMPtr<nsIURI> uri;
+ channel->GetURI(getter_AddRefs(uri));
+
++ nsCOMPtr<nsIURI> firstPartyURI;
++ nsCOMPtr<mozIThirdPartyUtil> thirdPartySvc
++ = do_GetService(THIRDPARTYUTIL_CONTRACTID);
++ thirdPartySvc->GetFirstPartyURI(channel, nullptr,
++ getter_AddRefs(firstPartyURI));
++
+ nsLoadFlags requestFlags = nsIRequest::LOAD_NORMAL;
+ channel->GetLoadFlags(&requestFlags);
+
+ nsRefPtr<imgCacheEntry> entry;
++ imgCacheTable &cache = GetCache(uri);
++ nsCAutoString spec = GetCacheKey(firstPartyURI, uri);
+
+ if (requestFlags & nsIRequest::LOAD_BYPASS_CACHE) {
+- RemoveFromCache(uri);
++ imgCacheQueue &queue = GetCacheQueue(uri);
++ RemoveKeyFromCache(cache, queue, spec);
+ } else {
+ // Look in the cache for our URI, and then validate it.
+ // XXX For now ignore aCacheKey. We will need it in the future
+ // for correctly dealing with image load requests that are a result
+ // of post data.
+- imgCacheTable &cache = GetCache(uri);
+- nsCAutoString spec;
+-
+- uri->GetSpec(spec);
+
+ if (cache.Get(spec, getter_AddRefs(entry)) && entry) {
+ // We don't want to kick off another network load. So we ask
+@@ -1833,7 +1914,7 @@ NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderOb
+ channel->GetOriginalURI(getter_AddRefs(originalURI));
+
+ // No principal specified here, because we're not passed one.
+- request->Init(originalURI, uri, channel, channel, entry,
++ request->Init(originalURI, uri, firstPartyURI, channel, channel, entry,
+ aCX, nullptr, imgIRequest::CORS_NONE);
+
+ ProxyListener *pl = new ProxyListener(static_cast<nsIStreamListener *>(request.get()));
+@@ -1845,7 +1926,7 @@ NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderOb
+ NS_RELEASE(pl);
+
+ // Try to add the new request into the cache.
+- PutIntoCache(originalURI, entry);
++ PutIntoCache(GetCacheKey(originalURI, firstPartyURI), entry);
+
+ rv = CreateNewProxyForRequest(request, loadGroup, aObserver,
+ requestFlags, nullptr, _retval);
+@@ -2132,6 +2213,7 @@ NS_IMETHODIMP imgCacheValidator::OnStartRequest(nsIRequest *aRequest, nsISupport
+
+ int32_t corsmode = mRequest->GetCORSMode();
+ nsCOMPtr<nsIPrincipal> loadingPrincipal = mRequest->GetLoadingPrincipal();
++ nsCOMPtr<nsIURI> firstPartyURI = mRequest->mFirstPartyURI;
+
+ // Doom the old request's cache entry
+ mRequest->RemoveFromCache();
+@@ -2142,16 +2224,16 @@ NS_IMETHODIMP imgCacheValidator::OnStartRequest(nsIRequest *aRequest, nsISupport
+ // We use originalURI here to fulfil the imgIRequest contract on GetURI.
+ nsCOMPtr<nsIURI> originalURI;
+ channel->GetOriginalURI(getter_AddRefs(originalURI));
+- mNewRequest->Init(originalURI, uri, aRequest, channel, mNewEntry,
+- mContext, loadingPrincipal,
+- corsmode);
++ mNewRequest->Init(originalURI, uri, firstPartyURI, aRequest, channel,
++ mNewEntry, mContext, loadingPrincipal, corsmode);
+
+ mDestListener = new ProxyListener(mNewRequest);
+
+ // Try to add the new request into the cache. Note that the entry must be in
+ // the cache before the proxies' ownership changes, because adding a proxy
+ // changes the caching behaviour for imgRequests.
+- sImgLoader.PutIntoCache(originalURI, mNewEntry);
++ sImgLoader.PutIntoCache(imgLoader::GetCacheKey(firstPartyURI, originalURI),
++ mNewEntry);
+
+ uint32_t count = mProxies.Count();
+ for (int32_t i = count-1; i>=0; i--) {
+diff --git a/image/src/imgLoader.h b/image/src/imgLoader.h
+index 64d3563..c275d83 100644
+--- a/image/src/imgLoader.h
++++ b/image/src/imgLoader.h
+@@ -227,10 +227,11 @@ public:
+
+ static nsresult InitCache();
+
+- static bool RemoveFromCache(nsIURI *aKey);
++ static nsCAutoString GetCacheKey(nsIURI *firstPartyURI,
++ nsIURI *imgURI);
+ static bool RemoveFromCache(imgCacheEntry *entry);
+-
+- static bool PutIntoCache(nsIURI *key, imgCacheEntry *entry);
++ static bool PutIntoCache(nsCAutoString key, imgCacheEntry *entry);
++ static bool RemoveMatchingUrlsFromCache(nsIURI *aKey);
+
+ // Returns true if we should prefer evicting cache entry |two| over cache
+ // entry |one|.
+@@ -269,14 +270,14 @@ public:
+ // HasObservers(). The request's cache entry will be re-set before this
+ // happens, by calling imgRequest::SetCacheEntry() when an entry with no
+ // observers is re-requested.
+- static bool SetHasNoProxies(nsIURI *key, imgCacheEntry *entry);
+- static bool SetHasProxies(nsIURI *key);
++ static bool SetHasProxies(nsIURI *firstPartyURI, nsIURI *imgURI);
++ static bool SetHasNoProxies(nsIURI *imgURI, imgCacheEntry *entry);
+
+ private: // methods
+
+
+- bool ValidateEntry(imgCacheEntry *aEntry, nsIURI *aKey,
+- nsIURI *aInitialDocumentURI, nsIURI *aReferrerURI,
++ bool ValidateEntry(imgCacheEntry *aEntry, nsIURI *aURI,
++ nsIURI *aFirstPartyURI, nsIURI *aReferrerURI,
+ nsILoadGroup *aLoadGroup,
+ imgIDecoderObserver *aObserver, nsISupports *aCX,
+ nsLoadFlags aLoadFlags, bool aCanMakeNewChannel,
+@@ -315,9 +316,14 @@ private: // methods
+ static void CacheEntriesChanged(nsIURI *aURI, int32_t sizediff = 0);
+ static void CheckCacheLimits(imgCacheTable &cache, imgCacheQueue &queue);
+
++ static bool RemoveKeyFromCache(imgCacheTable &cache,
++ imgCacheQueue &queue,
++ nsCAutoString key);
++
+ private: // data
+ friend class imgCacheEntry;
+ friend class imgMemoryReporter;
++ friend class imgRequest;
+
+ static imgCacheTable sCache;
+ static imgCacheQueue sCacheQueue;
+diff --git a/image/src/imgRequest.cpp b/image/src/imgRequest.cpp
+index e89e05a..71afe2c 100644
+--- a/image/src/imgRequest.cpp
++++ b/image/src/imgRequest.cpp
+@@ -103,6 +103,7 @@ imgRequest::~imgRequest()
+
+ nsresult imgRequest::Init(nsIURI *aURI,
+ nsIURI *aCurrentURI,
++ nsIURI *aFirstPartyURI,
+ nsIRequest *aRequest,
+ nsIChannel *aChannel,
+ imgCacheEntry *aCacheEntry,
+@@ -124,6 +125,7 @@ nsresult imgRequest::Init(nsIURI *aURI,
+
+ mURI = aURI;
+ mCurrentURI = aCurrentURI;
++ mFirstPartyURI = aFirstPartyURI;
+ mRequest = aRequest;
+ mChannel = aChannel;
+ mTimedChannel = do_QueryInterface(mChannel);
+@@ -178,7 +180,7 @@ nsresult imgRequest::AddProxy(imgRequestProxy *proxy)
+ // proxies.
+ if (mObservers.IsEmpty()) {
+ NS_ABORT_IF_FALSE(mURI, "Trying to SetHasProxies without key uri.");
+- imgLoader::SetHasProxies(mURI);
++ imgLoader::SetHasProxies(mFirstPartyURI, mURI);
+ }
+
+ // If we don't have any current observers, we should restart any animation.
+@@ -329,8 +331,11 @@ void imgRequest::RemoveFromCache()
+ // mCacheEntry is nulled out when we have no more observers.
+ if (mCacheEntry)
+ imgLoader::RemoveFromCache(mCacheEntry);
+- else
+- imgLoader::RemoveFromCache(mURI);
++ else {
++ imgLoader::RemoveKeyFromCache(imgLoader::GetCache(mURI),
++ imgLoader::GetCacheQueue(mURI),
++ imgLoader::GetCacheKey(mFirstPartyURI, mURI));
++ }
+ }
+
+ mCacheEntry = nullptr;
+diff --git a/image/src/imgRequest.h b/image/src/imgRequest.h
+index 424631b..7e1180f 100644
+--- a/image/src/imgRequest.h
++++ b/image/src/imgRequest.h
+@@ -57,6 +57,7 @@ public:
+
+ nsresult Init(nsIURI *aURI,
+ nsIURI *aCurrentURI,
++ nsIURI *aFirstPartyURI,
+ nsIRequest *aRequest,
+ nsIChannel *aChannel,
+ imgCacheEntry *aCacheEntry,
+@@ -189,6 +190,8 @@ private:
+ nsCOMPtr<nsIURI> mURI;
+ // The URI of the resource we ended up loading after all redirects, etc.
+ nsCOMPtr<nsIURI> mCurrentURI;
++ // The first party that triggered the load -- for cookie + cache isolation
++ nsCOMPtr<nsIURI> mFirstPartyURI;
+ // The principal of the document which loaded this image. Used when validating for CORS.
+ nsCOMPtr<nsIPrincipal> mLoadingPrincipal;
+ // The principal of this image.
+diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp
+index 748107d..3ecb1e9 100644
+--- a/layout/generic/nsImageFrame.cpp
++++ b/layout/generic/nsImageFrame.cpp
+@@ -63,6 +63,7 @@
+ #include "nsError.h"
+ #include "nsBidiUtils.h"
+ #include "nsBidiPresUtils.h"
++#include "mozIThirdPartyUtil.h"
+
+ #include "gfxRect.h"
+ #include "ImageLayers.h"
+@@ -1777,6 +1778,7 @@ nsImageFrame::LoadIcon(const nsAString& aSpec,
+ {
+ nsresult rv = NS_OK;
+ NS_PRECONDITION(!aSpec.IsEmpty(), "What happened??");
++ NS_PRECONDITION(aPresContext, "NULL PresContext");
+
+ if (!sIOService) {
+ rv = CallGetService(NS_IOSERVICE_CONTRACTID, &sIOService);
+@@ -1794,9 +1796,17 @@ nsImageFrame::LoadIcon(const nsAString& aSpec,
+
+ // For icon loads, we don't need to merge with the loadgroup flags
+ nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL;
+-
++
++ nsCOMPtr<nsIURI> firstPartyURI;
++ nsCOMPtr<mozIThirdPartyUtil> thirdPartySvc
++ = do_GetService(THIRDPARTYUTIL_CONTRACTID);
++ // XXX: Should we pass the loadgroup, too? Is document ever likely
++ // to be unset?
++ thirdPartySvc->GetFirstPartyURI(nullptr, aPresContext->Document(),
++ getter_AddRefs(firstPartyURI));
++
+ return il->LoadImage(realURI, /* icon URI */
+- nullptr, /* initial document URI; this is only
++ firstPartyURI, /* initial document URI; this is only
+ relevant for cookies, so does not
+ apply to icons. */
+ nullptr, /* referrer (not relevant for icons) */
+diff --git a/netwerk/cookie/nsICookiePermission.idl b/netwerk/cookie/nsICookiePermission.idl
+index 379695c..7ad3f3b 100644
+--- a/netwerk/cookie/nsICookiePermission.idl
++++ b/netwerk/cookie/nsICookiePermission.idl
+@@ -7,6 +7,7 @@
+ interface nsICookie2;
+ interface nsIURI;
+ interface nsIChannel;
++interface nsIDocument;
+
+ typedef long nsCookieAccess;
+
+diff --git a/toolkit/system/gnome/nsAlertsIconListener.cpp b/toolkit/system/gnome/nsAlertsIconListener.cpp
+index bfc43d1..37e93c3 100644
+--- a/toolkit/system/gnome/nsAlertsIconListener.cpp
++++ b/toolkit/system/gnome/nsAlertsIconListener.cpp
+@@ -261,7 +261,8 @@ nsAlertsIconListener::StartRequest(const nsAString & aImageUrl)
+ if (!il)
+ return ShowAlert(NULL);
+
+- return il->LoadImage(imageUri, nullptr, nullptr, nullptr, nullptr, this,
++ // XXX: Hrmm.... Bypass cache, or isolate to imageUrl?
++ return il->LoadImage(imageUri, imageUri, nullptr, nullptr, nullptr, this,
+ nullptr, nsIRequest::LOAD_NORMAL, nullptr, nullptr,
+ nullptr, getter_AddRefs(mIconRequest));
+ }
+diff --git a/widget/cocoa/nsMenuItemIconX.mm b/widget/cocoa/nsMenuItemIconX.mm
+index e0c07c4..368df5f 100644
+--- a/widget/cocoa/nsMenuItemIconX.mm
++++ b/widget/cocoa/nsMenuItemIconX.mm
+@@ -29,6 +29,7 @@
+ #include "gfxImageSurface.h"
+ #include "imgIContainer.h"
+ #include "nsCocoaUtils.h"
++#include "mozIThirdPartyUtil.h"
+
+ static const uint32_t kIconWidth = 16;
+ static const uint32_t kIconHeight = 16;
+@@ -304,9 +305,15 @@ nsMenuItemIconX::LoadIcon(nsIURI* aIconURI)
+ [mNativeMenuItem setImage:sPlaceholderIconImage];
+ }
+
++ nsCOMPtr<nsIURI> firstPartyURI;
++ nsCOMPtr<mozIThirdPartyUtil> thirdPartySvc
++ = do_GetService(THIRDPARTYUTIL_CONTRACTID);
++ thirdPartySvc->GetFirstPartyURI(nullptr, document,
++ getter_AddRefs(firstPartyURI));
++
+ // Passing in null for channelPolicy here since nsMenuItemIconX::LoadIcon is
+ // not exposed to web content
+- rv = loader->LoadImage(aIconURI, nullptr, nullptr, nullptr, loadGroup, this,
++ rv = loader->LoadImage(aIconURI, firstPartyURI, nullptr, nullptr, loadGroup, this,
+ nullptr, nsIRequest::LOAD_NORMAL, nullptr, nullptr,
+ nullptr, getter_AddRefs(mIconRequest));
+ if (NS_FAILED(rv)) return rv;
+--
+1.7.5.4
+
diff --git a/src/current-patches/firefox/0025-nsIHTTPChannel.redirectTo-API.patch b/src/current-patches/firefox/0025-nsIHTTPChannel.redirectTo-API.patch
new file mode 100644
index 0000000..1d81164
--- /dev/null
+++ b/src/current-patches/firefox/0025-nsIHTTPChannel.redirectTo-API.patch
@@ -0,0 +1,474 @@
+From 87461432d5e55eee144ed18e8551b637f7919950 Mon Sep 17 00:00:00 2001
+From: Mike Perry <mikeperry-git at torproject.org>
+Date: Mon, 14 Jan 2013 19:36:14 -0800
+Subject: [PATCH 25/26] nsIHTTPChannel.redirectTo API.
+
+Provides an API for HTTPS-Everywhere to perform redirects to https
+in a more secure and reliable way.
+---
+ netwerk/protocol/http/HttpBaseChannel.cpp | 13 +++++
+ netwerk/protocol/http/HttpBaseChannel.h | 10 ++++
+ netwerk/protocol/http/HttpChannelChild.cpp | 34 ++++++++----
+ netwerk/protocol/http/HttpChannelParent.cpp | 12 ++++-
+ netwerk/protocol/http/HttpChannelParent.h | 4 +-
+ netwerk/protocol/http/PHttpChannel.ipdl | 4 +-
+ netwerk/protocol/http/nsHttpChannel.cpp | 57 ++++++++++++++++---
+ netwerk/protocol/http/nsHttpChannel.h | 8 ++-
+ netwerk/protocol/http/nsIHttpChannel.idl | 14 +++++-
+ .../protocol/viewsource/nsViewSourceChannel.cpp | 10 +++-
+ 10 files changed, 139 insertions(+), 27 deletions(-)
+
+diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp
+index ec58de6..2926428 100644
+--- a/netwerk/protocol/http/HttpBaseChannel.cpp
++++ b/netwerk/protocol/http/HttpBaseChannel.cpp
+@@ -37,6 +37,7 @@ HttpBaseChannel::HttpBaseChannel()
+ , mIsPending(false)
+ , mWasOpened(false)
+ , mResponseHeadersModified(false)
++ , mRequestObserversCalled(false)
+ , mAllowPipelining(true)
+ , mForceAllowThirdPartyCookie(false)
+ , mUploadStreamHasHeaders(false)
+@@ -1119,6 +1120,18 @@ HttpBaseChannel::GetRequestSucceeded(bool *aValue)
+ return NS_OK;
+ }
+
++NS_IMETHODIMP
++HttpBaseChannel::RedirectTo(nsIURI *newURI)
++{
++ // We can only redirect unopened channels
++ ENSURE_CALLED_BEFORE_ASYNC_OPEN();
++
++ // The redirect is stored internally for use in AsyncOpen
++ mAPIRedirectToURI = newURI;
++
++ return NS_OK;
++}
++
+ //-----------------------------------------------------------------------------
+ // HttpBaseChannel::nsIHttpChannelInternal
+ //-----------------------------------------------------------------------------
+diff --git a/netwerk/protocol/http/HttpBaseChannel.h b/netwerk/protocol/http/HttpBaseChannel.h
+index 971958c..125734d 100644
+--- a/netwerk/protocol/http/HttpBaseChannel.h
++++ b/netwerk/protocol/http/HttpBaseChannel.h
+@@ -17,6 +17,7 @@
+ #include "nsHttpConnectionInfo.h"
+ #include "nsIEncodedChannel.h"
+ #include "nsIHttpChannel.h"
++#include "nsHttpHandler.h"
+ #include "nsIHttpChannelInternal.h"
+ #include "nsIUploadChannel.h"
+ #include "nsIUploadChannel2.h"
+@@ -117,6 +118,7 @@ public:
+ NS_IMETHOD GetResponseStatus(uint32_t *aValue);
+ NS_IMETHOD GetResponseStatusText(nsACString& aValue);
+ NS_IMETHOD GetRequestSucceeded(bool *aValue);
++ NS_IMETHOD RedirectTo(nsIURI *newURI);
+
+ // nsIHttpChannelInternal
+ NS_IMETHOD GetDocumentURI(nsIURI **aDocumentURI);
+@@ -199,6 +201,12 @@ protected:
+ nsIChannel *,
+ bool preserveMethod);
+
++ // bundle calling OMR observers and marking flag into one function
++ inline void CallOnModifyRequestObservers() {
++ gHttpHandler->OnModifyRequest(this);
++ mRequestObserversCalled = true;
++ }
++
+ // Helper function to simplify getting notification callbacks.
+ template <class T>
+ void GetCallback(nsCOMPtr<T> &aResult)
+@@ -252,6 +260,7 @@ protected:
+ uint32_t mIsPending : 1;
+ uint32_t mWasOpened : 1;
+ uint32_t mResponseHeadersModified : 1;
++ uint32_t mRequestObserversCalled : 1;
+ uint32_t mAllowPipelining : 1;
+ uint32_t mForceAllowThirdPartyCookie : 1;
+ uint32_t mUploadStreamHasHeaders : 1;
+@@ -268,6 +277,7 @@ protected:
+ // Current suspension depth for this channel object
+ uint32_t mSuspendCount;
+
++ nsCOMPtr<nsIURI> mAPIRedirectToURI;
+ nsAutoPtr<nsTArray<nsCString> > mRedirectedCachekeys;
+ };
+
+diff --git a/netwerk/protocol/http/HttpChannelChild.cpp b/netwerk/protocol/http/HttpChannelChild.cpp
+index 5d82f7e..35697be 100644
+--- a/netwerk/protocol/http/HttpChannelChild.cpp
++++ b/netwerk/protocol/http/HttpChannelChild.cpp
+@@ -854,6 +854,7 @@ HttpChannelChild::CompleteRedirectSetup(nsIStreamListener *listener,
+ NS_IMETHODIMP
+ HttpChannelChild::OnRedirectVerifyCallback(nsresult result)
+ {
++ OptionalURIParams redirectURI;
+ nsCOMPtr<nsIHttpChannel> newHttpChannel =
+ do_QueryInterface(mRedirectChannelChild);
+
+@@ -872,13 +873,25 @@ HttpChannelChild::OnRedirectVerifyCallback(nsresult result)
+ newHttpChannelChild->GetClientSetRequestHeaders(&headerTuples);
+ }
+
+- // After we verify redirect, nsHttpChannel may hit the network: must give
+- // "http-on-modify-request" observers the chance to cancel before that.
+- if (NS_SUCCEEDED(result))
+- gHttpHandler->OnModifyRequest(newHttpChannel);
+-
+- if (mIPCOpen)
+- SendRedirect2Verify(result, *headerTuples);
++ if (NS_SUCCEEDED(result)) {
++ // we know this is an HttpChannelChild
++ HttpChannelChild* base =
++ static_cast<HttpChannelChild*>(mRedirectChannelChild.get());
++ // After we verify redirect, nsHttpChannel may hit the network: must give
++ // "http-on-modify-request" observers the chance to cancel before that.
++ base->CallOnModifyRequestObservers();
++
++ /* If there was an API redirect of this redirect, we need to send it
++ * down here, since it can't get sent via SendAsyncOpen. */
++ SerializeURI(base->mAPIRedirectToURI, redirectURI);
++ } else {
++ /* If the redirect was canceled, bypass OMR and send an empty API
++ * redirect URI */
++ SerializeURI(nullptr, redirectURI);
++ }
++
++ if (mIPCOpen)
++ SendRedirect2Verify(result, *headerTuples, redirectURI);
+
+ return NS_OK;
+ }
+@@ -985,7 +998,7 @@ HttpChannelChild::AsyncOpen(nsIStreamListener *listener, nsISupports *aContext)
+ //
+
+ // notify "http-on-modify-request" observers
+- gHttpHandler->OnModifyRequest(this);
++ CallOnModifyRequestObservers();
+
+ mIsPending = true;
+ mWasOpened = true;
+@@ -1042,15 +1055,16 @@ HttpChannelChild::AsyncOpen(nsIStreamListener *listener, nsISupports *aContext)
+ URIParams uri;
+ SerializeURI(mURI, uri);
+
+- OptionalURIParams originalURI, documentURI, referrer;
++ OptionalURIParams originalURI, documentURI, referrer, redirectURI;
+ SerializeURI(mOriginalURI, originalURI);
+ SerializeURI(mDocumentURI, documentURI);
+ SerializeURI(mReferrer, referrer);
++ SerializeURI(mAPIRedirectToURI, redirectURI);
+
+ OptionalInputStreamParams uploadStream;
+ SerializeInputStream(mUploadStream, uploadStream);
+
+- SendAsyncOpen(uri, originalURI, documentURI, referrer, mLoadFlags,
++ SendAsyncOpen(uri, originalURI, documentURI, referrer, redirectURI, mLoadFlags,
+ mClientSetRequestHeaders, mRequestHead.Method(), uploadStream,
+ mUploadStreamHasHeaders, mPriority, mRedirectionLimit,
+ mAllowPipelining, mForceAllowThirdPartyCookie, mSendResumeAt,
+diff --git a/netwerk/protocol/http/HttpChannelParent.cpp b/netwerk/protocol/http/HttpChannelParent.cpp
+index 0a9ccc4..d01f162 100644
+--- a/netwerk/protocol/http/HttpChannelParent.cpp
++++ b/netwerk/protocol/http/HttpChannelParent.cpp
+@@ -110,6 +110,7 @@ HttpChannelParent::RecvAsyncOpen(const URIParams& aURI,
+ const OptionalURIParams& aOriginalURI,
+ const OptionalURIParams& aDocURI,
+ const OptionalURIParams& aReferrerURI,
++ const OptionalURIParams& aAPIRedirectToURI,
+ const uint32_t& loadFlags,
+ const RequestHeaderTuples& requestHeaders,
+ const nsHttpAtom& requestMethod,
+@@ -131,6 +132,7 @@ HttpChannelParent::RecvAsyncOpen(const URIParams& aURI,
+ nsCOMPtr<nsIURI> originalUri = DeserializeURI(aOriginalURI);
+ nsCOMPtr<nsIURI> docUri = DeserializeURI(aDocURI);
+ nsCOMPtr<nsIURI> referrerUri = DeserializeURI(aReferrerURI);
++ nsCOMPtr<nsIURI> apiRedirectToUri = DeserializeURI(aAPIRedirectToURI);
+
+ nsCString uriSpec;
+ uri->GetSpec(uriSpec);
+@@ -161,6 +163,8 @@ HttpChannelParent::RecvAsyncOpen(const URIParams& aURI,
+ httpChan->SetDocumentURI(docUri);
+ if (referrerUri)
+ httpChan->SetReferrerInternal(referrerUri);
++ if (apiRedirectToUri)
++ httpChan->RedirectTo(apiRedirectToUri);
+ if (loadFlags != nsIRequest::LOAD_NORMAL)
+ httpChan->SetLoadFlags(loadFlags);
+
+@@ -315,13 +319,19 @@ HttpChannelParent::RecvUpdateAssociatedContentSecurity(const int32_t& high,
+
+ bool
+ HttpChannelParent::RecvRedirect2Verify(const nsresult& result,
+- const RequestHeaderTuples& changedHeaders)
++ const RequestHeaderTuples& changedHeaders,
++ const OptionalURIParams& aAPIRedirectURI)
+ {
+ if (NS_SUCCEEDED(result)) {
+ nsCOMPtr<nsIHttpChannel> newHttpChannel =
+ do_QueryInterface(mRedirectChannel);
+
+ if (newHttpChannel) {
++ nsCOMPtr<nsIURI> apiRedirectUri = DeserializeURI(aAPIRedirectURI);
++
++ if (apiRedirectUri)
++ newHttpChannel->RedirectTo(apiRedirectUri);
++
+ for (uint32_t i = 0; i < changedHeaders.Length(); i++) {
+ newHttpChannel->SetRequestHeader(changedHeaders[i].mHeader,
+ changedHeaders[i].mValue,
+diff --git a/netwerk/protocol/http/HttpChannelParent.h b/netwerk/protocol/http/HttpChannelParent.h
+index e869d63..96f3f3c 100644
+--- a/netwerk/protocol/http/HttpChannelParent.h
++++ b/netwerk/protocol/http/HttpChannelParent.h
+@@ -47,6 +47,7 @@ protected:
+ const OptionalURIParams& originalUri,
+ const OptionalURIParams& docUri,
+ const OptionalURIParams& referrerUri,
++ const OptionalURIParams& internalRedirectUri,
+ const uint32_t& loadFlags,
+ const RequestHeaderTuples& requestHeaders,
+ const nsHttpAtom& requestMethod,
+@@ -71,7 +72,8 @@ protected:
+ virtual bool RecvResume();
+ virtual bool RecvCancel(const nsresult& status);
+ virtual bool RecvRedirect2Verify(const nsresult& result,
+- const RequestHeaderTuples& changedHeaders);
++ const RequestHeaderTuples& changedHeaders,
++ const OptionalURIParams& apiRedirectUri);
+ virtual bool RecvUpdateAssociatedContentSecurity(const int32_t& high,
+ const int32_t& low,
+ const int32_t& broken,
+diff --git a/netwerk/protocol/http/PHttpChannel.ipdl b/netwerk/protocol/http/PHttpChannel.ipdl
+index c13c969..e16afd6 100644
+--- a/netwerk/protocol/http/PHttpChannel.ipdl
++++ b/netwerk/protocol/http/PHttpChannel.ipdl
+@@ -37,6 +37,7 @@ parent:
+ OptionalURIParams original,
+ OptionalURIParams doc,
+ OptionalURIParams referrer,
++ OptionalURIParams apiRedirectTo,
+ uint32_t loadFlags,
+ RequestHeaderTuples requestHeaders,
+ nsHttpAtom requestMethod,
+@@ -72,7 +73,8 @@ parent:
+ Cancel(nsresult status);
+
+ // Reports approval/veto of redirect by child process redirect observers
+- Redirect2Verify(nsresult result, RequestHeaderTuples changedHeaders);
++ Redirect2Verify(nsresult result, RequestHeaderTuples changedHeaders,
++ OptionalURIParams apiRedirectTo);
+
+ // For document loads we keep this protocol open after child's
+ // OnStopRequest, and send this msg (instead of __delete__) to allow
+diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp
+index 9223d08..6bf11a1 100644
+--- a/netwerk/protocol/http/nsHttpChannel.cpp
++++ b/netwerk/protocol/http/nsHttpChannel.cpp
+@@ -1580,18 +1580,17 @@ nsHttpChannel::HandleAsyncRedirectChannelToHttps()
+ return;
+ }
+
+- nsresult rv = AsyncRedirectChannelToHttps();
++ nsresult rv = StartRedirectChannelToHttps();
+ if (NS_FAILED(rv))
+- ContinueAsyncRedirectChannelToHttps(rv);
++ ContinueAsyncRedirectChannelToURI(rv);
+ }
+
+ nsresult
+-nsHttpChannel::AsyncRedirectChannelToHttps()
++nsHttpChannel::StartRedirectChannelToHttps()
+ {
+ nsresult rv = NS_OK;
+ LOG(("nsHttpChannel::HandleAsyncRedirectChannelToHttps() [STS]\n"));
+
+- nsCOMPtr<nsIChannel> newChannel;
+ nsCOMPtr<nsIURI> upgradedURI;
+
+ rv = mURI->Clone(getter_AddRefs(upgradedURI));
+@@ -1613,6 +1612,36 @@ nsHttpChannel::AsyncRedirectChannelToHttps()
+ else
+ upgradedURI->SetPort(oldPort);
+
++ return StartRedirectChannelToURI(upgradedURI);
++}
++
++void
++nsHttpChannel::HandleAsyncAPIRedirect()
++{
++ NS_PRECONDITION(!mCallOnResume, "How did that happen?");
++ NS_PRECONDITION(mAPIRedirectToURI, "How did that happen?");
++
++ if (mSuspendCount) {
++ LOG(("Waiting until resume to do async API redirect [this=%p]\n", this));
++ mCallOnResume = &nsHttpChannel::HandleAsyncAPIRedirect;
++ return;
++ }
++
++ nsresult rv = StartRedirectChannelToURI(mAPIRedirectToURI);
++ if (NS_FAILED(rv))
++ ContinueAsyncRedirectChannelToURI(rv);
++
++ return;
++}
++
++nsresult
++nsHttpChannel::StartRedirectChannelToURI(nsIURI *upgradedURI)
++{
++ nsresult rv = NS_OK;
++ LOG(("nsHttpChannel::StartRedirectChannelToURI()\n"));
++
++ nsCOMPtr<nsIChannel> newChannel;
++
+ nsCOMPtr<nsIIOService> ioService;
+ rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
+ NS_ENSURE_SUCCESS(rv, rv);
+@@ -1628,7 +1657,7 @@ nsHttpChannel::AsyncRedirectChannelToHttps()
+ uint32_t flags = nsIChannelEventSink::REDIRECT_PERMANENT;
+
+ PushRedirectAsyncFunc(
+- &nsHttpChannel::ContinueAsyncRedirectChannelToHttps);
++ &nsHttpChannel::ContinueAsyncRedirectChannelToURI);
+ rv = gHttpHandler->AsyncOnChannelRedirect(this, newChannel, flags);
+
+ if (NS_SUCCEEDED(rv))
+@@ -1636,15 +1665,19 @@ nsHttpChannel::AsyncRedirectChannelToHttps()
+
+ if (NS_FAILED(rv)) {
+ AutoRedirectVetoNotifier notifier(this);
++
++ /* Remove the async call to ContinueAsyncRedirectChannelToURI().
++ * It is called directly by our callers upon return (to clean up
++ * the failed redirect). */
+ PopRedirectAsyncFunc(
+- &nsHttpChannel::ContinueAsyncRedirectChannelToHttps);
++ &nsHttpChannel::ContinueAsyncRedirectChannelToURI);
+ }
+
+ return rv;
+ }
+
+ nsresult
+-nsHttpChannel::ContinueAsyncRedirectChannelToHttps(nsresult rv)
++nsHttpChannel::ContinueAsyncRedirectChannelToURI(nsresult rv)
+ {
+ AutoRedirectVetoNotifier notifier(this);
+
+@@ -4374,7 +4407,7 @@ nsHttpChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *context)
+ mAuthProvider->AddAuthorizationHeaders();
+
+ // notify "http-on-modify-request" observers
+- gHttpHandler->OnModifyRequest(this);
++ CallOnModifyRequestObservers();
+
+ // Adjust mCaps according to our request headers:
+ // - If "Connection: close" is set as a request header, then do not bother
+@@ -4401,6 +4434,12 @@ nsHttpChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *context)
+ if (mLoadGroup)
+ mLoadGroup->AddRequest(this, nullptr);
+
++ // Check to see if we should redirect this channel elsewhere by
++ // nsIHttpChannel.redirectTo API request
++ if (mAPIRedirectToURI) {
++ return AsyncCall(&nsHttpChannel::HandleAsyncAPIRedirect);
++ }
++
+ // Collect mAsyncOpenTime after we have called all obsrevers like
+ // "http-on-modify-request" and load group observers that may set
+ // mTimingEnabled flag.
+@@ -5531,7 +5570,7 @@ nsHttpChannel::DoAuthRetry(nsAHttpConnection *conn)
+ AddCookiesToRequest();
+
+ // notify "http-on-modify-request" observers
+- gHttpHandler->OnModifyRequest(this);
++ CallOnModifyRequestObservers();
+
+ mIsPending = true;
+
+diff --git a/netwerk/protocol/http/nsHttpChannel.h b/netwerk/protocol/http/nsHttpChannel.h
+index 5b4ddb9..1c0c6b7 100644
+--- a/netwerk/protocol/http/nsHttpChannel.h
++++ b/netwerk/protocol/http/nsHttpChannel.h
+@@ -174,12 +174,14 @@ private:
+
+ // redirection specific methods
+ void HandleAsyncRedirect();
++ void HandleAsyncAPIRedirect();
+ nsresult ContinueHandleAsyncRedirect(nsresult);
+ void HandleAsyncNotModified();
+ void HandleAsyncFallback();
+ nsresult ContinueHandleAsyncFallback(nsresult);
+ nsresult PromptTempRedirect();
+- virtual nsresult SetupReplacementChannel(nsIURI *, nsIChannel *, bool preserveMethod);
++ nsresult StartRedirectChannelToURI(nsIURI *);
++ virtual nsresult SetupReplacementChannel(nsIURI *, nsIChannel *, bool preserveMethod);
+
+ // proxy specific methods
+ nsresult ProxyFailover();
+@@ -236,8 +238,8 @@ private:
+ nsresult DoAuthRetry(nsAHttpConnection *);
+
+ void HandleAsyncRedirectChannelToHttps();
+- nsresult AsyncRedirectChannelToHttps();
+- nsresult ContinueAsyncRedirectChannelToHttps(nsresult rv);
++ nsresult StartRedirectChannelToHttps();
++ nsresult ContinueAsyncRedirectChannelToURI(nsresult rv);
+
+ /**
+ * A function that takes care of reading STS headers and enforcing STS
+diff --git a/netwerk/protocol/http/nsIHttpChannel.idl b/netwerk/protocol/http/nsIHttpChannel.idl
+index c541df1..7037f95 100644
+--- a/netwerk/protocol/http/nsIHttpChannel.idl
++++ b/netwerk/protocol/http/nsIHttpChannel.idl
+@@ -14,7 +14,7 @@ interface nsIHttpHeaderVisitor;
+ * the inspection of the resulting HTTP response status and headers when they
+ * become available.
+ */
+-[scriptable, uuid(9277fe09-f0cc-4cd9-bbce-581dd94b0260)]
++[scriptable, uuid(a01362a0-5c45-11e2-bcfd-0800200c9a66)]
+ interface nsIHttpChannel : nsIChannel
+ {
+ /**************************************************************************
+@@ -257,4 +257,16 @@ interface nsIHttpChannel : nsIChannel
+ * has been received (before onStartRequest).
+ */
+ boolean isNoCacheResponse();
++
++ /**
++ * Instructs the channel to immediately redirect to a new destination.
++ * Can only be called on channels not yet opened.
++ *
++ * This method provides no explicit conflict resolution. The last
++ * caller to call it wins.
++ *
++ * @throws NS_ERROR_ALREADY_OPENED if called after the channel
++ * has been opened.
++ */
++ void redirectTo(in nsIURI aNewURI);
+ };
+diff --git a/netwerk/protocol/viewsource/nsViewSourceChannel.cpp b/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
+index 643ed0e..c63c2a5 100644
+--- a/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
++++ b/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
+@@ -671,4 +671,12 @@ nsViewSourceChannel::IsNoCacheResponse(bool *_retval)
+ {
+ return !mHttpChannel ? NS_ERROR_NULL_POINTER :
+ mHttpChannel->IsNoCacheResponse(_retval);
+-}
++}
++
++NS_IMETHODIMP
++nsViewSourceChannel::RedirectTo(nsIURI *uri)
++{
++ return !mHttpChannel ? NS_ERROR_NULL_POINTER :
++ mHttpChannel->RedirectTo(uri);
++}
++
+--
+1.7.5.4
+
diff --git a/src/current-patches/firefox/0026-Isolate-DOM-storage-to-first-party-URI.patch b/src/current-patches/firefox/0026-Isolate-DOM-storage-to-first-party-URI.patch
new file mode 100644
index 0000000..89f4ed6
--- /dev/null
+++ b/src/current-patches/firefox/0026-Isolate-DOM-storage-to-first-party-URI.patch
@@ -0,0 +1,776 @@
+From 69a8f50fc6d4881e48f29ef783e6246d6b7fbee4 Mon Sep 17 00:00:00 2001
+From: Kathleen Brade <brade at pearlcrescent.com>
+Date: Tue, 15 Jan 2013 14:18:43 -0800
+Subject: [PATCH 26/26] Isolate DOM storage to first party URI
+
+Also prevents DOM storage from writing to disk (hardcoded).
+---
+ docshell/base/nsDocShell.cpp | 78 ++++++++++++++++++-
+ docshell/base/nsDocShell.h | 6 +-
+ docshell/base/nsIDocShell.idl | 33 ++++++++-
+ dom/base/nsGlobalWindow.cpp | 13 +++-
+ dom/interfaces/storage/nsIDOMStorageManager.idl | 11 +++-
+ dom/interfaces/storage/nsPIDOMStorage.h | 8 +-
+ dom/src/storage/StorageChild.cpp | 6 +-
+ dom/src/storage/StorageChild.h | 3 +-
+ dom/src/storage/nsDOMStorage.cpp | 44 ++++++++---
+ dom/src/storage/nsDOMStorage.h | 14 +++-
+ dom/src/storage/nsDOMStorageDBWrapper.cpp | 41 ++++++++---
+ dom/src/storage/nsDOMStorageDBWrapper.h | 14 ++-
+ dom/src/storage/nsDOMStorageMemoryDB.cpp | 21 +++++-
+ dom/src/storage/nsDOMStoragePersistentDB.cpp | 8 ++-
+ .../windowwatcher/src/nsWindowWatcher.cpp | 5 +-
+ 15 files changed, 255 insertions(+), 50 deletions(-)
+
+diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
+index 7a141d9..84a0043 100644
+--- a/docshell/base/nsDocShell.cpp
++++ b/docshell/base/nsDocShell.cpp
+@@ -184,6 +184,7 @@
+ #include "nsIChannelPolicy.h"
+ #include "nsIContentSecurityPolicy.h"
+ #include "nsSandboxFlags.h"
++#include "mozIThirdPartyUtil.h"
+
+ #include "nsXULAppAPI.h"
+
+@@ -2395,6 +2396,17 @@ nsDocShell::GetSessionStorageForPrincipal(nsIPrincipal* aPrincipal,
+ bool aCreate,
+ nsIDOMStorage** aStorage)
+ {
++ return GetSessionStorageForFirstParty(nullptr, aPrincipal, aDocumentURI,
++ aCreate, aStorage);
++}
++
++NS_IMETHODIMP
++nsDocShell::GetSessionStorageForFirstParty(nsIURI *aFirstPartyURI,
++ nsIPrincipal* aPrincipal,
++ const nsAString& aDocumentURI,
++ bool aCreate,
++ nsIDOMStorage** aStorage)
++{
+ NS_ENSURE_ARG_POINTER(aStorage);
+ *aStorage = nullptr;
+
+@@ -2426,7 +2438,11 @@ nsDocShell::GetSessionStorageForPrincipal(nsIPrincipal* aPrincipal,
+ if (origin.IsEmpty())
+ return NS_OK;
+
+- if (!mStorages.Get(origin, aStorage) && aCreate) {
++ nsXPIDLCString key;
++ rv = GetSessionStorageKey(aFirstPartyURI, origin, key);
++ NS_ENSURE_SUCCESS(rv, rv);
++
++ if (!mStorages.Get(key, aStorage) && aCreate) {
+ nsCOMPtr<nsIDOMStorage> newstorage =
+ do_CreateInstance("@mozilla.org/dom/storage;2");
+ if (!newstorage)
+@@ -2440,7 +2456,7 @@ nsDocShell::GetSessionStorageForPrincipal(nsIPrincipal* aPrincipal,
+ if (NS_FAILED(rv))
+ return rv;
+
+- mStorages.Put(origin, newstorage);
++ mStorages.Put(key, newstorage);
+
+ newstorage.swap(*aStorage);
+ #if defined(PR_LOGGING) && defined(DEBUG)
+@@ -2454,7 +2470,7 @@ nsDocShell::GetSessionStorageForPrincipal(nsIPrincipal* aPrincipal,
+ if (piStorage) {
+ nsCOMPtr<nsIPrincipal> storagePrincipal = piStorage->Principal();
+
+- // The origin string used to map items in the hash table is
++ // The key string used to map items in the hash table is
+ // an implicit security check. That check is double-confirmed
+ // by checking the principal a storage was demanded for
+ // really is the principal for which that storage was originally
+@@ -2513,6 +2529,14 @@ nsresult
+ nsDocShell::AddSessionStorage(nsIPrincipal* aPrincipal,
+ nsIDOMStorage* aStorage)
+ {
++ return AddSessionStorageForFirstParty(nullptr, aPrincipal, aStorage);
++}
++
++nsresult
++nsDocShell::AddSessionStorageForFirstParty(nsIURI* aFirstPartyURI,
++ nsIPrincipal* aPrincipal,
++ nsIDOMStorage* aStorage)
++{
+ NS_ENSURE_ARG_POINTER(aStorage);
+
+ if (!aPrincipal)
+@@ -2534,8 +2558,12 @@ nsDocShell::AddSessionStorage(nsIPrincipal* aPrincipal,
+ if (origin.IsEmpty())
+ return NS_ERROR_FAILURE;
+
++ nsXPIDLCString key;
++ rv = GetSessionStorageKey(aFirstPartyURI, origin, key);
++ NS_ENSURE_SUCCESS(rv, rv);
++
+ // Do not replace an existing session storage.
+- if (mStorages.GetWeak(origin))
++ if (mStorages.GetWeak(key))
+ return NS_ERROR_NOT_AVAILABLE;
+
+ #if defined(PR_LOGGING) && defined(DEBUG)
+@@ -2543,7 +2571,7 @@ nsDocShell::AddSessionStorage(nsIPrincipal* aPrincipal,
+ ("nsDocShell[%p]: was added a sessionStorage %p",
+ this, aStorage));
+ #endif
+- mStorages.Put(origin, aStorage);
++ mStorages.Put(key, aStorage);
+ }
+ else {
+ return topDocShell->AddSessionStorage(aPrincipal, aStorage);
+@@ -2568,6 +2596,10 @@ CloneSessionStorages(nsCStringHashKey::KeyType aKey, nsIDOMStorage* aStorage,
+ return PL_DHASH_NEXT;
+ }
+
++// CloneSessionStoragesTo() copies all session storage data from aDocShell to
++// this doc shell. It does not check if that is an appropriate thing to do,
++// e.g., by verifying that the first party URIs are the same. For now that is
++// okay because no Firefox code uses this method.
+ NS_IMETHODIMP
+ nsDocShell::CloneSessionStoragesTo(nsIDocShell* aDocShell)
+ {
+@@ -12389,3 +12421,39 @@ nsDocShell::GetAsyncPanZoomEnabled(bool* aOut)
+ *aOut = false;
+ return NS_OK;
+ }
++
++nsresult
++nsDocShell::GetSessionStorageKey(nsIURI *aFirstPartyURI,
++ nsXPIDLCString& aOrigin,
++ nsXPIDLCString& aResult)
++{
++ aResult.Truncate();
++
++ if (!aOrigin)
++ return NS_ERROR_FAILURE;
++
++ aResult.Append(aOrigin);
++
++ nsCOMPtr<nsIURI> firstPartyURI = aFirstPartyURI;
++ if (!firstPartyURI) {
++ nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
++ do_GetService(THIRDPARTYUTIL_CONTRACTID);
++ if (!thirdPartyUtil)
++ return NS_ERROR_FAILURE;
++
++ nsCOMPtr<nsIDocument> doc(do_GetInterface(GetAsSupports(this)));
++ nsresult rv = thirdPartyUtil->GetFirstPartyURI(nullptr, doc,
++ getter_AddRefs(firstPartyURI));
++ NS_ENSURE_SUCCESS(rv, rv);
++ }
++
++ nsCAutoString host;
++ nsresult rv = firstPartyURI->GetHost(host);
++ if (NS_SUCCEEDED(rv) && (host.Length() > 0)) {
++ aResult.AppendLiteral("&");
++ aResult.Append(host);
++ }
++
++ return NS_OK;
++}
++
+diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
+index 225a636..aeb00c9 100644
+--- a/docshell/base/nsDocShell.h
++++ b/docshell/base/nsDocShell.h
+@@ -679,7 +679,7 @@ protected:
+ FrameType GetInheritedFrameType();
+ FrameType GetFrameType();
+
+- // hash of session storages, keyed by domain
++ // hash of session storages, keyed by domain&firstPartyHost
+ nsInterfaceHashtable<nsCStringHashKey, nsIDOMStorage> mStorages;
+
+ // Dimensions of the docshell
+@@ -846,6 +846,10 @@ private:
+ static unsigned long gNumberOfDocShells;
+ #endif /* DEBUG */
+
++ nsresult GetSessionStorageKey(nsIURI *aFirstPartyURI,
++ nsXPIDLCString& aOrigin,
++ nsXPIDLCString& aResult);
++
+ public:
+ class InterfaceRequestorProxy : public nsIInterfaceRequestor {
+ public:
+diff --git a/docshell/base/nsIDocShell.idl b/docshell/base/nsIDocShell.idl
+index 986f4b4..4f26a04 100644
+--- a/docshell/base/nsIDocShell.idl
++++ b/docshell/base/nsIDocShell.idl
+@@ -39,7 +39,7 @@ interface nsIWebBrowserPrint;
+ interface nsIVariant;
+ interface nsIPrivacyTransitionObserver;
+
+-[scriptable, builtinclass, uuid(9b283337-097d-4fa8-a2da-916318eaf828)]
++[scriptable, builtinclass, uuid(5289f25a-1175-4b01-bc56-b1628ef097b9)]
+ interface nsIDocShell : nsISupports
+ {
+ /**
+@@ -416,6 +416,24 @@ interface nsIDocShell : nsISupports
+ in boolean create);
+
+ /*
++ * A variant of getSessionStorageForPrincipal that is used when cloning
++ * session storage during creation of new windows/tabs (the first party URI
++ * of the new window/tab must be used to generate the key that is used to
++ * access the session data).
++ *
++ * @param firstPartyURI the URL bar URI
++ * @param principal returns a storage for this principal
++ * @param documentURI new storage will be created with reference to this
++ * document.documentURI that will appear in storage event
++ * @param create If true and a session storage object doesn't
++ * already exist, a new one will be created.
++ */
++ nsIDOMStorage getSessionStorageForFirstParty(in nsIURI firstPartyURI,
++ in nsIPrincipal principal,
++ in DOMString documentURI,
++ in boolean create);
++
++ /*
+ * Add a WebApps session storage object to the docshell.
+ *
+ * @param principal the principal the storage object is associated with
+@@ -423,6 +441,19 @@ interface nsIDocShell : nsISupports
+ */
+ void addSessionStorage(in nsIPrincipal principal, in nsIDOMStorage storage);
+
++ /*
++ * A variant of addSessionStorage that is used when cloning session storage
++ * during creation of new windows/tabs (the cloning must occur before the
++ * document load begins).
++ *
++ * @param firstPartyURI the URL bar URI
++ * @param principal the principal the storage object is associated with
++ * @param storage the storage object to add
++ */
++ void addSessionStorageForFirstParty(in nsIURI firstPartyURI,
++ in nsIPrincipal principal,
++ in nsIDOMStorage storage);
++
+ /**
+ * Clones all session storage objects and attaches them to the given docshell.
+ * Useful when duplicating tabs and their states.
+diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp
+index 3a370c9..201a0a2 100644
+--- a/dom/base/nsGlobalWindow.cpp
++++ b/dom/base/nsGlobalWindow.cpp
+@@ -8382,7 +8382,18 @@ nsGlobalWindow::GetLocalStorage(nsIDOMStorage ** aLocalStorage)
+ nsIDocShell* docShell = GetDocShell();
+ nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
+
+- rv = storageManager->GetLocalStorageForPrincipal(principal,
++ nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
++ do_GetService(THIRDPARTYUTIL_CONTRACTID);
++ if (!thirdPartyUtil)
++ return NS_ERROR_FAILURE;
++
++ nsCOMPtr<nsIURI> firstPartyURI;
++ nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocument);
++ rv = thirdPartyUtil->GetFirstPartyURI(NULL, doc,
++ getter_AddRefs(firstPartyURI));
++ NS_ENSURE_SUCCESS(rv, rv);
++
++ rv = storageManager->GetLocalStorageForFirstParty(firstPartyURI, principal,
+ documentURI,
+ loadContext && loadContext->UsePrivateBrowsing(),
+ getter_AddRefs(mLocalStorage));
+diff --git a/dom/interfaces/storage/nsIDOMStorageManager.idl b/dom/interfaces/storage/nsIDOMStorageManager.idl
+index 94b8789..21bedf0 100644
+--- a/dom/interfaces/storage/nsIDOMStorageManager.idl
++++ b/dom/interfaces/storage/nsIDOMStorageManager.idl
+@@ -7,8 +7,9 @@
+
+ interface nsIDOMStorage;
+ interface nsIPrincipal;
++interface nsIURI;
+
+-[scriptable, uuid(1541da6c-a9fb-4a8f-af9d-4493c981491d)]
++[scriptable, uuid(682edebf-7bbe-4b4b-b5f8-752cacfb2afa)]
+ interface nsIDOMStorageManager : nsISupports
+ {
+ /**
+@@ -35,4 +36,12 @@ interface nsIDOMStorageManager : nsISupports
+ nsIDOMStorage getLocalStorageForPrincipal(in nsIPrincipal aPrincipal,
+ in DOMString aDocumentURI,
+ [optional] in bool aPrivate);
++
++ /**
++ * Returns instance of localStorage object.
++ */
++ nsIDOMStorage getLocalStorageForFirstParty(in nsIURI aFirstPartyURI,
++ in nsIPrincipal aPrincipal,
++ in DOMString aDocumentURI,
++ [optional] in bool aPrivate);
+ };
+diff --git a/dom/interfaces/storage/nsPIDOMStorage.h b/dom/interfaces/storage/nsPIDOMStorage.h
+index fabb5cc..9f8de6b 100644
+--- a/dom/interfaces/storage/nsPIDOMStorage.h
++++ b/dom/interfaces/storage/nsPIDOMStorage.h
+@@ -15,8 +15,8 @@ class nsIURI;
+ class nsIPrincipal;
+
+ #define NS_PIDOMSTORAGE_IID \
+-{ 0x86dfe3c4, 0x4286, 0x4648, \
+- { 0xb2, 0x09, 0x55, 0x27, 0x50, 0x59, 0x26, 0xac } }
++{ 0x0db5e488, 0x08f4, 0x4155, \
++ { 0x81, 0x9b, 0x2b, 0x5a, 0x44, 0xaa, 0xa2, 0x45 } }
+
+ class nsPIDOMStorage : public nsISupports
+ {
+@@ -31,7 +31,9 @@ public:
+
+ virtual nsresult InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI,
+ bool aPrivate) = 0;
+- virtual nsresult InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI,
++ virtual nsresult InitAsLocalStorage(nsIURI *aFirstPartyURI,
++ nsIPrincipal *aPrincipal,
++ const nsSubstring &aDocumentURI,
+ bool aPrivate) = 0;
+
+ virtual already_AddRefed<nsIDOMStorage> Clone() = 0;
+diff --git a/dom/src/storage/StorageChild.cpp b/dom/src/storage/StorageChild.cpp
+index 6754fde..5d24973 100644
+--- a/dom/src/storage/StorageChild.cpp
++++ b/dom/src/storage/StorageChild.cpp
+@@ -95,9 +95,11 @@ StorageChild::InitAsSessionStorage(nsIURI* aDomainURI, bool aPrivate)
+ }
+
+ void
+-StorageChild::InitAsLocalStorage(nsIURI* aDomainURI, bool aCanUseChromePersist, bool aPrivate)
++StorageChild::InitAsLocalStorage(nsIURI* aFirstPartyURI, nsIURI* aDomainURI,
++ bool aCanUseChromePersist, bool aPrivate)
+ {
+- DOMStorageBase::InitAsLocalStorage(aDomainURI, aCanUseChromePersist, aPrivate);
++ DOMStorageBase::InitAsLocalStorage(aFirstPartyURI, aDomainURI,
++ aCanUseChromePersist, aPrivate);
+ InitRemote();
+ }
+
+diff --git a/dom/src/storage/StorageChild.h b/dom/src/storage/StorageChild.h
+index 297f093..81ddabe 100644
+--- a/dom/src/storage/StorageChild.h
++++ b/dom/src/storage/StorageChild.h
+@@ -27,7 +27,8 @@ public:
+ StorageChild(nsDOMStorage* aOwner, StorageChild& aOther);
+
+ virtual void InitAsSessionStorage(nsIURI* aDomainURI, bool aPrivate);
+- virtual void InitAsLocalStorage(nsIURI* aDomainURI, bool aCanUseChromePersist, bool aPrivate);
++ virtual void InitAsLocalStorage(nsIURI* aFirstPartyURI, nsIURI* aDomainURI,
++ bool aCanUseChromePersist, bool aPrivate);
+
+ virtual bool CacheStoragePermissions();
+
+diff --git a/dom/src/storage/nsDOMStorage.cpp b/dom/src/storage/nsDOMStorage.cpp
+index 2dd0fbc..23e8739 100644
+--- a/dom/src/storage/nsDOMStorage.cpp
++++ b/dom/src/storage/nsDOMStorage.cpp
+@@ -496,6 +496,17 @@ nsDOMStorageManager::GetLocalStorageForPrincipal(nsIPrincipal *aPrincipal,
+ bool aPrivate,
+ nsIDOMStorage **aResult)
+ {
++ return GetLocalStorageForFirstParty(nullptr, aPrincipal, aDocumentURI,
++ aPrivate, aResult);
++}
++
++NS_IMETHODIMP
++nsDOMStorageManager::GetLocalStorageForFirstParty(nsIURI *aFirstPartyURI,
++ nsIPrincipal *aPrincipal,
++ const nsSubstring &aDocumentURI,
++ bool aPrivate,
++ nsIDOMStorage **aResult)
++{
+ NS_ENSURE_ARG_POINTER(aPrincipal);
+ *aResult = nullptr;
+
+@@ -505,7 +516,8 @@ nsDOMStorageManager::GetLocalStorageForPrincipal(nsIPrincipal *aPrincipal,
+ if (!storage)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+- rv = storage->InitAsLocalStorage(aPrincipal, aDocumentURI, aPrivate);
++ rv = storage->InitAsLocalStorage(aFirstPartyURI, aPrincipal, aDocumentURI,
++ aPrivate);
+ if (NS_FAILED(rv))
+ return rv;
+
+@@ -622,7 +634,8 @@ DOMStorageBase::InitAsSessionStorage(nsIURI* aDomainURI, bool aPrivate)
+ }
+
+ void
+-DOMStorageBase::InitAsLocalStorage(nsIURI* aDomainURI,
++DOMStorageBase::InitAsLocalStorage(nsIURI* aFirstPartyURI,
++ nsIURI* aDomainURI,
+ bool aCanUseChromePersist,
+ bool aPrivate)
+ {
+@@ -634,7 +647,8 @@ DOMStorageBase::InitAsLocalStorage(nsIURI* aDomainURI,
+ // mPrincipal in bug 455070. It is not even used for localStorage.
+ aDomainURI->GetAsciiHost(mDomain);
+
+- nsDOMStorageDBWrapper::CreateOriginScopeDBKey(aDomainURI, mScopeDBKey);
++ nsDOMStorageDBWrapper::CreateOriginScopeDBKey(aFirstPartyURI, aDomainURI,
++ mScopeDBKey);
+
+ // XXX Bug 357323, we have to solve the issue how to define
+ // origin for file URLs. In that case CreateOriginScopeDBKey
+@@ -642,9 +656,9 @@ DOMStorageBase::InitAsLocalStorage(nsIURI* aDomainURI,
+ // in that case because it produces broken entries w/o owner.
+ mUseDB = !mScopeDBKey.IsEmpty();
+
+- nsDOMStorageDBWrapper::CreateQuotaDomainDBKey(mDomain,
++ nsDOMStorageDBWrapper::CreateQuotaDomainDBKey(aFirstPartyURI, mDomain,
+ true, false, mQuotaDomainDBKey);
+- nsDOMStorageDBWrapper::CreateQuotaDomainDBKey(mDomain,
++ nsDOMStorageDBWrapper::CreateQuotaDomainDBKey(aFirstPartyURI, mDomain,
+ true, true, mQuotaETLDplus1DomainDBKey);
+ mCanUseChromePersist = aCanUseChromePersist;
+ mStorageType = nsPIDOMStorage::LocalStorage;
+@@ -763,11 +777,13 @@ DOMStorageImpl::InitAsSessionStorage(nsIURI* aDomainURI, bool aPrivate)
+ }
+
+ void
+-DOMStorageImpl::InitAsLocalStorage(nsIURI* aDomainURI,
++DOMStorageImpl::InitAsLocalStorage(nsIURI *aFirstPartyURI,
++ nsIURI* aDomainURI,
+ bool aCanUseChromePersist,
+ bool aPrivate)
+ {
+- DOMStorageBase::InitAsLocalStorage(aDomainURI, aCanUseChromePersist, aPrivate);
++ DOMStorageBase::InitAsLocalStorage(aFirstPartyURI, aDomainURI,
++ aCanUseChromePersist, aPrivate);
+ }
+
+ bool
+@@ -1352,7 +1368,9 @@ nsDOMStorage::InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &
+ }
+
+ nsresult
+-nsDOMStorage::InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI,
++nsDOMStorage::InitAsLocalStorage(nsIURI *aFirstPartyURI,
++ nsIPrincipal *aPrincipal,
++ const nsSubstring &aDocumentURI,
+ bool aPrivate)
+ {
+ nsCOMPtr<nsIURI> domainURI;
+@@ -1370,7 +1388,8 @@ nsDOMStorage::InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aD
+ canUseChromePersist = URICanUseChromePersist(URI);
+ }
+
+- mStorageImpl->InitAsLocalStorage(domainURI, canUseChromePersist, aPrivate);
++ mStorageImpl->InitAsLocalStorage(aFirstPartyURI, domainURI,
++ canUseChromePersist, aPrivate);
+ return NS_OK;
+ }
+
+@@ -1782,7 +1801,9 @@ nsDOMStorage2::InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring
+ }
+
+ nsresult
+-nsDOMStorage2::InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI,
++nsDOMStorage2::InitAsLocalStorage(nsIURI *aFirstPartyURI,
++ nsIPrincipal *aPrincipal,
++ const nsSubstring &aDocumentURI,
+ bool aPrivate)
+ {
+ mStorage = new nsDOMStorage();
+@@ -1792,7 +1813,8 @@ nsDOMStorage2::InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &a
+ mPrincipal = aPrincipal;
+ mDocumentURI = aDocumentURI;
+
+- return mStorage->InitAsLocalStorage(aPrincipal, aDocumentURI, aPrivate);
++ return mStorage->InitAsLocalStorage(aFirstPartyURI, aPrincipal,
++ aDocumentURI, aPrivate);
+ }
+
+ already_AddRefed<nsIDOMStorage>
+diff --git a/dom/src/storage/nsDOMStorage.h b/dom/src/storage/nsDOMStorage.h
+index 7add846..b795397 100644
+--- a/dom/src/storage/nsDOMStorage.h
++++ b/dom/src/storage/nsDOMStorage.h
+@@ -114,7 +114,8 @@ public:
+ DOMStorageBase(DOMStorageBase&);
+
+ virtual void InitAsSessionStorage(nsIURI* aDomainURI, bool aPrivate);
+- virtual void InitAsLocalStorage(nsIURI* aDomainURI, bool aCanUseChromePersist, bool aPrivate);
++ virtual void InitAsLocalStorage(nsIURI* aFirstPartyURI, nsIURI* aDomainURI,
++ bool aCanUseChromePersist, bool aPrivate);
+
+ virtual nsTArray<nsString>* GetKeys(bool aCallerSecure) = 0;
+ virtual nsresult GetLength(bool aCallerSecure, uint32_t* aLength) = 0;
+@@ -221,7 +222,8 @@ public:
+ ~DOMStorageImpl();
+
+ virtual void InitAsSessionStorage(nsIURI* aDomainURI, bool aPrivate);
+- virtual void InitAsLocalStorage(nsIURI* aDomainURI, bool aCanUseChromePersist, bool aPrivate);
++ virtual void InitAsLocalStorage(nsIURI *aFirstPartyURI, nsIURI* aDomainURI,
++ bool aCanUseChromePersist, bool aPrivate);
+
+ bool SessionOnly() {
+ return mSessionOnly;
+@@ -336,7 +338,9 @@ public:
+ // nsPIDOMStorage
+ virtual nsresult InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI,
+ bool aPrivate);
+- virtual nsresult InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI,
++ virtual nsresult InitAsLocalStorage(nsIURI *aFirstPartyURI,
++ nsIPrincipal *aPrincipal,
++ const nsSubstring &aDocumentURI,
+ bool aPrivate);
+ virtual already_AddRefed<nsIDOMStorage> Clone();
+ virtual already_AddRefed<nsIDOMStorage> Fork(const nsSubstring &aDocumentURI);
+@@ -411,7 +415,9 @@ public:
+ // nsPIDOMStorage
+ virtual nsresult InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI,
+ bool aPrivate);
+- virtual nsresult InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI,
++ virtual nsresult InitAsLocalStorage(nsIURI *aFirstPartyURI,
++ nsIPrincipal *aPrincipal,
++ const nsSubstring &aDocumentURI,
+ bool aPrivate);
+ virtual already_AddRefed<nsIDOMStorage> Clone();
+ virtual already_AddRefed<nsIDOMStorage> Fork(const nsSubstring &aDocumentURI);
+diff --git a/dom/src/storage/nsDOMStorageDBWrapper.cpp b/dom/src/storage/nsDOMStorageDBWrapper.cpp
+index bd2581b..048738a 100644
+--- a/dom/src/storage/nsDOMStorageDBWrapper.cpp
++++ b/dom/src/storage/nsDOMStorageDBWrapper.cpp
+@@ -47,7 +47,6 @@ nsDOMStorageDBWrapper::~nsDOMStorageDBWrapper()
+ void
+ nsDOMStorageDBWrapper::Close()
+ {
+- mPersistentDB.Close();
+ mChromePersistentDB.Close();
+ }
+
+@@ -56,13 +55,13 @@ nsDOMStorageDBWrapper::Init()
+ {
+ nsresult rv;
+
+- rv = mPersistentDB.Init(NS_LITERAL_STRING("webappsstore.sqlite"));
++ rv = mPersistentDB.Init();
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = mChromePersistentDB.Init(NS_LITERAL_STRING("chromeappsstore.sqlite"));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+- rv = mSessionOnlyDB.Init(&mPersistentDB);
++ rv = mSessionOnlyDB.Init();
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = mPrivateBrowsingDB.Init();
+@@ -74,16 +73,14 @@ nsDOMStorageDBWrapper::Init()
+ nsresult
+ nsDOMStorageDBWrapper::FlushAndDeleteTemporaryTables(bool force)
+ {
+- nsresult rv1, rv2;
++ nsresult rv1;
+ rv1 = mChromePersistentDB.FlushTemporaryTables(force);
+- rv2 = mPersistentDB.FlushTemporaryTables(force);
+
+ // Everything flushed? Then no need for a timer.
+- if (!mChromePersistentDB.mTempTableLoads.Count() &&
+- !mPersistentDB.mTempTableLoads.Count())
++ if (!mChromePersistentDB.mTempTableLoads.Count())
+ StopTempTableFlushTimer();
+
+- return NS_FAILED(rv1) ? rv1 : rv2;
++ return rv1;
+ }
+
+ #define IMPL_FORWARDER_GUTS(_return, _code) \
+@@ -243,7 +240,8 @@ nsDOMStorageDBWrapper::GetUsage(const nsACString& aDomain,
+ }
+
+ nsresult
+-nsDOMStorageDBWrapper::CreateOriginScopeDBKey(nsIURI* aUri, nsACString& aKey)
++nsDOMStorageDBWrapper::CreateOriginScopeDBKey(nsIURI *aFirstPartyURI,
++ nsIURI* aUri, nsACString& aKey)
+ {
+ nsresult rv;
+
+@@ -264,6 +262,17 @@ nsDOMStorageDBWrapper::CreateOriginScopeDBKey(nsIURI* aUri, nsACString& aKey)
+ aKey.Append(nsPrintfCString("%d", port));
+ }
+
++ // Isolate scope keys to the URL bar domain by appending &firstPartyHost
++ // if available.
++ if (aFirstPartyURI) {
++ nsCAutoString host;
++ rv = aFirstPartyURI->GetHost(host);
++ if (NS_SUCCEEDED(rv) && (host.Length() > 0)) {
++ aKey.AppendLiteral("&");
++ aKey.Append(host);
++ }
++ }
++
+ return NS_OK;
+ }
+
+@@ -317,7 +326,8 @@ nsDOMStorageDBWrapper::CreateDomainScopeDBKey(const nsACString& aAsciiDomain,
+ }
+
+ nsresult
+-nsDOMStorageDBWrapper::CreateQuotaDomainDBKey(const nsACString& aAsciiDomain,
++nsDOMStorageDBWrapper::CreateQuotaDomainDBKey(nsIURI *aFirstPartyURI,
++ const nsACString& aAsciiDomain,
+ bool aIncludeSubDomains,
+ bool aEffectiveTLDplus1Only,
+ nsACString& aKey)
+@@ -351,6 +361,17 @@ nsDOMStorageDBWrapper::CreateQuotaDomainDBKey(const nsACString& aAsciiDomain,
+ if (!aIncludeSubDomains)
+ subdomainsDBKey.AppendLiteral(":");
+
++ // Isolate quota keys to the URL bar domain by appending &firstPartyHost
++ // if available.
++ if (aFirstPartyURI) {
++ nsCAutoString host;
++ rv = aFirstPartyURI->GetHost(host);
++ if (NS_SUCCEEDED(rv) && (host.Length() > 0)) {
++ subdomainsDBKey.AppendLiteral("&");
++ subdomainsDBKey.Append(host);
++ }
++ }
++
+ aKey.Assign(subdomainsDBKey);
+ return NS_OK;
+ }
+diff --git a/dom/src/storage/nsDOMStorageDBWrapper.h b/dom/src/storage/nsDOMStorageDBWrapper.h
+index 94d28af..60a4f91 100644
+--- a/dom/src/storage/nsDOMStorageDBWrapper.h
++++ b/dom/src/storage/nsDOMStorageDBWrapper.h
+@@ -178,9 +178,11 @@ public:
+ /**
+ * Turns "http://foo.bar.com:80" to "moc.rab.oof.:http:80",
+ * i.e. reverses the host, appends a dot, appends the schema
+- * and a port number.
++ * and a port number. If aFirstPartyURI is present, the first party
++ * host is appended, e.g., "moc.rab.oof.:http:80:example.com"
+ */
+- static nsresult CreateOriginScopeDBKey(nsIURI* aUri, nsACString& aKey);
++ static nsresult CreateOriginScopeDBKey(nsIURI *aFirstPartyURI,
++ nsIURI* aUri, nsACString& aKey);
+
+ /**
+ * Turns "http://foo.bar.com" to "moc.rab.oof.",
+@@ -192,9 +194,11 @@ public:
+ /**
+ * Turns "foo.bar.com" to "moc.rab.",
+ * i.e. extracts eTLD+1 from the host, reverses the result
+- * and appends a dot.
++ * and appends a dot. If aFirstPartyURI is present, the first party
++ * host is appended, e.g., "moc.rab.:example.com"
+ */
+- static nsresult CreateQuotaDomainDBKey(const nsACString& aAsciiDomain,
++ static nsresult CreateQuotaDomainDBKey(nsIURI *aFirstPartyURI,
++ const nsACString& aAsciiDomain,
+ bool aIncludeSubDomains, bool aETLDplus1Only,
+ nsACString& aKey);
+
+@@ -222,7 +226,7 @@ public:
+
+ protected:
+ nsDOMStoragePersistentDB mChromePersistentDB;
+- nsDOMStoragePersistentDB mPersistentDB;
++ nsDOMStorageMemoryDB mPersistentDB; // No longer an nsDOMStoragePersistentDB
+ nsDOMStorageMemoryDB mSessionOnlyDB;
+ nsDOMStorageMemoryDB mPrivateBrowsingDB;
+
+diff --git a/dom/src/storage/nsDOMStorageMemoryDB.cpp b/dom/src/storage/nsDOMStorageMemoryDB.cpp
+index 5cc2e5d..639f516 100644
+--- a/dom/src/storage/nsDOMStorageMemoryDB.cpp
++++ b/dom/src/storage/nsDOMStorageMemoryDB.cpp
+@@ -382,7 +382,12 @@ nsDOMStorageMemoryDB::GetUsage(const nsACString& aDomain,
+ nsresult rv;
+
+ nsCAutoString quotadomainDBKey;
+- rv = nsDOMStorageDBWrapper::CreateQuotaDomainDBKey(aDomain,
++ // This GetUsage() call is only used to report usage totals in the
++ // preferences and page info. UI, and only for sites that have been
++ // granted "offline application" permission. Since we pass nullptr
++ // for the firstPartURI, the usage total returned will not be
++ // partitioned by first party, which is OK for the UI.
++ rv = nsDOMStorageDBWrapper::CreateQuotaDomainDBKey(nullptr, aDomain,
+ aIncludeSubDomains,
+ false,
+ quotadomainDBKey);
+@@ -395,6 +400,7 @@ struct GetUsageEnumStruc
+ {
+ int32_t mUsage;
+ int32_t mExcludeOfflineFromUsage;
++ nsCString mFirstPartyHostSuffix; // e.g., &example.com
+ nsCString mSubdomain;
+ };
+
+@@ -405,7 +411,9 @@ GetUsageEnum(const nsACString& key,
+ {
+ GetUsageEnumStruc* struc = (GetUsageEnumStruc*)closure;
+
+- if (StringBeginsWith(key, struc->mSubdomain)) {
++ if (StringBeginsWith(key, struc->mSubdomain) &&
++ ((0 == struc->mFirstPartyHostSuffix.Length()) ||
++ StringEndsWith(key, struc->mFirstPartyHostSuffix))) {
+ if (struc->mExcludeOfflineFromUsage) {
+ nsCAutoString domain;
+ nsresult rv = nsDOMStorageDBWrapper::GetDomainFromScopeKey(key, domain);
+@@ -428,6 +436,15 @@ nsDOMStorageMemoryDB::GetUsageInternal(const nsACString& aQuotaDomainDBKey,
+ struc.mUsage = 0;
+ struc.mExcludeOfflineFromUsage = aExcludeOfflineFromUsage;
+ struc.mSubdomain = aQuotaDomainDBKey;
++ nsCAutoString tmpQuotaKey(aQuotaDomainDBKey);
++ int32_t idx = tmpQuotaKey.RFindChar('&');
++ if (idx > 0) {
++ const nsDependentCSubstring& tmpStr = Substring(tmpQuotaKey, idx);
++ if (tmpStr.Length() > 1) {
++ struc.mFirstPartyHostSuffix = tmpStr;
++ struc.mSubdomain = Substring(tmpQuotaKey, 0, idx - 1);
++ }
++ }
+
+ if (mPreloadDB) {
+ nsresult rv;
+diff --git a/dom/src/storage/nsDOMStoragePersistentDB.cpp b/dom/src/storage/nsDOMStoragePersistentDB.cpp
+index 93ad303..7814a60 100644
+--- a/dom/src/storage/nsDOMStoragePersistentDB.cpp
++++ b/dom/src/storage/nsDOMStoragePersistentDB.cpp
+@@ -813,7 +813,13 @@ nsDOMStoragePersistentDB::GetUsage(const nsACString& aDomain,
+ nsresult rv;
+
+ nsCAutoString quotadomainDBKey;
+- rv = nsDOMStorageDBWrapper::CreateQuotaDomainDBKey(aDomain,
++ // This GetUsage() call is only used to report usage totals in the
++ // preferences and page info. UI, and only for sites that have been
++ // granted "offline application" permission. Since we pass nullptr
++ // for the firstPartURI, the usage total returned will not be
++ // partitioned by first party, which is OK for the UI.
++ // Also, Tor does not use currently use nsDOMStoragePersistentDB.
++ rv = nsDOMStorageDBWrapper::CreateQuotaDomainDBKey(nullptr, aDomain,
+ aIncludeSubDomains,
+ false,
+ quotadomainDBKey);
+diff --git a/embedding/components/windowwatcher/src/nsWindowWatcher.cpp b/embedding/components/windowwatcher/src/nsWindowWatcher.cpp
+index 6abbed7..0bad9ed 100644
+--- a/embedding/components/windowwatcher/src/nsWindowWatcher.cpp
++++ b/embedding/components/windowwatcher/src/nsWindowWatcher.cpp
+@@ -963,14 +963,15 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow *aParent,
+
+ if (subjectPrincipal && parentDocShell) {
+ nsCOMPtr<nsIDOMStorage> storage;
+- parentDocShell->GetSessionStorageForPrincipal(subjectPrincipal,
++ parentDocShell->GetSessionStorageForFirstParty(uriToLoad, subjectPrincipal,
+ EmptyString(), false,
+ getter_AddRefs(storage));
+ nsCOMPtr<nsPIDOMStorage> piStorage =
+ do_QueryInterface(storage);
+ if (piStorage){
+ storage = piStorage->Clone();
+- newDocShell->AddSessionStorage(
++ newDocShell->AddSessionStorageForFirstParty(
++ uriToLoad,
+ piStorage->Principal(),
+ storage);
+ }
+--
+1.7.5.4
+
More information about the tor-commits
mailing list