aboutsummaryrefslogtreecommitdiff
path: root/gnu
diff options
context:
space:
mode:
authorMark H Weaver <mhw@netris.org>2017-11-15 09:35:12 -0500
committerMark H Weaver <mhw@netris.org>2017-11-16 00:01:46 -0500
commitf1e32145341326f56b172288861a2d4b30967892 (patch)
tree0a0f6a76e346d8c93ffa4eb17b663fb70b591fb9 /gnu
parent6a71fa6faaa6d3f5812d08008b487f0b8b12c997 (diff)
downloadguix-f1e32145341326f56b172288861a2d4b30967892.tar
guix-f1e32145341326f56b172288861a2d4b30967892.tar.gz
gnu: icecat: Add more fixes from upstream mozilla-esr52.
Add fixes for CVE-2017-7830, the remaining 1/2 changesets for CVE-2017-7828, the remaining 1/19 changesets for CVE-2017-7826, and selected other fixes. * gnu/packages/gnuzilla.scm (icecat)[source]: Add selected fixes from the upstream mozilla-esr52 repository. * gnu/packages/patches/icecat-bug-1348660-pt5.patch, gnu/packages/patches/icecat-bug-1415133.patch: New files. * gnu/local.mk (dist_patch_DATA): Add them.
Diffstat (limited to 'gnu')
-rw-r--r--gnu/local.mk2
-rw-r--r--gnu/packages/gnuzilla.scm19
-rw-r--r--gnu/packages/patches/icecat-bug-1348660-pt5.patch727
-rw-r--r--gnu/packages/patches/icecat-bug-1415133.patch40
4 files changed, 787 insertions, 1 deletions
diff --git a/gnu/local.mk b/gnu/local.mk
index 459112fc57..84483da999 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -744,6 +744,8 @@ dist_patch_DATA = \
%D%/packages/patches/hurd-fix-eth-multiplexer-dependency.patch \
%D%/packages/patches/hydra-disable-darcs-test.patch \
%D%/packages/patches/icecat-avoid-bundled-libraries.patch \
+ %D%/packages/patches/icecat-bug-1348660-pt5.patch \
+ %D%/packages/patches/icecat-bug-1415133.patch \
%D%/packages/patches/icu4c-CVE-2017-7867-CVE-2017-7868.patch \
%D%/packages/patches/icu4c-CVE-2017-14952.patch \
%D%/packages/patches/icu4c-reset-keyword-list-iterator.patch \
diff --git a/gnu/packages/gnuzilla.scm b/gnu/packages/gnuzilla.scm
index ca563777c6..93aaaa9c5b 100644
--- a/gnu/packages/gnuzilla.scm
+++ b/gnu/packages/gnuzilla.scm
@@ -463,7 +463,24 @@ standards.")
(mozilla-patch "icecat-CVE-2017-7826-pt16.patch" "dd068f4e132a" "17qy9c1vfkz3pj6y8qmqbic73wrangsbdlylk2s54nbzhhp9cj1g")
(mozilla-patch "icecat-CVE-2017-7826-pt17.patch" "e6bd533b57e9" "1mmqav9yhxd0j47yffcdykaqjibfwjsk0jn0f44099s87y8qn9zy")
(mozilla-patch "icecat-CVE-2017-7826-pt18.patch" "2a87fb6b9c07" "0z0scw4y1vqhqkbw1ag14g8xrif14l95x7fd50q2sw425lli29lc")
- (mozilla-patch "icecat-bug-1404910.patch" "5007f2472f64" "0ns1l4yipwbb52sps2xzg30qd1rkpwykxq4chjg3wllhmcxbvvpw")))
+ (mozilla-patch "icecat-bug-1404910.patch" "5007f2472f64" "0ns1l4yipwbb52sps2xzg30qd1rkpwykxq4chjg3wllhmcxbvvpw")
+ (mozilla-patch "icecat-CVE-2017-7830.patch" "04e3b5c1f0b2" "0nmv3jnx94ykxg64xkiwc8kx4df8zw7y5yzjnxz1sll2v88b9hmf")
+ (mozilla-patch "icecat-CVE-2017-7828-pt2.patch" "2f48c03d9b3f" "16qdy3rahmkhsjnzqjcgzg1a4k7czd40m04gs9i75cd88kbripri")
+ (mozilla-patch "icecat-bug-1348660-pt1.patch" "a352bfcbaf55" "1j3kxnhci9fh3lj8rizbcfv8xzn5kikxwpfy8a091d51sdn20873")
+ (mozilla-patch "icecat-bug-1348660-pt2.patch" "57f43e2ab9b5" "1jva4y79zb85npak3mddrx5rsf4mxczb314kcr8yhlkwqv0nx5sp")
+ (mozilla-patch "icecat-bug-1348660-pt3.patch" "917d65bb8896" "0k29y8i96lanqjjm6vybg0s6gjbk1mz5bfnga6aj1g0hnb7c3s8d")
+ (mozilla-patch "icecat-bug-1348660-pt4.patch" "28934912eede" "1mhxw26050l3d09n8w912a86df87afcshvsk9k1k375anfk0927x")
+ (search-patch "icecat-bug-1348660-pt5.patch")
+ (mozilla-patch "icecat-bug-1348660-pt6.patch" "556ff3bfb9fc" "0kckjc8jp885xfaiwx2b9qnk1plqjhi0mwhjjcmfajvh3l3mrl8h")
+ (mozilla-patch "icecat-bug-1350564.patch" "2abf26abb2a2" "0axdzp9g9k74wpkwrsdx263h01sv9bd3rarhhl68xnvc7n6i45lx")
+ (mozilla-patch "icecat-bug-1404787.patch" "8335e1d7b140" "17d7kb8ginzflhdkrbi60vh2b907spbzmvwih7a595gqpihmnqqn")
+ (mozilla-patch "icecat-CVE-2017-7826-pt19.patch" "de336078d36b" "0gyzbap8hr1iywk0x2x0h7z7zp7q89hi56h8c03vvc7771dkvjkf")
+ (mozilla-patch "icecat-bug-1047098-pt1.patch" "088577f0c46e" "0y3sz6kx07ls7jsvhqhhrl6v69a94wqvv3lz7hnplah23y06h17z")
+ (mozilla-patch "icecat-bug-1047098-pt2.patch" "c7e3abf74023" "11dcjzx56v4yb2dvm23j2g86q8yva2hc69lmb7s5w18l6ygwwhzr")
+ (mozilla-patch "icecat-bug-1047098-pt3.patch" "36bd15d14c5a" "0cb3l3hpsgk674f08kfamxhqfga3ah5v904gpxq9ag006vzd2cxz")
+ (mozilla-patch "icecat-bug-1404105.patch" "2909ba991f31" "126vssj57dc800347f075wlnjzcwamnxxmgxl9w78jpb0hj9gf16")
+ (search-patch "icecat-bug-1415133.patch")
+ (mozilla-patch "icecat-bug-1355576.patch" "cf34a0574e58" "1z7sa1d12hypgivm5xxn32s58afpjcij97jvnafcgnfvxywrgr1m")))
(modules '((guix build utils)))
(snippet
'(begin
diff --git a/gnu/packages/patches/icecat-bug-1348660-pt5.patch b/gnu/packages/patches/icecat-bug-1348660-pt5.patch
new file mode 100644
index 0000000000..b0bede3b38
--- /dev/null
+++ b/gnu/packages/patches/icecat-bug-1348660-pt5.patch
@@ -0,0 +1,727 @@
+This is a subset of the following changeset from upstream:
+ https://hg.mozilla.org/releases/mozilla-esr52/raw-rev/5e07bd37ac61
+
+This excludes all test code from that changeset, including a GIT binary patch
+that is not supported by Guix's patch-and-repack mechanism.
+
+# HG changeset patch
+# User Jan Varga <jan.varga@gmail.com>
+# Date 1490181244 -3600
+# Node ID 5e07bd37ac6162f218dfe03ed83b5dcca9653b68
+# Parent 28934912eede9e14895baf4af7575ca9639f59ee
+Bug 1348660 - Part 5: Implement a method to retrieve usage data for all origins at once. r=btseng, a=lizzard
+
+diff --git a/dom/quota/ActorsChild.cpp b/dom/quota/ActorsChild.cpp
+--- a/dom/quota/ActorsChild.cpp
++++ b/dom/quota/ActorsChild.cpp
+@@ -137,16 +137,52 @@ QuotaUsageRequestChild::HandleResponse(n
+ AssertIsOnOwningThread();
+ MOZ_ASSERT(NS_FAILED(aResponse));
+ MOZ_ASSERT(mRequest);
+
+ mRequest->SetError(aResponse);
+ }
+
+ void
++QuotaUsageRequestChild::HandleResponse(const nsTArray<OriginUsage>& aResponse)
++{
++ AssertIsOnOwningThread();
++ MOZ_ASSERT(mRequest);
++
++ RefPtr<nsVariant> variant = new nsVariant();
++
++ if (aResponse.IsEmpty()) {
++ variant->SetAsEmptyArray();
++ } else {
++ nsTArray<RefPtr<UsageResult>> usageResults;
++
++ const uint32_t count = aResponse.Length();
++
++ usageResults.SetCapacity(count);
++
++ for (uint32_t index = 0; index < count; index++) {
++ auto& originUsage = aResponse[index];
++
++ RefPtr<UsageResult> usageResult = new UsageResult(originUsage.origin(),
++ originUsage.persisted(),
++ originUsage.usage());
++
++ usageResults.AppendElement(usageResult.forget());
++ }
++
++ variant->SetAsArray(nsIDataType::VTYPE_INTERFACE_IS,
++ &NS_GET_IID(nsIQuotaUsageResult),
++ usageResults.Length(),
++ static_cast<void*>(usageResults.Elements()));
++ }
++
++ mRequest->SetResult(variant);
++}
++
++void
+ QuotaUsageRequestChild::HandleResponse(const OriginUsageResponse& aResponse)
+ {
+ AssertIsOnOwningThread();
+ MOZ_ASSERT(mRequest);
+
+ RefPtr<OriginUsageResult> result =
+ new OriginUsageResult(aResponse.usage(),
+ aResponse.fileUsage(),
+@@ -177,16 +213,20 @@ QuotaUsageRequestChild::Recv__delete__(c
+ AssertIsOnOwningThread();
+ MOZ_ASSERT(mRequest);
+
+ switch (aResponse.type()) {
+ case UsageRequestResponse::Tnsresult:
+ HandleResponse(aResponse.get_nsresult());
+ break;
+
++ case UsageRequestResponse::TAllUsageResponse:
++ HandleResponse(aResponse.get_AllUsageResponse().originUsages());
++ break;
++
+ case UsageRequestResponse::TOriginUsageResponse:
+ HandleResponse(aResponse.get_OriginUsageResponse());
+ break;
+
+ default:
+ MOZ_CRASH("Unknown response type!");
+ }
+
+diff --git a/dom/quota/ActorsChild.h b/dom/quota/ActorsChild.h
+--- a/dom/quota/ActorsChild.h
++++ b/dom/quota/ActorsChild.h
+@@ -93,16 +93,19 @@ private:
+
+ // Only destroyed by QuotaChild.
+ ~QuotaUsageRequestChild();
+
+ void
+ HandleResponse(nsresult aResponse);
+
+ void
++ HandleResponse(const nsTArray<OriginUsage>& aResponse);
++
++ void
+ HandleResponse(const OriginUsageResponse& aResponse);
+
+ // IPDL methods are only called by IPDL.
+ virtual void
+ ActorDestroy(ActorDestroyReason aWhy) override;
+
+ virtual bool
+ Recv__delete__(const UsageRequestResponse& aResponse) override;
+diff --git a/dom/quota/ActorsParent.cpp b/dom/quota/ActorsParent.cpp
+--- a/dom/quota/ActorsParent.cpp
++++ b/dom/quota/ActorsParent.cpp
+@@ -1039,16 +1039,42 @@ private:
+ // IPDL methods.
+ void
+ ActorDestroy(ActorDestroyReason aWhy) override;
+
+ bool
+ RecvCancel() override;
+ };
+
++class GetUsageOp final
++ : public QuotaUsageRequestBase
++{
++ nsTArray<OriginUsage> mOriginUsages;
++ nsDataHashtable<nsCStringHashKey, uint32_t> mOriginUsagesIndex;
++
++ bool mGetAll;
++
++public:
++ explicit GetUsageOp(const UsageRequestParams& aParams);
++
++private:
++ ~GetUsageOp()
++ { }
++
++ nsresult
++ TraverseRepository(QuotaManager* aQuotaManager,
++ PersistenceType aPersistenceType);
++
++ nsresult
++ DoDirectoryWork(QuotaManager* aQuotaManager) override;
++
++ void
++ GetResponse(UsageRequestResponse& aResponse) override;
++};
++
+ class GetOriginUsageOp final
+ : public QuotaUsageRequestBase
+ {
+ // If mGetGroupUsage is false, we use mUsageInfo to record the origin usage
+ // and the file usage. Otherwise, we use it to record the group usage and the
+ // limit.
+ UsageInfo mUsageInfo;
+
+@@ -5693,16 +5719,20 @@ PQuotaUsageRequestParent*
+ Quota::AllocPQuotaUsageRequestParent(const UsageRequestParams& aParams)
+ {
+ AssertIsOnBackgroundThread();
+ MOZ_ASSERT(aParams.type() != UsageRequestParams::T__None);
+
+ RefPtr<QuotaUsageRequestBase> actor;
+
+ switch (aParams.type()) {
++ case UsageRequestParams::TAllUsageParams:
++ actor = new GetUsageOp(aParams);
++ break;
++
+ case UsageRequestParams::TOriginUsageParams:
+ actor = new GetOriginUsageOp(aParams);
+ break;
+
+ default:
+ MOZ_CRASH("Should never get here!");
+ }
+
+@@ -6033,16 +6063,189 @@ QuotaUsageRequestBase::RecvCancel()
+ if (mCanceled.exchange(true)) {
+ NS_WARNING("Canceled more than once?!");
+ return false;
+ }
+
+ return true;
+ }
+
++GetUsageOp::GetUsageOp(const UsageRequestParams& aParams)
++ : mGetAll(aParams.get_AllUsageParams().getAll())
++{
++ AssertIsOnOwningThread();
++ MOZ_ASSERT(aParams.type() == UsageRequestParams::TAllUsageParams);
++}
++
++nsresult
++GetUsageOp::TraverseRepository(QuotaManager* aQuotaManager,
++ PersistenceType aPersistenceType)
++{
++ AssertIsOnIOThread();
++ MOZ_ASSERT(aQuotaManager);
++
++ nsresult rv;
++
++ nsCOMPtr<nsIFile> directory =
++ do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
++ if (NS_WARN_IF(NS_FAILED(rv))) {
++ return rv;
++ }
++
++ rv = directory->InitWithPath(aQuotaManager->GetStoragePath(aPersistenceType));
++ if (NS_WARN_IF(NS_FAILED(rv))) {
++ return rv;
++ }
++
++ bool exists;
++ rv = directory->Exists(&exists);
++ if (NS_WARN_IF(NS_FAILED(rv))) {
++ return rv;
++ }
++
++ if (!exists) {
++ return NS_OK;
++ }
++
++ nsCOMPtr<nsISimpleEnumerator> entries;
++ rv = directory->GetDirectoryEntries(getter_AddRefs(entries));
++ if (NS_WARN_IF(NS_FAILED(rv))) {
++ return rv;
++ }
++
++ bool persistent = aPersistenceType == PERSISTENCE_TYPE_PERSISTENT;
++
++ bool hasMore;
++ while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) &&
++ hasMore && !mCanceled) {
++ nsCOMPtr<nsISupports> entry;
++ rv = entries->GetNext(getter_AddRefs(entry));
++ if (NS_WARN_IF(NS_FAILED(rv))) {
++ return rv;
++ }
++
++ nsCOMPtr<nsIFile> originDir = do_QueryInterface(entry);
++ MOZ_ASSERT(originDir);
++
++ bool isDirectory;
++ rv = originDir->IsDirectory(&isDirectory);
++ if (NS_WARN_IF(NS_FAILED(rv))) {
++ return rv;
++ }
++
++ if (!isDirectory) {
++ nsString leafName;
++ rv = originDir->GetLeafName(leafName);
++ if (NS_WARN_IF(NS_FAILED(rv))) {
++ return rv;
++ }
++
++ if (!leafName.EqualsLiteral(DSSTORE_FILE_NAME)) {
++ QM_WARNING("Something (%s) in the repository that doesn't belong!",
++ NS_ConvertUTF16toUTF8(leafName).get());
++ }
++ continue;
++ }
++
++ int64_t timestamp;
++ nsCString suffix;
++ nsCString group;
++ nsCString origin;
++ bool isApp;
++ rv = aQuotaManager->GetDirectoryMetadata2WithRestore(originDir,
++ persistent,
++ &timestamp,
++ suffix,
++ group,
++ origin,
++ &isApp);
++ if (NS_WARN_IF(NS_FAILED(rv))) {
++ return rv;
++ }
++
++ if (!mGetAll &&
++ aQuotaManager->IsOriginWhitelistedForPersistentStorage(origin)) {
++ continue;
++ }
++
++ OriginUsage* originUsage;
++
++ // We can't store pointers to OriginUsage objects in the hashtable
++ // since AppendElement() reallocates its internal array buffer as number
++ // of elements grows.
++ uint32_t index;
++ if (mOriginUsagesIndex.Get(origin, &index)) {
++ originUsage = &mOriginUsages[index];
++ } else {
++ index = mOriginUsages.Length();
++
++ originUsage = mOriginUsages.AppendElement();
++
++ originUsage->origin() = origin;
++ originUsage->persisted() = false;
++ originUsage->usage() = 0;
++
++ mOriginUsagesIndex.Put(origin, index);
++ }
++
++ UsageInfo usageInfo;
++ rv = GetUsageForOrigin(aQuotaManager,
++ aPersistenceType,
++ group,
++ origin,
++ isApp,
++ &usageInfo);
++ if (NS_WARN_IF(NS_FAILED(rv))) {
++ return rv;
++ }
++
++ originUsage->usage() = originUsage->usage() + usageInfo.TotalUsage();
++ }
++ if (NS_WARN_IF(NS_FAILED(rv))) {
++ return rv;
++ }
++
++ return NS_OK;
++}
++
++nsresult
++GetUsageOp::DoDirectoryWork(QuotaManager* aQuotaManager)
++{
++ AssertIsOnIOThread();
++
++ PROFILER_LABEL("Quota", "GetUsageOp::DoDirectoryWork",
++ js::ProfileEntry::Category::OTHER);
++
++ nsresult rv;
++
++ for (const PersistenceType type : kAllPersistenceTypes) {
++ rv = TraverseRepository(aQuotaManager, type);
++ if (NS_WARN_IF(NS_FAILED(rv))) {
++ return rv;
++ }
++ }
++
++ return NS_OK;
++}
++
++void
++GetUsageOp::GetResponse(UsageRequestResponse& aResponse)
++{
++ AssertIsOnOwningThread();
++
++ aResponse = AllUsageResponse();
++
++ if (!mOriginUsages.IsEmpty()) {
++ nsTArray<OriginUsage>& originUsages =
++ aResponse.get_AllUsageResponse().originUsages();
++
++ mOriginUsages.SwapElements(originUsages);
++ }
++}
++
+ GetOriginUsageOp::GetOriginUsageOp(const UsageRequestParams& aParams)
+ : mParams(aParams.get_OriginUsageParams())
+ , mGetGroupUsage(aParams.get_OriginUsageParams().getGroupUsage())
+ {
+ AssertIsOnOwningThread();
+ MOZ_ASSERT(aParams.type() == UsageRequestParams::TOriginUsageParams);
+ }
+
+diff --git a/dom/quota/PQuota.ipdl b/dom/quota/PQuota.ipdl
+--- a/dom/quota/PQuota.ipdl
++++ b/dom/quota/PQuota.ipdl
+@@ -12,24 +12,30 @@ include "mozilla/dom/quota/Serialization
+
+ using mozilla::dom::quota::PersistenceType
+ from "mozilla/dom/quota/PersistenceType.h";
+
+ namespace mozilla {
+ namespace dom {
+ namespace quota {
+
++struct AllUsageParams
++{
++ bool getAll;
++};
++
+ struct OriginUsageParams
+ {
+ PrincipalInfo principalInfo;
+ bool getGroupUsage;
+ };
+
+ union UsageRequestParams
+ {
++ AllUsageParams;
+ OriginUsageParams;
+ };
+
+ struct ClearOriginParams
+ {
+ PrincipalInfo principalInfo;
+ PersistenceType persistenceType;
+ bool persistenceTypeIsExplicit;
+diff --git a/dom/quota/PQuotaUsageRequest.ipdl b/dom/quota/PQuotaUsageRequest.ipdl
+--- a/dom/quota/PQuotaUsageRequest.ipdl
++++ b/dom/quota/PQuotaUsageRequest.ipdl
+@@ -3,26 +3,39 @@
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+ include protocol PQuota;
+
+ namespace mozilla {
+ namespace dom {
+ namespace quota {
+
++struct OriginUsage
++{
++ nsCString origin;
++ bool persisted;
++ uint64_t usage;
++};
++
++struct AllUsageResponse
++{
++ OriginUsage[] originUsages;
++};
++
+ struct OriginUsageResponse
+ {
+ uint64_t usage;
+ uint64_t fileUsage;
+ uint64_t limit;
+ };
+
+ union UsageRequestResponse
+ {
+ nsresult;
++ AllUsageResponse;
+ OriginUsageResponse;
+ };
+
+ protocol PQuotaUsageRequest
+ {
+ manager PQuota;
+
+ parent:
+diff --git a/dom/quota/QuotaManagerService.cpp b/dom/quota/QuotaManagerService.cpp
+--- a/dom/quota/QuotaManagerService.cpp
++++ b/dom/quota/QuotaManagerService.cpp
+@@ -490,16 +490,41 @@ QuotaManagerService::RemoveIdleObserver(
+
+ NS_IMPL_ADDREF(QuotaManagerService)
+ NS_IMPL_RELEASE_WITH_DESTROY(QuotaManagerService, Destroy())
+ NS_IMPL_QUERY_INTERFACE(QuotaManagerService,
+ nsIQuotaManagerService,
+ nsIObserver)
+
+ NS_IMETHODIMP
++QuotaManagerService::GetUsage(nsIQuotaUsageCallback* aCallback,
++ bool aGetAll,
++ nsIQuotaUsageRequest** _retval)
++{
++ MOZ_ASSERT(NS_IsMainThread());
++ MOZ_ASSERT(aCallback);
++
++ RefPtr<UsageRequest> request = new UsageRequest(aCallback);
++
++ AllUsageParams params;
++
++ params.getAll() = aGetAll;
++
++ nsAutoPtr<PendingRequestInfo> info(new UsageRequestInfo(request, params));
++
++ nsresult rv = InitiateRequest(info);
++ if (NS_WARN_IF(NS_FAILED(rv))) {
++ return rv;
++ }
++
++ request.forget(_retval);
++ return NS_OK;
++}
++
++NS_IMETHODIMP
+ QuotaManagerService::GetUsageForPrincipal(nsIPrincipal* aPrincipal,
+ nsIQuotaUsageCallback* aCallback,
+ bool aGetGroupUsage,
+ nsIQuotaUsageRequest** _retval)
+ {
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(aPrincipal);
+ MOZ_ASSERT(aCallback);
+diff --git a/dom/quota/QuotaRequests.cpp b/dom/quota/QuotaRequests.cpp
+--- a/dom/quota/QuotaRequests.cpp
++++ b/dom/quota/QuotaRequests.cpp
+@@ -86,16 +86,25 @@ RequestBase::GetResultCode(nsresult* aRe
+ if (!mHaveResultOrErrorCode) {
+ return NS_ERROR_FAILURE;
+ }
+
+ *aResultCode = mResultCode;
+ return NS_OK;
+ }
+
++UsageRequest::UsageRequest(nsIQuotaUsageCallback* aCallback)
++ : mCallback(aCallback)
++ , mBackgroundActor(nullptr)
++ , mCanceled(false)
++{
++ AssertIsOnOwningThread();
++ MOZ_ASSERT(aCallback);
++}
++
+ UsageRequest::UsageRequest(nsIPrincipal* aPrincipal,
+ nsIQuotaUsageCallback* aCallback)
+ : RequestBase(aPrincipal)
+ , mCallback(aCallback)
+ , mBackgroundActor(nullptr)
+ , mCanceled(false)
+ {
+ AssertIsOnOwningThread();
+diff --git a/dom/quota/QuotaRequests.h b/dom/quota/QuotaRequests.h
+--- a/dom/quota/QuotaRequests.h
++++ b/dom/quota/QuotaRequests.h
+@@ -73,16 +73,18 @@ class UsageRequest final
+
+ nsCOMPtr<nsIVariant> mResult;
+
+ QuotaUsageRequestChild* mBackgroundActor;
+
+ bool mCanceled;
+
+ public:
++ explicit UsageRequest(nsIQuotaUsageCallback* aCallback);
++
+ UsageRequest(nsIPrincipal* aPrincipal,
+ nsIQuotaUsageCallback* aCallback);
+
+ void
+ SetBackgroundActor(QuotaUsageRequestChild* aBackgroundActor);
+
+ void
+ ClearBackgroundActor()
+diff --git a/dom/quota/QuotaResults.cpp b/dom/quota/QuotaResults.cpp
+--- a/dom/quota/QuotaResults.cpp
++++ b/dom/quota/QuotaResults.cpp
+@@ -5,16 +5,53 @@
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+ #include "QuotaResults.h"
+
+ namespace mozilla {
+ namespace dom {
+ namespace quota {
+
++UsageResult::UsageResult(const nsACString& aOrigin,
++ bool aPersisted,
++ uint64_t aUsage)
++ : mOrigin(aOrigin)
++ , mUsage(aUsage)
++ , mPersisted(aPersisted)
++{
++}
++
++NS_IMPL_ISUPPORTS(UsageResult,
++ nsIQuotaUsageResult)
++
++NS_IMETHODIMP
++UsageResult::GetOrigin(nsACString& aOrigin)
++{
++ aOrigin = mOrigin;
++ return NS_OK;
++}
++
++NS_IMETHODIMP
++UsageResult::GetPersisted(bool* aPersisted)
++{
++ MOZ_ASSERT(aPersisted);
++
++ *aPersisted = mPersisted;
++ return NS_OK;
++}
++
++NS_IMETHODIMP
++UsageResult::GetUsage(uint64_t* aUsage)
++{
++ MOZ_ASSERT(aUsage);
++
++ *aUsage = mUsage;
++ return NS_OK;
++}
++
+ OriginUsageResult::OriginUsageResult(uint64_t aUsage,
+ uint64_t aFileUsage,
+ uint64_t aLimit)
+ : mUsage(aUsage)
+ , mFileUsage(aFileUsage)
+ , mLimit(aLimit)
+ {
+ }
+diff --git a/dom/quota/QuotaResults.h b/dom/quota/QuotaResults.h
+--- a/dom/quota/QuotaResults.h
++++ b/dom/quota/QuotaResults.h
+@@ -8,16 +8,36 @@
+ #define mozilla_dom_quota_QuotaResults_h
+
+ #include "nsIQuotaResults.h"
+
+ namespace mozilla {
+ namespace dom {
+ namespace quota {
+
++class UsageResult
++ : public nsIQuotaUsageResult
++{
++ nsCString mOrigin;
++ uint64_t mUsage;
++ bool mPersisted;
++
++public:
++ UsageResult(const nsACString& aOrigin,
++ bool aPersisted,
++ uint64_t aUsage);
++
++private:
++ virtual ~UsageResult()
++ { }
++
++ NS_DECL_ISUPPORTS
++ NS_DECL_NSIQUOTAUSAGERESULT
++};
++
+ class OriginUsageResult
+ : public nsIQuotaOriginUsageResult
+ {
+ uint64_t mUsage;
+ uint64_t mFileUsage;
+ uint64_t mLimit;
+
+ public:
+diff --git a/dom/quota/nsIQuotaManagerService.idl b/dom/quota/nsIQuotaManagerService.idl
+--- a/dom/quota/nsIQuotaManagerService.idl
++++ b/dom/quota/nsIQuotaManagerService.idl
+@@ -10,16 +10,31 @@ interface nsIPrincipal;
+ interface nsIQuotaRequest;
+ interface nsIQuotaUsageCallback;
+ interface nsIQuotaUsageRequest;
+
+ [scriptable, builtinclass, uuid(1b3d0a38-8151-4cf9-89fa-4f92c2ef0e7e)]
+ interface nsIQuotaManagerService : nsISupports
+ {
+ /**
++ * Schedules an asynchronous callback that will inspect all origins and
++ * return the total amount of disk space being used by storages for each
++ * origin separately.
++ *
++ * @param aCallback
++ * The callback that will be called when the usage is available.
++ * @param aGetAll
++ * An optional boolean to indicate inspection of all origins,
++ * including internal ones.
++ */
++ [must_use] nsIQuotaUsageRequest
++ getUsage(in nsIQuotaUsageCallback aCallback,
++ [optional] in boolean aGetAll);
++
++ /**
+ * Schedules an asynchronous callback that will return the total amount of
+ * disk space being used by storages for the given origin.
+ *
+ * @param aPrincipal
+ * A principal for the origin whose usage is being queried.
+ * @param aCallback
+ * The callback that will be called when the usage is available.
+ * @param aGetGroupUsage
+diff --git a/dom/quota/nsIQuotaRequests.idl b/dom/quota/nsIQuotaRequests.idl
+--- a/dom/quota/nsIQuotaRequests.idl
++++ b/dom/quota/nsIQuotaRequests.idl
+@@ -18,16 +18,17 @@ interface nsIQuotaRequestBase : nsISuppo
+
+ [must_use] readonly attribute nsresult resultCode;
+ };
+
+ [scriptable, uuid(166e28e6-cf6d-4927-a6d7-b51bca9d3469)]
+ interface nsIQuotaUsageRequest : nsIQuotaRequestBase
+ {
+ // The result can contain one of these types:
++ // array of nsIQuotaUsageResult
+ // nsIQuotaOriginUsageResult
+ [must_use] readonly attribute nsIVariant result;
+
+ attribute nsIQuotaUsageCallback callback;
+
+ [must_use] void
+ cancel();
+ };
+diff --git a/dom/quota/nsIQuotaResults.idl b/dom/quota/nsIQuotaResults.idl
+--- a/dom/quota/nsIQuotaResults.idl
++++ b/dom/quota/nsIQuotaResults.idl
+@@ -1,16 +1,26 @@
+ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+ /* vim: set ts=2 et sw=2 tw=80: */
+ /* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+ #include "nsISupports.idl"
+
++[scriptable, function, uuid(d8c9328b-9aa8-4f5d-90e6-482de4a6d5b8)]
++interface nsIQuotaUsageResult : nsISupports
++{
++ readonly attribute ACString origin;
++
++ readonly attribute boolean persisted;
++
++ readonly attribute unsigned long long usage;
++};
++
+ [scriptable, function, uuid(96df03d2-116a-493f-bb0b-118c212a6b32)]
+ interface nsIQuotaOriginUsageResult : nsISupports
+ {
+ readonly attribute unsigned long long usage;
+
+ readonly attribute unsigned long long fileUsage;
+
+ readonly attribute unsigned long long limit;
+
diff --git a/gnu/packages/patches/icecat-bug-1415133.patch b/gnu/packages/patches/icecat-bug-1415133.patch
new file mode 100644
index 0000000000..4e322d21fb
--- /dev/null
+++ b/gnu/packages/patches/icecat-bug-1415133.patch
@@ -0,0 +1,40 @@
+Based on:
+ https://hg.mozilla.org/releases/mozilla-esr52/raw-rev/22fe3ff3f923
+
+Adapted to apply cleanly to IceCat.
+
+# HG changeset patch
+# User Marco Bonardo <mbonardo@mozilla.com>
+# Date 1510052455 -3600
+# Node ID 22fe3ff3f92358596521f7155ddc512006022207
+# Parent 2909ba991f3134f9fbf4859cf08582f1c9845594
+Bug 1415133 - Downgrades from 55+ to ESR lose bookmarks. r=past a=lizzard
+
+MozReview-Commit-ID: 44Rw7m1FP4h
+
+diff --git a/toolkit/components/places/Database.cpp b/toolkit/components/places/Database.cpp
+--- a/toolkit/components/places/Database.cpp
++++ b/toolkit/components/places/Database.cpp
+@@ -761,16 +761,21 @@ Database::InitSchema(bool* aDatabaseMigr
+ // 2. implement a method that performs upgrade to your version from the
+ // previous one.
+ //
+ // NOTE: The downgrade process is pretty much complicated by the fact old
+ // versions cannot know what a new version is going to implement.
+ // The only thing we will do for downgrades is setting back the schema
+ // version, so that next upgrades will run again the migration step.
+
++ if (currentSchemaVersion > 36) {
++ // These versions are not downgradable.
++ return NS_ERROR_FILE_CORRUPTED;
++ }
++
+ if (currentSchemaVersion < DATABASE_SCHEMA_VERSION) {
+ *aDatabaseMigrated = true;
+
+ if (currentSchemaVersion < 11) {
+ // These are versions older than IceCat 4 that are not supported
+ // anymore. In this case it's safer to just replace the database.
+ return NS_ERROR_FILE_CORRUPTED;
+ }
+