lists.torproject.org
Sign In Sign Up
Manage this list Sign In Sign Up

Keyboard Shortcuts

Thread View

  • j: Next unread message
  • k: Previous unread message
  • j a: Jump to all threads
  • j l: Jump to MailingList overview

tbb-commits

Thread Start a new thread
Download
Threads by month
  • ----- 2025 -----
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2024 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2023 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2022 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2021 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2020 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2019 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2018 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2017 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2016 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2015 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2014 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
tbb-commits@lists.torproject.org

  • 1 participants
  • 18605 discussions
[tor-browser/tor-browser-38.1.0esr-5.0-1] Bug #15502. Isolate blob, mediasource & mediastream URLs to first party
by mikeperry@torproject.org 28 Jul '15

28 Jul '15
commit f538052047ad61cf74f926381bc7c41b60fa2a3d Author: Arthur Edelstein <arthuredelstein(a)gmail.com> Date: Thu Jul 2 12:56:23 2015 -0700 Bug #15502. Isolate blob, mediasource & mediastream URLs to first party This patch handles blob URLs created and retrieved in Web Workers. See also #15703 and #16429. --- dom/base/ThirdPartyUtil.cpp | 21 ++++++ dom/base/ThirdPartyUtil.h | 12 +++ dom/base/URL.cpp | 32 +++++--- dom/base/moz.build | 1 + dom/base/nsDocument.cpp | 17 ++++- dom/base/nsHostObjectProtocolHandler.cpp | 120 ++++++++++++++++++------------ dom/base/nsHostObjectProtocolHandler.h | 15 ++-- dom/fetch/Fetch.cpp | 17 ++++- dom/fetch/FetchDriver.cpp | 8 +- dom/fetch/FetchDriver.h | 5 +- dom/html/HTMLMediaElement.cpp | 17 ++++- dom/media/MediaResource.cpp | 6 +- dom/workers/URL.cpp | 21 +++++- dom/workers/WorkerPrivate.cpp | 22 +++++- 14 files changed, 232 insertions(+), 82 deletions(-) diff --git a/dom/base/ThirdPartyUtil.cpp b/dom/base/ThirdPartyUtil.cpp index d0aed3a..e8ec06c 100644 --- a/dom/base/ThirdPartyUtil.cpp +++ b/dom/base/ThirdPartyUtil.cpp @@ -33,6 +33,27 @@ static PRLogModuleInfo *gThirdPartyLog; #undef LOG #define LOG(args) PR_LOG(gThirdPartyLog, PR_LOG_DEBUG, args) +// static +mozIThirdPartyUtil* ThirdPartyUtil::gThirdPartyUtilService = nullptr; + +//static +nsresult +ThirdPartyUtil::GetFirstPartyHost(nsIChannel* aChannel, nsIDocument* aDocument, nsACString& aResult) +{ + if (!gThirdPartyUtilService) { + CallGetService(THIRDPARTYUTIL_CONTRACTID, &gThirdPartyUtilService); + } + nsCOMPtr<nsIURI> isolationURI; + nsresult rv = gThirdPartyUtilService->GetFirstPartyIsolationURI(aChannel, aDocument, getter_AddRefs(isolationURI)); + NS_ENSURE_SUCCESS(rv, rv); + if (!isolationURI) { + // Isolation is not active. + aResult.Truncate(); + return NS_OK; + } + return gThirdPartyUtilService->GetFirstPartyHostForIsolation(isolationURI, aResult); +} + nsresult ThirdPartyUtil::Init() { diff --git a/dom/base/ThirdPartyUtil.h b/dom/base/ThirdPartyUtil.h index c03740e..77e73f7 100644 --- a/dom/base/ThirdPartyUtil.h +++ b/dom/base/ThirdPartyUtil.h @@ -24,6 +24,18 @@ public: nsresult Init(); + static mozIThirdPartyUtil* gThirdPartyUtilService; + + static nsresult GetFirstPartyHost(nsIChannel* aChannel, nsIDocument* aDocument, nsACString& aResult); + + static nsresult GetFirstPartyHost(nsIChannel* aChannel, nsACString& aResult) { + return GetFirstPartyHost(aChannel, nullptr, aResult); + } + + static nsresult GetFirstPartyHost(nsIDocument* aDocument, nsACString& aResult) { + return GetFirstPartyHost(nullptr, aDocument, aResult); + } + private: ~ThirdPartyUtil() {} diff --git a/dom/base/URL.cpp b/dom/base/URL.cpp index fea8dd2..1931c28 100644 --- a/dom/base/URL.cpp +++ b/dom/base/URL.cpp @@ -17,6 +17,7 @@ #include "nsNetCID.h" #include "nsNetUtil.h" #include "nsIURL.h" +#include "ThirdPartyUtil.h" namespace mozilla { namespace dom { @@ -152,12 +153,6 @@ URL::CreateObjectURLInternal(const GlobalObject& aGlobal, nsISupports* aObject, nsCOMPtr<nsIPrincipal> principal = nsContentUtils::ObjectPrincipal(aGlobal.Get()); nsCString url; - nsresult rv = nsHostObjectProtocolHandler::AddDataEntry(aScheme, aObject, - principal, url); - if (NS_FAILED(rv)) { - aError.Throw(rv); - return; - } nsCOMPtr<nsPIDOMWindow> w = do_QueryInterface(aGlobal.GetAsSupports()); nsGlobalWindow* window = static_cast<nsGlobalWindow*>(w.get()); @@ -172,6 +167,18 @@ URL::CreateObjectURLInternal(const GlobalObject& aGlobal, nsISupports* aObject, nsIDocument* doc = window->GetExtantDoc(); if (doc) { + nsCString isolationKey; + nsresult rv = ThirdPartyUtil::GetFirstPartyHost(doc, isolationKey); + if (NS_FAILED(rv)) { + aError.Throw(rv); + return; + } + rv = nsHostObjectProtocolHandler::AddDataEntry(aScheme, aObject, + principal, isolationKey, url); + if (NS_FAILED(rv)) { + aError.Throw(rv); + return; + } doc->RegisterHostObjectUri(url); } } @@ -193,10 +200,17 @@ URL::RevokeObjectURL(const GlobalObject& aGlobal, const nsAString& aURL) nsCOMPtr<nsPIDOMWindow> w = do_QueryInterface(aGlobal.GetAsSupports()); nsGlobalWindow* window = static_cast<nsGlobalWindow*>(w.get()); - if (window && window->GetExtantDoc()) { - window->GetExtantDoc()->UnregisterHostObjectUri(asciiurl); + if (window) { + nsCOMPtr<nsIDocument> doc = window->GetExtantDoc(); + if (doc) { + doc->UnregisterHostObjectUri(asciiurl); + nsCString isolationKey; + nsresult rv = ThirdPartyUtil::GetFirstPartyHost(doc, isolationKey); + if (NS_SUCCEEDED(rv)) { + nsHostObjectProtocolHandler::RemoveDataEntry(asciiurl, isolationKey); + } + } } - nsHostObjectProtocolHandler::RemoveDataEntry(asciiurl); } } diff --git a/dom/base/moz.build b/dom/base/moz.build index 27de87b..1d92f94 100644 --- a/dom/base/moz.build +++ b/dom/base/moz.build @@ -194,6 +194,7 @@ EXPORTS.mozilla.dom += [ 'StyleSheetList.h', 'SubtleCrypto.h', 'Text.h', + 'ThirdPartyUtil.h', 'TreeWalker.h', 'URL.h', 'URLSearchParams.h', diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index 47f611e..e5f0a2f2 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -226,6 +226,7 @@ #include "nsLocation.h" #include "mozilla/dom/FontFaceSet.h" #include "mozilla/dom/BoxObject.h" +#include "ThirdPartyUtil.h" #ifdef MOZ_MEDIA_NAVIGATOR #include "mozilla/MediaManager.h" @@ -1776,8 +1777,12 @@ nsDocument::~nsDocument() mPendingTitleChangeEvent.Revoke(); - for (uint32_t i = 0; i < mHostObjectURIs.Length(); ++i) { - nsHostObjectProtocolHandler::RemoveDataEntry(mHostObjectURIs[i]); + nsCString isolationKey; + nsresult rv = ThirdPartyUtil::GetFirstPartyHost(this, isolationKey); + if (NS_SUCCEEDED(rv)) { + for (uint32_t i = 0; i < mHostObjectURIs.Length(); ++i) { + nsHostObjectProtocolHandler::RemoveDataEntry(mHostObjectURIs[i], isolationKey); + } } // We don't want to leave residual locks on images. Make sure we're in an @@ -2156,8 +2161,12 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument) NS_IMPL_CYCLE_COLLECTION_UNLINK(mCSSLoader) } - for (uint32_t i = 0; i < tmp->mHostObjectURIs.Length(); ++i) { - nsHostObjectProtocolHandler::RemoveDataEntry(tmp->mHostObjectURIs[i]); + nsCString isolationKey; + nsresult rv = ThirdPartyUtil::GetFirstPartyHost(tmp, isolationKey); + if (NS_SUCCEEDED(rv)) { + for (uint32_t i = 0; i < tmp->mHostObjectURIs.Length(); ++i) { + nsHostObjectProtocolHandler::RemoveDataEntry(tmp->mHostObjectURIs[i], isolationKey); + } } // We own only the items in mDOMMediaQueryLists that have listeners; diff --git a/dom/base/nsHostObjectProtocolHandler.cpp b/dom/base/nsHostObjectProtocolHandler.cpp index aac33f9..429938b 100644 --- a/dom/base/nsHostObjectProtocolHandler.cpp +++ b/dom/base/nsHostObjectProtocolHandler.cpp @@ -16,6 +16,7 @@ #include "mozilla/dom/File.h" #include "mozilla/Preferences.h" #include "mozilla/LoadInfo.h" +#include "ThirdPartyUtil.h" using mozilla::dom::FileImpl; using mozilla::ErrorResult; @@ -29,6 +30,7 @@ struct DataInfo nsCOMPtr<nsISupports> mObject; nsCOMPtr<nsIPrincipal> mPrincipal; nsCString mStack; + nsCString mFirstPartyHost; }; static nsClassHashtable<nsCStringHashKey, DataInfo>* gDataTable; @@ -298,6 +300,7 @@ nsresult nsHostObjectProtocolHandler::AddDataEntry(const nsACString& aScheme, nsISupports* aObject, nsIPrincipal* aPrincipal, + const nsACString& aIsolationKey, nsACString& aUri) { Init(); @@ -313,28 +316,55 @@ nsHostObjectProtocolHandler::AddDataEntry(const nsACString& aScheme, info->mObject = aObject; info->mPrincipal = aPrincipal; + // Record the first party host that originated this object. + info->mFirstPartyHost = aIsolationKey; mozilla::BlobURLsReporter::GetJSStackForBlob(info); gDataTable->Put(aUri, info); return NS_OK; } +static DataInfo* +GetDataInfo(const nsACString& aUri) +{ + if (!gDataTable) { + return nullptr; + } + + DataInfo* res; + nsCString uriIgnoringRef; + int32_t hashPos = aUri.FindChar('#'); + if (hashPos < 0) { + uriIgnoringRef = aUri; + } + else { + uriIgnoringRef = StringHead(aUri, hashPos); + } + gDataTable->Get(uriIgnoringRef, &res); + + return res; +} + void -nsHostObjectProtocolHandler::RemoveDataEntry(const nsACString& aUri) +nsHostObjectProtocolHandler::RemoveDataEntry(const nsACString& aUri, + const nsACString& aIsolationKey) { if (gDataTable) { - nsCString uriIgnoringRef; - int32_t hashPos = aUri.FindChar('#'); - if (hashPos < 0) { - uriIgnoringRef = aUri; - } - else { - uriIgnoringRef = StringHead(aUri, hashPos); - } - gDataTable->Remove(uriIgnoringRef); - if (gDataTable->Count() == 0) { - delete gDataTable; - gDataTable = nullptr; + DataInfo* info = GetDataInfo(aUri); + if (info->mFirstPartyHost == aIsolationKey) { + nsCString uriIgnoringRef; + int32_t hashPos = aUri.FindChar('#'); + if (hashPos < 0) { + uriIgnoringRef = aUri; + } + else { + uriIgnoringRef = StringHead(aUri, hashPos); + } + gDataTable->Remove(uriIgnoringRef); + if (gDataTable->Count() == 0) { + delete gDataTable; + gDataTable = nullptr; + } } } } @@ -375,27 +405,6 @@ nsHostObjectProtocolHandler::GenerateURIString(const nsACString &aScheme, return NS_OK; } -static DataInfo* -GetDataInfo(const nsACString& aUri) -{ - if (!gDataTable) { - return nullptr; - } - - DataInfo* res; - nsCString uriIgnoringRef; - int32_t hashPos = aUri.FindChar('#'); - if (hashPos < 0) { - uriIgnoringRef = aUri; - } - else { - uriIgnoringRef = StringHead(aUri, hashPos); - } - gDataTable->Get(uriIgnoringRef, &res); - - return res; -} - nsIPrincipal* nsHostObjectProtocolHandler::GetDataEntryPrincipal(const nsACString& aUri) { @@ -431,13 +440,16 @@ nsHostObjectProtocolHandler::Traverse(const nsACString& aUri, } static nsISupports* -GetDataObject(nsIURI* aURI) +GetDataObject(nsIURI* aURI, const nsACString& aIsolationKey) { nsCString spec; aURI->GetSpec(spec); DataInfo* info = GetDataInfo(spec); - return info ? info->mObject : nullptr; + // Deny access to this object if the current first-party host + // doesn't match the originating first-party host. + return (info && info->mFirstPartyHost == aIsolationKey) + ? info->mObject : nullptr; } // ----------------------------------------------------------------------- @@ -493,9 +505,19 @@ nsHostObjectProtocolHandler::NewChannel2(nsIURI* uri, nsCString spec; uri->GetSpec(spec); - DataInfo* info = GetDataInfo(spec); + nsCString firstPartyHost; + if (aLoadInfo) { + nsCOMPtr<nsIDOMDocument> loadingDOMDocument; + aLoadInfo->GetLoadingDocument(getter_AddRefs(loadingDOMDocument)); + nsCOMPtr<nsIDocument> loadingDocument = do_QueryInterface(loadingDOMDocument); + nsresult rv = ThirdPartyUtil::GetFirstPartyHost(loadingDocument, firstPartyHost); + NS_ENSURE_SUCCESS(rv, rv); + } - if (!info) { + DataInfo* info = GetDataInfo(spec); + // Deny access to this URI if the current first party host + // doesn't match the first party host when it was created. + if (!info || (info->mFirstPartyHost != firstPartyHost)) { return NS_ERROR_DOM_BAD_URI; } @@ -594,13 +616,13 @@ nsFontTableProtocolHandler::GetScheme(nsACString &result) } nsresult -NS_GetBlobForBlobURI(nsIURI* aURI, FileImpl** aBlob) +NS_GetBlobForBlobURI(nsIURI* aURI, const nsACString& aIsolationKey, FileImpl** aBlob) { NS_ASSERTION(IsBlobURI(aURI), "Only call this with blob URIs"); *aBlob = nullptr; - nsCOMPtr<FileImpl> blob = do_QueryInterface(GetDataObject(aURI)); + nsCOMPtr<FileImpl> blob = do_QueryInterface(GetDataObject(aURI, aIsolationKey)); if (!blob) { return NS_ERROR_DOM_BAD_URI; } @@ -610,10 +632,12 @@ NS_GetBlobForBlobURI(nsIURI* aURI, FileImpl** aBlob) } nsresult -NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream) +NS_GetStreamForBlobURI(nsIURI* aURI, + const nsACString& aIsolationKey, + nsIInputStream** aStream) { nsRefPtr<FileImpl> blobImpl; - nsresult rv = NS_GetBlobForBlobURI(aURI, getter_AddRefs(blobImpl)); + nsresult rv = NS_GetBlobForBlobURI(aURI, aIsolationKey, getter_AddRefs(blobImpl)); if (NS_FAILED(rv)) { return rv; } @@ -622,11 +646,13 @@ NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream) } nsresult -NS_GetStreamForMediaStreamURI(nsIURI* aURI, mozilla::DOMMediaStream** aStream) +NS_GetStreamForMediaStreamURI(nsIURI* aURI, + const nsACString& aIsolationKey, + mozilla::DOMMediaStream** aStream) { NS_ASSERTION(IsMediaStreamURI(aURI), "Only call this with mediastream URIs"); - nsISupports* dataObject = GetDataObject(aURI); + nsISupports* dataObject = GetDataObject(aURI, aIsolationKey); if (!dataObject) { return NS_ERROR_DOM_BAD_URI; } @@ -669,13 +695,15 @@ nsFontTableProtocolHandler::NewURI(const nsACString& aSpec, } nsresult -NS_GetSourceForMediaSourceURI(nsIURI* aURI, mozilla::dom::MediaSource** aSource) +NS_GetSourceForMediaSourceURI(nsIURI* aURI, + const nsACString& aIsolationKey, + mozilla::dom::MediaSource** aSource) { NS_ASSERTION(IsMediaSourceURI(aURI), "Only call this with mediasource URIs"); *aSource = nullptr; - nsCOMPtr<mozilla::dom::MediaSource> source = do_QueryInterface(GetDataObject(aURI)); + nsCOMPtr<mozilla::dom::MediaSource> source = do_QueryInterface(GetDataObject(aURI, aIsolationKey)); if (!source) { return NS_ERROR_DOM_BAD_URI; } diff --git a/dom/base/nsHostObjectProtocolHandler.h b/dom/base/nsHostObjectProtocolHandler.h index 977e5e0..e335886 100644 --- a/dom/base/nsHostObjectProtocolHandler.h +++ b/dom/base/nsHostObjectProtocolHandler.h @@ -53,8 +53,9 @@ public: static nsresult AddDataEntry(const nsACString& aScheme, nsISupports* aObject, nsIPrincipal* aPrincipal, + const nsACString& aIsolationKey, nsACString& aUri); - static void RemoveDataEntry(const nsACString& aUri); + static void RemoveDataEntry(const nsACString& aUri, const nsACString& aIsolationKey); static nsIPrincipal* GetDataEntryPrincipal(const nsACString& aUri); static void Traverse(const nsACString& aUri, nsCycleCollectionTraversalCallback& aCallback); @@ -121,16 +122,20 @@ inline bool IsFontTableURI(nsIURI* aUri) } extern nsresult -NS_GetBlobForBlobURI(nsIURI* aURI, mozilla::dom::FileImpl** aBlob); +NS_GetBlobForBlobURI(nsIURI* aURI, const nsACString& aIsolationKey, + mozilla::dom::FileImpl** aBlob); extern nsresult -NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream); +NS_GetStreamForBlobURI(nsIURI* aURI, const nsACString& aIsolationKey, + nsIInputStream** aStream); extern nsresult -NS_GetStreamForMediaStreamURI(nsIURI* aURI, mozilla::DOMMediaStream** aStream); +NS_GetStreamForMediaStreamURI(nsIURI* aURI, const nsACString& aIsolationKey, + mozilla::DOMMediaStream** aStream); extern nsresult -NS_GetSourceForMediaSourceURI(nsIURI* aURI, mozilla::dom::MediaSource** aSource); +NS_GetSourceForMediaSourceURI(nsIURI* aURI, const nsACString& aIsolationKey, + mozilla::dom::MediaSource** aSource); #define NS_BLOBPROTOCOLHANDLER_CID \ { 0xb43964aa, 0xa078, 0x44b2, \ diff --git a/dom/fetch/Fetch.cpp b/dom/fetch/Fetch.cpp index b84393e..9a53555 100644 --- a/dom/fetch/Fetch.cpp +++ b/dom/fetch/Fetch.cpp @@ -27,6 +27,7 @@ #include "mozilla/dom/Request.h" #include "mozilla/dom/Response.h" #include "mozilla/dom/ScriptSettings.h" +#include "mozilla/dom/ThirdPartyUtil.h" #include "mozilla/dom/URLSearchParams.h" #include "InternalRequest.h" @@ -174,13 +175,18 @@ public: nsCOMPtr<nsIPrincipal> principal = mResolver->GetWorkerPrivate()->GetPrincipal(); nsCOMPtr<nsILoadGroup> loadGroup = mResolver->GetWorkerPrivate()->GetLoadGroup(); - nsRefPtr<FetchDriver> fetch = new FetchDriver(mRequest, principal, loadGroup); nsIDocument* doc = mResolver->GetWorkerPrivate()->GetDocument(); + nsCString isolationKey; + nsresult rv = ThirdPartyUtil::GetFirstPartyHost(doc, isolationKey); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + nsRefPtr<FetchDriver> fetch = new FetchDriver(mRequest, principal, isolationKey, loadGroup); if (doc) { fetch->SetReferrerPolicy(doc->GetReferrerPolicy()); } - nsresult rv = fetch->Fetch(mResolver); + rv = fetch->Fetch(mResolver); // Right now we only support async fetch, which should never directly fail. if (NS_WARN_IF(NS_FAILED(rv))) { return rv; @@ -230,10 +236,15 @@ FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput, return nullptr; } + nsCString isolationKey; + nsresult rv = ThirdPartyUtil::GetFirstPartyHost(doc, isolationKey); + if (NS_WARN_IF(NS_FAILED(rv))) { + return nullptr; + } nsRefPtr<MainThreadFetchResolver> resolver = new MainThreadFetchResolver(p); nsCOMPtr<nsILoadGroup> loadGroup = doc->GetDocumentLoadGroup(); nsRefPtr<FetchDriver> fetch = - new FetchDriver(r, doc->NodePrincipal(), loadGroup); + new FetchDriver(r, doc->NodePrincipal(), isolationKey, loadGroup); fetch->SetReferrerPolicy(doc->GetReferrerPolicy()); aRv = fetch->Fetch(resolver); if (NS_WARN_IF(aRv.Failed())) { diff --git a/dom/fetch/FetchDriver.cpp b/dom/fetch/FetchDriver.cpp index ad54daf..b57141c 100644 --- a/dom/fetch/FetchDriver.cpp +++ b/dom/fetch/FetchDriver.cpp @@ -28,6 +28,7 @@ #include "Fetch.h" #include "InternalRequest.h" #include "InternalResponse.h" +#include "mozilla/dom/ThirdPartyUtil.h" namespace mozilla { namespace dom { @@ -36,9 +37,12 @@ NS_IMPL_ISUPPORTS(FetchDriver, nsIStreamListener, nsIChannelEventSink, nsIInterfaceRequestor, nsIAsyncVerifyRedirectCallback) -FetchDriver::FetchDriver(InternalRequest* aRequest, nsIPrincipal* aPrincipal, +FetchDriver::FetchDriver(InternalRequest* aRequest, + nsIPrincipal* aPrincipal, + const nsACString& aIsolationKey, nsILoadGroup* aLoadGroup) : mPrincipal(aPrincipal) + , mIsolationKey(aIsolationKey) , mLoadGroup(aLoadGroup) , mRequest(aRequest) , mFetchRecursionCount(0) @@ -187,7 +191,7 @@ FetchDriver::BasicFetch() if (scheme.LowerCaseEqualsLiteral("blob")) { nsRefPtr<FileImpl> blobImpl; - rv = NS_GetBlobForBlobURI(uri, getter_AddRefs(blobImpl)); + rv = NS_GetBlobForBlobURI(uri, mIsolationKey, getter_AddRefs(blobImpl)); FileImpl* blob = static_cast<FileImpl*>(blobImpl.get()); if (NS_WARN_IF(NS_FAILED(rv))) { FailWithNetworkError(); diff --git a/dom/fetch/FetchDriver.h b/dom/fetch/FetchDriver.h index d58224209..c835149 100644 --- a/dom/fetch/FetchDriver.h +++ b/dom/fetch/FetchDriver.h @@ -53,7 +53,9 @@ public: NS_DECL_NSIINTERFACEREQUESTOR NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK - explicit FetchDriver(InternalRequest* aRequest, nsIPrincipal* aPrincipal, + explicit FetchDriver(InternalRequest* aRequest, + nsIPrincipal* aPrincipal, + const nsACString& isolationKey, nsILoadGroup* aLoadGroup); NS_IMETHOD Fetch(FetchDriverObserver* aObserver); @@ -67,6 +69,7 @@ public: private: nsCOMPtr<nsIPrincipal> mPrincipal; + nsAutoCString mIsolationKey; nsCOMPtr<nsILoadGroup> mLoadGroup; nsRefPtr<InternalRequest> mRequest; nsRefPtr<InternalResponse> mResponse; diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp index 41a1505..d80cfff 100644 --- a/dom/html/HTMLMediaElement.cpp +++ b/dom/html/HTMLMediaElement.cpp @@ -90,6 +90,7 @@ #include "ImageContainer.h" #include "nsRange.h" #include <algorithm> +#include "ThirdPartyUtil.h" #ifdef PR_LOGGING static PRLogModuleInfo* gMediaElementLog; @@ -521,7 +522,11 @@ HTMLMediaElement::GetMozMediaSourceObject() const { nsRefPtr<MediaSource> source; if (mLoadingSrc && IsMediaSourceURI(mLoadingSrc)) { - NS_GetSourceForMediaSourceURI(mLoadingSrc, getter_AddRefs(source)); + nsCString isolationKey; + nsresult rv = ThirdPartyUtil::GetFirstPartyHost(GetOwnerDocument(), isolationKey); + if (NS_SUCCEEDED(rv)) { + NS_GetSourceForMediaSourceURI(mLoadingSrc, isolationKey, getter_AddRefs(source)); + } } return source.forget(); } @@ -1191,7 +1196,10 @@ nsresult HTMLMediaElement::LoadResource() if (IsMediaStreamURI(mLoadingSrc)) { nsRefPtr<DOMMediaStream> stream; - rv = NS_GetStreamForMediaStreamURI(mLoadingSrc, getter_AddRefs(stream)); + nsCString isolationKey; + rv = ThirdPartyUtil::GetFirstPartyHost(GetOwnerDocument(), isolationKey); + NS_ENSURE_SUCCESS(rv, rv); + rv = NS_GetStreamForMediaStreamURI(mLoadingSrc, isolationKey, getter_AddRefs(stream)); if (NS_FAILED(rv)) { nsCString specUTF8; mLoadingSrc->GetSpec(specUTF8); @@ -1206,7 +1214,10 @@ nsresult HTMLMediaElement::LoadResource() if (IsMediaSourceURI(mLoadingSrc)) { nsRefPtr<MediaSource> source; - rv = NS_GetSourceForMediaSourceURI(mLoadingSrc, getter_AddRefs(source)); + nsCString isolationKey; + rv = ThirdPartyUtil::GetFirstPartyHost(GetOwnerDocument(), isolationKey); + NS_ENSURE_SUCCESS(rv, rv); + rv = NS_GetSourceForMediaSourceURI(mLoadingSrc, isolationKey, getter_AddRefs(source)); if (NS_FAILED(rv)) { nsCString specUTF8; mLoadingSrc->GetSpec(specUTF8); diff --git a/dom/media/MediaResource.cpp b/dom/media/MediaResource.cpp index 956776c..618b10a 100644 --- a/dom/media/MediaResource.cpp +++ b/dom/media/MediaResource.cpp @@ -32,6 +32,7 @@ #include <algorithm> #include "nsProxyRelease.h" #include "nsIContentPolicy.h" +#include "mozilla/dom/ThirdPartyUtil.h" #ifdef PR_LOGGING PRLogModuleInfo* gMediaResourceLog; @@ -1365,7 +1366,10 @@ nsresult FileMediaResource::Open(nsIStreamListener** aStreamListener) rv = NS_NewLocalFileInputStream(getter_AddRefs(mInput), file); } else if (IsBlobURI(mURI)) { - rv = NS_GetStreamForBlobURI(mURI, getter_AddRefs(mInput)); + nsCString isolationKey; + rv = ThirdPartyUtil::GetFirstPartyHost(mChannel, isolationKey); + NS_ENSURE_SUCCESS(rv, rv); + rv = NS_GetStreamForBlobURI(mURI, isolationKey, getter_AddRefs(mInput)); } } else { // Ensure that we never load a local file from some page on a diff --git a/dom/workers/URL.cpp b/dom/workers/URL.cpp index fbf6987..1eda4fd 100644 --- a/dom/workers/URL.cpp +++ b/dom/workers/URL.cpp @@ -24,6 +24,7 @@ #include "WorkerPrivate.h" #include "WorkerRunnable.h" +#include "ThirdPartyUtil.h" BEGIN_WORKERS_NAMESPACE using mozilla::dom::GlobalObject; @@ -140,10 +141,17 @@ public: principal = mWorkerPrivate->GetPrincipal(); } + nsCString firstPartyHost; + nsresult rv = ThirdPartyUtil::GetFirstPartyHost(doc, firstPartyHost); + if (NS_FAILED(rv)) { + NS_WARNING("Isolation failed; blob URL creation denied."); + return false; + } + nsCString url; - nsresult rv = nsHostObjectProtocolHandler::AddDataEntry( + rv = nsHostObjectProtocolHandler::AddDataEntry( NS_LITERAL_CSTRING(BLOBURI_SCHEME), - mBlobImpl, principal, url); + mBlobImpl, principal, firstPartyHost, url); if (NS_FAILED(rv)) { NS_WARNING("Failed to add data entry for the blob!"); @@ -209,8 +217,13 @@ public: if (doc) { doc->UnregisterHostObjectUri(url); } - - nsHostObjectProtocolHandler::RemoveDataEntry(url); + nsCString isolationKey; + nsresult rv = ThirdPartyUtil::GetFirstPartyHost(doc, isolationKey); + if (NS_FAILED(rv)) { + NS_WARNING("Isolation failed; blob removal denied."); + return false; + } + nsHostObjectProtocolHandler::RemoveDataEntry(url, isolationKey); } if (!window) { diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index 0d4702d..d998471 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -99,6 +99,7 @@ #include "WorkerRunnable.h" #include "WorkerScope.h" #include "WorkerThread.h" +#include "ThirdPartyUtil.h" #ifdef XP_WIN #undef PostMessage @@ -708,14 +709,17 @@ class MainThreadReleaseRunnable final : public nsRunnable nsTArray<nsCOMPtr<nsISupports>> mDoomed; nsTArray<nsCString> mHostObjectURIs; nsCOMPtr<nsILoadGroup> mLoadGroupToCancel; + nsRefPtr<WorkerPrivate> mWorkerPrivate; public: MainThreadReleaseRunnable(nsTArray<nsCOMPtr<nsISupports>>& aDoomed, nsTArray<nsCString>& aHostObjectURIs, + WorkerPrivate* aWorkerPrivate, nsCOMPtr<nsILoadGroup>& aLoadGroupToCancel) { mDoomed.SwapElements(aDoomed); mHostObjectURIs.SwapElements(aHostObjectURIs); + mWorkerPrivate = aWorkerPrivate; mLoadGroupToCancel.swap(aLoadGroupToCancel); } @@ -731,8 +735,17 @@ public: mDoomed.Clear(); - for (uint32_t index = 0; index < mHostObjectURIs.Length(); index++) { - nsHostObjectProtocolHandler::RemoveDataEntry(mHostObjectURIs[index]); + nsCOMPtr<nsIDocument> doc; + nsCOMPtr<nsPIDOMWindow> window = mWorkerPrivate->GetWindow(); + if (window) { + doc = window->GetExtantDoc(); + } + nsCString isolationKey; + nsresult rv = ThirdPartyUtil::GetFirstPartyHost(doc, isolationKey); + if (NS_SUCCEEDED(rv)) { + for (uint32_t index = 0; index < mHostObjectURIs.Length(); index++) { + nsHostObjectProtocolHandler::RemoveDataEntry(mHostObjectURIs[index], isolationKey); + } } return NS_OK; @@ -782,7 +795,8 @@ private: mFinishedWorker->StealHostObjectURIs(hostObjectURIs); nsRefPtr<MainThreadReleaseRunnable> runnable = - new MainThreadReleaseRunnable(doomed, hostObjectURIs, loadGroupToCancel); + new MainThreadReleaseRunnable(doomed, hostObjectURIs, + aWorkerPrivate, loadGroupToCancel); if (NS_FAILED(NS_DispatchToMainThread(runnable))) { NS_WARNING("Failed to dispatch, going to leak!"); } @@ -840,7 +854,7 @@ private: mFinishedWorker->StealHostObjectURIs(hostObjectURIs); nsRefPtr<MainThreadReleaseRunnable> runnable = - new MainThreadReleaseRunnable(doomed, hostObjectURIs, loadGroupToCancel); + new MainThreadReleaseRunnable(doomed, hostObjectURIs, mFinishedWorker, loadGroupToCancel); if (NS_FAILED(NS_DispatchToCurrentThread(runnable))) { NS_WARNING("Failed to dispatch, going to leak!"); }
1 0
0 0
[tor-browser/tor-browser-38.1.0esr-5.0-1] Bug #15703: Regression tests for isolation of mediasource URI
by mikeperry@torproject.org 28 Jul '15

28 Jul '15
commit 2ae052be0e0cdcba4df89607002233ad3d1e6f11 Author: Arthur Edelstein <arthuredelstein(a)gmail.com> Date: Thu Jul 2 16:28:36 2015 -0700 Bug #15703: Regression tests for isolation of mediasource URI --- dom/base/test/bug15703_page_create.html | 28 +++++++++ dom/base/test/bug15703_page_retrieve.html | 50 ++++++++++++++++ dom/base/test/mochitest.ini | 3 + dom/base/test/test_tor_bug15703.html | 92 +++++++++++++++++++++++++++++ 4 files changed, 173 insertions(+) diff --git a/dom/base/test/bug15703_page_create.html b/dom/base/test/bug15703_page_create.html new file mode 100644 index 0000000..2325e6f --- /dev/null +++ b/dom/base/test/bug15703_page_create.html @@ -0,0 +1,28 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugs.torproject.org/15703 +--> +<head> + <meta http-equiv="content-type" content="text/html; charset=utf-8"> + <title>Page mediasource URI creator for Tor Browser Bug 15703</title> + <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script> + <script type="text/javascript;version=1.7" src="bug15502_utils.js"></script> +</head> +<body> +<div id="display" style="white-space:pre; font-family:monospace; display:inline;"></div> + +<script type="text/javascript;version=1.7"> + +spawnTask(function* () { + sendMessage(window.parent, "ready"); + let message = yield receiveMessage(window.parent), + mediaSource = new MediaSource(), + mediaSourceURL = URL.createObjectURL(mediaSource); + sendMessage(window.parent, mediaSourceURL); + appendLine("display", message + " -> " + mediaSourceURL); +}); + +</script> +</body> +</html> diff --git a/dom/base/test/bug15703_page_retrieve.html b/dom/base/test/bug15703_page_retrieve.html new file mode 100644 index 0000000..de3e14f --- /dev/null +++ b/dom/base/test/bug15703_page_retrieve.html @@ -0,0 +1,50 @@ + +<!DOCTYPE HTML> +<html> +<!-- +https://bugs.torproject.org/15502 +--> +<head> + <meta http-equiv="content-type" content="text/html; charset=utf-8"> + <title>Page mediaSource retriever for Tor Browser Bug 15703</title> + <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script> + <script type="text/javascript;version=1.7" src="bug15502_utils.js"></script> +</head> +<body> +<div id="display" style="white-space:pre; font-family:monospace; display:inline;"></div> +<video id="testvideo"></video> +<script type="text/javascript;version=1.7"> + +let reportResult = function(mediaSourceURL, message) { + sendMessage(window.parent, message); + appendLine("display", mediaSourceURL + " -> " + message); +}; + +spawnTask(function* () { + // Tell the parent tab we are ready to start. + sendMessage(window.parent, "ready"); + // Receive a mediaSourceURL. In a moment, we will + // use a video element to attempt to implicitly load + // the MediaSource object at this URL. + let mediaSourceURL = yield receiveMessage(window.parent); + // First create the video element. + let videoElement = document.getElementById("testvideo"); + // If we are not able to load a MediaSource object + // at mediaSourceURL, then an error event will occur. + videoElement.addEventListener("error", function (e) { + reportResult(mediaSourceURL, "setting videoElement.src failed"); + }); + // If we do find a MediaSource object at mediaSourceURL, + // then a "stalled" event will occur, because the object + // has been found, but contains no content. + videoElement.addEventListener("stalled", function (e) { + reportResult(mediaSourceURL, "retrieved"); + }); + // Now attempt to load a MediaSource object by setting + // the video element's src to mediaSourceURL. + videoElement.src = mediaSourceURL; +}); + +</script> +</body> +</html> diff --git a/dom/base/test/mochitest.ini b/dom/base/test/mochitest.ini index dc5dfef..133348e 100644 --- a/dom/base/test/mochitest.ini +++ b/dom/base/test/mochitest.ini @@ -31,6 +31,8 @@ support-files = bug15502_worker_blobify.html bug15502_worker_deblobify.js bug15502_worker_deblobify.html + bug15703_page_create.html + bug15703_page_retrieve.html bug282547.sjs bug298064-subframe.html bug313646.txt @@ -736,6 +738,7 @@ skip-if = toolkit == 'android' || e10s #RANDOM [test_textnode_split_in_selection.html] [test_title.html] [test_tor_bug15502.html] +[test_tor_bug15703.html] [test_treewalker_nextsibling.xml] [test_viewport_scroll.html] [test_viewsource_forbidden_in_object.html] diff --git a/dom/base/test/test_tor_bug15703.html b/dom/base/test/test_tor_bug15703.html new file mode 100644 index 0000000..a0d3ae1 --- /dev/null +++ b/dom/base/test/test_tor_bug15703.html @@ -0,0 +1,92 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugs.torproject.org/15703 +--> +<head> + <meta http-equiv="content-type" content="text/html; charset=utf-8"> + <title>Test for Tor Browser Bug 15703</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script> + <script type="text/javascript;version=1.7" src="bug15502_utils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<p id="display"></p> +<div id="content"></div> + +<script class="testbody" type="application/javascript;version=1.7"> +SimpleTest.waitForExplicitFinish(); + +// __setPref(key, value)__. +// Set a pref value asynchronously, returning a prmoise that resolves +// when it succeeds. +let setPref = function* (key, value) { + return new Promise(function(resolve, reject) { + SpecialPowers.pushPrefEnv({"set": [[key, value]]}, resolve); + }); +}; + +// ## Testing constants +let domain1 = "http://example.com", + domain2 = "http://example.net", + path = "/tests/dom/base/test/", + page_create = "bug15703_page_create.html", + page_retrieve = "bug15703_page_retrieve.html" + worker_create = "bug15703_worker_create.html", + worker_retrieve = "bug15703_worker_retrieve.html"; + +// __tabIO(domain, child, input)__. +// Open a tab at the given `domain` and `child` page. Post an +// `input` message to the tab. +let tabIO = function* (domain, child, input) { + tab = window.open(domain + path + "bug15502_tab.html", "_blank"); + yield receiveMessage(tab); // ready message + sendMessage(tab, "http://example.org" + path + child); + yield receiveMessage(tab); // ready message + sendMessage(tab, input); + return yield receiveMessage(tab); +}; + +// __mediaSourceTest(isolationOn, domainA, domainB, createPage, retrievePage)__. +// Run a test where we set the pref "privacy.thirdparty.isolate" to on or off, +// and then create a media source in `domainA`, using the page `createPage`, +// and then attempt to retrive a media source in `domainB`, using +// the page `retrievePage`. +let mediaSourceTest = function* (isolationOn, domainA, domainB, createPage, retrievePage) { + yield setPref("privacy.thirdparty.isolate", isolationOn ? 2 : 0); + let input = "create", + mediaSourceURL = yield tabIO(domainA, createPage, input), + result = yield tabIO(domainB, retrievePage, mediaSourceURL), + description = domainA + ":" + createPage + "->" + domainB + ":" + retrievePage + ", isolation " + (isolationOn ? "on." : "off."); + if (isolationOn && domainA !== domainB) { + ok(result !== "retrieved", description + " Deny retrieval"); + } else { + ok(result === "retrieved", description + " Allow retrieval"); + } +}; + + +// ## The main test +// Run a Task.jsm coroutine that tests various combinations of domains +// methods, and isolation states for reading and writing mediasource URLs. +spawnTask(function* () { + yield setPref("media.mediasource.whitelist", false); + for (let isolate of [false, true]) { + for (let domainB of [domain1, domain2]) { + // There doesn't appear to be a way to create a MediaSource object in a worker. + for (let create of [page_create, /* worker_create */]) { + // No way I could find to retrieve a MediaSource object in a worker. + for (let retrieve of [page_retrieve, /* worker_retrieve */]) { + yield mediaSourceTest(isolate, domain1, domainB, create, retrieve); + } + } + } + } + SimpleTest.finish(); +}); + +</script> + +</body> +</html>
1 0
0 0
[tor-browser/tor-browser-38.1.0esr-5.0-1] fixup! Bug #15502, Part 2: Regression tests for blob URL isolation
by mikeperry@torproject.org 28 Jul '15

28 Jul '15
commit 4ef8f72964d1608a9ded427137d66547f78d71b8 Author: Arthur Edelstein <arthuredelstein(a)gmail.com> Date: Thu Jul 2 12:26:40 2015 -0700 fixup! Bug #15502, Part 2: Regression tests for blob URL isolation --- dom/base/test/test_tor_bug15502.html | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/dom/base/test/test_tor_bug15502.html b/dom/base/test/test_tor_bug15502.html index 18b8459..05173d9 100644 --- a/dom/base/test/test_tor_bug15502.html +++ b/dom/base/test/test_tor_bug15502.html @@ -59,20 +59,10 @@ let blobTest = function* (isolationOn, domainA, domainB, blobPage, deblobPage) { blobURL = yield tabIO(domainA, blobPage, input), result = yield tabIO(domainB, deblobPage, blobURL), description = domainA + ":" + blobPage + "->" + domainB + ":" + deblobPage + ", isolation " + (isolationOn ? "on." : "off."); - if (blobPage === worker_blob) { - // Remove this case when we write a patch that properly isolates web worker blob URLs - // by first party domain. - ok(blobURL.contains("Permission to call 'URL.createObjectURL' denied."), description + " Deny blob URL creation in web worker"); - } else if (deblobPage === worker_deblob && isolationOn) { - // Remove this case when we write a patch that properly isolates web worker blob URLs - // by first party domain. - ok(result.contains("Access to restricted URI denied"), description + " Isolated blobs not available to web workers"); + if (isolationOn && domainA !== domainB) { + ok(input !== result, description + " Deny retrieval"); } else { - if (isolationOn && domainA !== domainB) { - ok(input !== result, description + " Deny retrieval"); - } else { - ok(input === result, description + " Allow retrieval"); - } + ok(input === result, description + " Allow retrieval"); } };
1 0
0 0
[tor-browser/tor-browser-38.1.0esr-5.0-1] Bug 1078657 - Add SpawnTask.js for async tasks in mochitests. r=jmaher
by mikeperry@torproject.org 28 Jul '15

28 Jul '15
commit 6bc7fec8c4381a2ed4112ab9c43a6b243c6a0dd5 Author: Arthur Edelstein <arthuredelstein(a)gmail.com> Date: Fri Jul 17 12:37:24 2015 -0400 Bug 1078657 - Add SpawnTask.js for async tasks in mochitests. r=jmaher --- testing/mochitest/chrome/chrome.ini | 1 + testing/mochitest/chrome/test_sanitySpawnTask.xul | 70 ++++++ testing/mochitest/jar.mn | 1 + .../mochitest/tests/Harness_sanity/mochitest.ini | 2 +- .../tests/Harness_sanity/test_spawn_task.html | 73 ++++++ .../mochitest/tests/SimpleTest/LICENSE_SpawnTask | 24 ++ testing/mochitest/tests/SimpleTest/SpawnTask.js | 244 ++++++++++++++++++++ testing/mochitest/tests/SimpleTest/moz.build | 1 + 8 files changed, 415 insertions(+), 1 deletion(-) diff --git a/testing/mochitest/chrome/chrome.ini b/testing/mochitest/chrome/chrome.ini index ecd3911..a5ed449 100644 --- a/testing/mochitest/chrome/chrome.ini +++ b/testing/mochitest/chrome/chrome.ini @@ -12,4 +12,5 @@ skip-if = buildapp == 'mulet' fail-if = true [test_sanityManifest_pf.xul] fail-if = true +[test_sanitySpawnTask.xul] [test_chromeGetTestFile.xul] diff --git a/testing/mochitest/chrome/test_sanitySpawnTask.xul b/testing/mochitest/chrome/test_sanitySpawnTask.xul new file mode 100644 index 0000000..c26b761 --- /dev/null +++ b/testing/mochitest/chrome/test_sanitySpawnTask.xul @@ -0,0 +1,70 @@ +<?xml version="1.0"?> +<!-- 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/. --> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<window title="Test spawnTawk function" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script type="application/javascript" + src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + <script type="application/javascript" + src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"/> + <script type="application/javascript"> + <![CDATA[ + SimpleTest.waitForExplicitFinish(); + + var externalGeneratorFunction = function* () { + return 8; + }; + + var nestedFunction = function* () { + return yield function* () { + return yield function* () { + return yield function* () { + return yield Promise.resolve(9); + }(); + }(); + }(); + } + + var variousTests = function* () { + var val1 = yield [Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)]; + is(val1.join(""), "123", "Array of promises -> Promise.all"); + var val2 = yield Promise.resolve(2); + is(val2, 2, "Resolved promise yields value."); + var val3 = yield function* () { return 3; }; + is(val3, 3, "Generator functions are spawned."); + //var val4 = yield function () { return 4; }; + //is(val4, 4, "Plain functions run and return."); + var val5 = yield (function* () { return 5; }()); + is(val5, 5, "Generators are spawned."); + try { + var val6 = yield Promise.reject(Error("error6")); + ok(false, "Shouldn't reach this line."); + } catch (error) { + is(error.message, "error6", "Rejected promise throws error."); + } + try { + var val7 = yield function* () { throw Error("error7"); }; + ok(false, "Shouldn't reach this line."); + } catch (error) { + is(error.message, "error7", "Thrown error propagates."); + } + var val8 = yield externalGeneratorFunction(); + is(val8, 8, "External generator also spawned."); + var val9 = yield nestedFunction(); + is(val9, 9, "Nested generator functions work."); + return 10; + }; + + spawnTask(variousTests).then(function(result) { + is(result, 10, "spawnTask(...) returns promise"); + SimpleTest.finish(); + }); + ]]> + </script> + + <body xmlns="http://www.w3.org/1999/xhtml" > + </body> +</window> diff --git a/testing/mochitest/jar.mn b/testing/mochitest/jar.mn index c678812..75f535d 100644 --- a/testing/mochitest/jar.mn +++ b/testing/mochitest/jar.mn @@ -20,6 +20,7 @@ mochikit.jar: content/static/harness.css (static/harness.css) content/tests/SimpleTest/ChromePowers.js (tests/SimpleTest/ChromePowers.js) content/tests/SimpleTest/EventUtils.js (tests/SimpleTest/EventUtils.js) + content/tests/SimpleTest/SpawnTask.js (tests/SimpleTest/SpawnTask.js) content/tests/SimpleTest/ChromeUtils.js (tests/SimpleTest/ChromeUtils.js) content/tests/SimpleTest/LogController.js (tests/SimpleTest/LogController.js) content/tests/SimpleTest/MemoryStats.js (tests/SimpleTest/MemoryStats.js) diff --git a/testing/mochitest/tests/Harness_sanity/mochitest.ini b/testing/mochitest/tests/Harness_sanity/mochitest.ini index 0eefc3f..935acc3 100644 --- a/testing/mochitest/tests/Harness_sanity/mochitest.ini +++ b/testing/mochitest/tests/Harness_sanity/mochitest.ini @@ -31,4 +31,4 @@ fail-if = true [test_sanity_manifest_pf.html] skip-if = toolkit == 'android' # we use the old manifest style on android fail-if = true - +[test_spawn_task.html] diff --git a/testing/mochitest/tests/Harness_sanity/test_spawn_task.html b/testing/mochitest/tests/Harness_sanity/test_spawn_task.html new file mode 100644 index 0000000..425b7fd --- /dev/null +++ b/testing/mochitest/tests/Harness_sanity/test_spawn_task.html @@ -0,0 +1,73 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for mochitest SpawnTask.js sanity</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=">Mozilla Bug 1078657</a> +<p id="display"></p> +<div id="content" style="display: none"></div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for sanity **/ +SimpleTest.waitForExplicitFinish(); + +var externalGeneratorFunction = function* () { + return 8; +}; + +var nestedFunction = function* () { + return yield function* () { + return yield function* () { + return yield function* () { + return yield Promise.resolve(9); + }(); + }(); + }(); +} + +var variousTests = function* () { + var val1 = yield [Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)]; + is(val1.join(""), "123", "Array of promises -> Promise.all"); + var val2 = yield Promise.resolve(2); + is(val2, 2, "Resolved promise yields value."); + var val3 = yield function* () { return 3; }; + is(val3, 3, "Generator functions are spawned."); + //var val4 = yield function () { return 4; }; + //is(val4, 4, "Plain functions run and return."); + var val5 = yield (function* () { return 5; }()); + is(val5, 5, "Generators are spawned."); + try { + var val6 = yield Promise.reject(Error("error6")); + ok(false, "Shouldn't reach this line."); + } catch (error) { + is(error.message, "error6", "Rejected promise throws error."); + } + try { + var val7 = yield function* () { throw Error("error7"); }; + ok(false, "Shouldn't reach this line."); + } catch (error) { + is(error.message, "error7", "Thrown error propagates."); + } + var val8 = yield externalGeneratorFunction(); + is(val8, 8, "External generator also spawned."); + var val9 = yield nestedFunction(); + is(val9, 9, "Nested generator functions work."); + return 10; +}; + +spawnTask(variousTests).then(function(result) { + is(result, 10, "spawnTask(...) returns promise"); + SimpleTest.finish(); +}); + + +</script> +</pre> +</body> +</html> + diff --git a/testing/mochitest/tests/SimpleTest/LICENSE_SpawnTask b/testing/mochitest/tests/SimpleTest/LICENSE_SpawnTask new file mode 100644 index 0000000..088c54c --- /dev/null +++ b/testing/mochitest/tests/SimpleTest/LICENSE_SpawnTask @@ -0,0 +1,24 @@ +LICENSE for SpawnTask.js (the co library): + +(The MIT License) + +Copyright (c) 2014 TJ Holowaychuk &lt;tj(a)vision-media.ca&gt; + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/testing/mochitest/tests/SimpleTest/SpawnTask.js b/testing/mochitest/tests/SimpleTest/SpawnTask.js new file mode 100644 index 0000000..954dcc4 --- /dev/null +++ b/testing/mochitest/tests/SimpleTest/SpawnTask.js @@ -0,0 +1,244 @@ +// # SpawnTask.js +// Directly copied from the "co" library by TJ Holowaychuk. +// See https://github.com/tj/co/tree/4.6.0 +// For use with mochitest-plain and mochitest-chrome. + +// __spawnTask(generatorFunction)__. +// Expose only the `co` function, which is very similar to Task.spawn in Task.jsm. +// We call this function spawnTask to make its purpose more plain, and to +// reduce the chance of name collisions. +var spawnTask = (function () { + +/** + * slice() reference. + */ + +var slice = Array.prototype.slice; + +/** + * Wrap the given generator `fn` into a + * function that returns a promise. + * This is a separate function so that + * every `co()` call doesn't create a new, + * unnecessary closure. + * + * @param {GeneratorFunction} fn + * @return {Function} + * @api public + */ + +co.wrap = function (fn) { + createPromise.__generatorFunction__ = fn; + return createPromise; + function createPromise() { + return co.call(this, fn.apply(this, arguments)); + } +}; + +/** + * Execute the generator function or a generator + * and return a promise. + * + * @param {Function} fn + * @return {Promise} + * @api public + */ + +function co(gen) { + var ctx = this; + var args = slice.call(arguments, 1) + + // we wrap everything in a promise to avoid promise chaining, + // which leads to memory leak errors. + // see https://github.com/tj/co/issues/180 + return new Promise(function(resolve, reject) { + if (typeof gen === 'function') gen = gen.apply(ctx, args); + if (!gen || typeof gen.next !== 'function') return resolve(gen); + + onFulfilled(); + + /** + * @param {Mixed} res + * @return {Promise} + * @api private + */ + + function onFulfilled(res) { + var ret; + try { + ret = gen.next(res); + } catch (e) { + return reject(e); + } + next(ret); + } + + /** + * @param {Error} err + * @return {Promise} + * @api private + */ + + function onRejected(err) { + var ret; + try { + ret = gen.throw(err); + } catch (e) { + return reject(e); + } + next(ret); + } + + /** + * Get the next value in the generator, + * return a promise. + * + * @param {Object} ret + * @return {Promise} + * @api private + */ + + function next(ret) { + if (ret.done) return resolve(ret.value); + var value = toPromise.call(ctx, ret.value); + if (value && isPromise(value)) return value.then(onFulfilled, onRejected); + return onRejected(new TypeError('You may only yield a function, promise, generator, array, or object, ' + + 'but the following object was passed: "' + String(ret.value) + '"')); + } + }); +} + +/** + * Convert a `yield`ed value into a promise. + * + * @param {Mixed} obj + * @return {Promise} + * @api private + */ + +function toPromise(obj) { + if (!obj) return obj; + if (isPromise(obj)) return obj; + if (isGeneratorFunction(obj) || isGenerator(obj)) return co.call(this, obj); + if ('function' == typeof obj) return thunkToPromise.call(this, obj); + if (Array.isArray(obj)) return arrayToPromise.call(this, obj); + if (isObject(obj)) return objectToPromise.call(this, obj); + return obj; +} + +/** + * Convert a thunk to a promise. + * + * @param {Function} + * @return {Promise} + * @api private + */ + +function thunkToPromise(fn) { + var ctx = this; + return new Promise(function (resolve, reject) { + fn.call(ctx, function (err, res) { + if (err) return reject(err); + if (arguments.length > 2) res = slice.call(arguments, 1); + resolve(res); + }); + }); +} + +/** + * Convert an array of "yieldables" to a promise. + * Uses `Promise.all()` internally. + * + * @param {Array} obj + * @return {Promise} + * @api private + */ + +function arrayToPromise(obj) { + return Promise.all(obj.map(toPromise, this)); +} + +/** + * Convert an object of "yieldables" to a promise. + * Uses `Promise.all()` internally. + * + * @param {Object} obj + * @return {Promise} + * @api private + */ + +function objectToPromise(obj){ + var results = new obj.constructor(); + var keys = Object.keys(obj); + var promises = []; + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + var promise = toPromise.call(this, obj[key]); + if (promise && isPromise(promise)) defer(promise, key); + else results[key] = obj[key]; + } + return Promise.all(promises).then(function () { + return results; + }); + + function defer(promise, key) { + // predefine the key in the result + results[key] = undefined; + promises.push(promise.then(function (res) { + results[key] = res; + })); + } +} + +/** + * Check if `obj` is a promise. + * + * @param {Object} obj + * @return {Boolean} + * @api private + */ + +function isPromise(obj) { + return 'function' == typeof obj.then; +} + +/** + * Check if `obj` is a generator. + * + * @param {Mixed} obj + * @return {Boolean} + * @api private + */ + +function isGenerator(obj) { + return 'function' == typeof obj.next && 'function' == typeof obj.throw; +} + +/** + * Check if `obj` is a generator function. + * + * @param {Mixed} obj + * @return {Boolean} + * @api private + */ +function isGeneratorFunction(obj) { + var constructor = obj.constructor; + if (!constructor) return false; + if ('GeneratorFunction' === constructor.name || 'GeneratorFunction' === constructor.displayName) return true; + return isGenerator(constructor.prototype); +} + +/** + * Check for plain object. + * + * @param {Mixed} val + * @return {Boolean} + * @api private + */ + +function isObject(val) { + return Object == val.constructor; +} + +return co; +})(); diff --git a/testing/mochitest/tests/SimpleTest/moz.build b/testing/mochitest/tests/SimpleTest/moz.build index 4cf31c7..e07b652 100644 --- a/testing/mochitest/tests/SimpleTest/moz.build +++ b/testing/mochitest/tests/SimpleTest/moz.build @@ -17,6 +17,7 @@ TEST_HARNESS_FILES.testing.mochitest.tests.SimpleTest += [ 'paint_listener.js', 'setup.js', 'SimpleTest.js', + 'SpawnTask.js', 'test.css', 'TestRunner.js', 'WindowSnapshot.js',
1 0
0 0
[tor-browser/tor-browser-38.1.0esr-5.0-1] fixup! Bug #15502, Part 2: Regression tests for blob URL isolation
by mikeperry@torproject.org 28 Jul '15

28 Jul '15
commit eaeb778b28d2f300403a721db8374ea72f8499b6 Author: Arthur Edelstein <arthuredelstein(a)gmail.com> Date: Mon Jun 22 16:18:46 2015 -0700 fixup! Bug #15502, Part 2: Regression tests for blob URL isolation --- dom/base/test/bug15502_page_blobify.html | 3 ++- dom/base/test/bug15502_page_deblobify.html | 3 ++- dom/base/test/bug15502_tab.html | 5 +++-- dom/base/test/bug15502_utils.js | 15 +++++++-------- dom/base/test/bug15502_worker_blobify.html | 3 ++- dom/base/test/bug15502_worker_deblobify.html | 3 ++- dom/base/test/test_tor_bug15502.html | 17 ++++++++++++----- 7 files changed, 30 insertions(+), 19 deletions(-) diff --git a/dom/base/test/bug15502_page_blobify.html b/dom/base/test/bug15502_page_blobify.html index d883929..5d81bec 100644 --- a/dom/base/test/bug15502_page_blobify.html +++ b/dom/base/test/bug15502_page_blobify.html @@ -6,6 +6,7 @@ https://bugs.torproject.org/15502 <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <title>Page blobifier for Tor Browser Bug 15502</title> + <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script> <script type="text/javascript;version=1.7" src="bug15502_utils.js"></script> </head> <body> @@ -13,7 +14,7 @@ https://bugs.torproject.org/15502 <script type="text/javascript;version=1.7"> -Task.spawn(function* () { +spawnTask(function* () { sendMessage(window.parent, "ready"); let message = yield receiveMessage(window.parent), blobURL = stringToBlobURL(message); diff --git a/dom/base/test/bug15502_page_deblobify.html b/dom/base/test/bug15502_page_deblobify.html index e8cbd51..c728c79 100644 --- a/dom/base/test/bug15502_page_deblobify.html +++ b/dom/base/test/bug15502_page_deblobify.html @@ -6,6 +6,7 @@ https://bugs.torproject.org/15502 <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <title>Page deblobifier for Tor Browser Bug 15502</title> + <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script> <script type="text/javascript;version=1.7" src="bug15502_utils.js"></script> </head> <body> @@ -13,7 +14,7 @@ https://bugs.torproject.org/15502 <script type="text/javascript;version=1.7"> -Task.spawn(function* () { +spawnTask(function* () { sendMessage(window.parent, "ready"); let blobURL = yield receiveMessage(window.parent), string; diff --git a/dom/base/test/bug15502_tab.html b/dom/base/test/bug15502_tab.html index 7bd4744..b41274e 100644 --- a/dom/base/test/bug15502_tab.html +++ b/dom/base/test/bug15502_tab.html @@ -6,6 +6,7 @@ https://bugs.torproject.org/15502 <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <title>Tab for Tor Browser Bug 15502</title> + <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script> <script type="text/javascript;version=1.7" src="bug15502_utils.js"></script> </head> <body> @@ -18,7 +19,7 @@ https://bugs.torproject.org/15502 let iframe = document.getElementById("child"); let connect = function (sourceObject, destinationObject) { - Task.spawn(function* () { + spawnTask(function* () { for (;;) { let message = yield receiveMessage(sourceObject); sendMessage(destinationObject, message); @@ -26,7 +27,7 @@ let connect = function (sourceObject, destinationObject) { }); }; -Task.spawn(function* () { +spawnTask(function* () { sendMessage(window.opener, "ready"); let firstParentMessage = yield receiveMessage(window.opener); iframe.src = firstParentMessage; diff --git a/dom/base/test/bug15502_utils.js b/dom/base/test/bug15502_utils.js index 9d69c12..23f61c4 100644 --- a/dom/base/test/bug15502_utils.js +++ b/dom/base/test/bug15502_utils.js @@ -1,11 +1,8 @@ -// Import Task.jsm -let { Task } = SpecialPowers.Cu.import("resource://gre/modules/Task.jsm"); - // __listen(target, eventType, timeoutMs, useCapture)__. // Calls addEventListener on target, with the given eventType. // Returns a Promise that resolves to an Event object, if the event fires. // If a timeout occurs, then Promise is rejected with a "Timed out" error. -// For use with Task.jsm. +// For use with SpawnTask.js. let listen = function (target, eventType, timeoutMs, useCapture) { return new Promise(function (resolve, reject) { let listenFunction = function (event) { @@ -13,17 +10,19 @@ let listen = function (target, eventType, timeoutMs, useCapture) { resolve(event); }; target.addEventListener(eventType, listenFunction, useCapture); - setTimeout(() => reject(new Error("Timed out")), timeoutMs); + if (timeoutMs) { + setTimeout(() => reject(new Error("Timed out")), timeoutMs); + } }); }; // __receiveMessage(source)__. // Returns an event object for the next message received from source. -// A Task.jsm coroutine. +// A SpawnTask.js coroutine. let receiveMessage = function* (source) { let event; do { - event = yield listen(self, "message", 5000, false); + event = yield listen(self, "message", null, false); } while (event.source !== source); return event.data; }; @@ -94,7 +93,7 @@ let stringToBlobURL = function (s) { // __workerIO(scriptFile, inputString)__. // Sends inputString for the worker, and waits // for the worker to return an outputString. -// Task.jsm coroutine. +// SpawnTask.js coroutine. let workerIO = function* (scriptFile, inputString) { let worker = new Worker(scriptFile); worker.postMessage(inputString); diff --git a/dom/base/test/bug15502_worker_blobify.html b/dom/base/test/bug15502_worker_blobify.html index 3dd7926..7084366 100644 --- a/dom/base/test/bug15502_worker_blobify.html +++ b/dom/base/test/bug15502_worker_blobify.html @@ -6,6 +6,7 @@ https://bugs.torproject.org/15502 <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <title>Worker blobifier for Tor Browser Bug 15502</title> + <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script> <script type="text/javascript;version=1.7" src="bug15502_utils.js"></script> </head> <body> @@ -14,7 +15,7 @@ https://bugs.torproject.org/15502 <pre id="test"> <script type="text/javascript;version=1.7"> -Task.spawn(function* () { +spawnTask(function* () { sendMessage(window.parent, "ready"); let message = yield receiveMessage(window.parent), blobURL = yield workerIO("bug15502_worker_blobify.js", message); diff --git a/dom/base/test/bug15502_worker_deblobify.html b/dom/base/test/bug15502_worker_deblobify.html index 30ec6b4..4f498f1 100644 --- a/dom/base/test/bug15502_worker_deblobify.html +++ b/dom/base/test/bug15502_worker_deblobify.html @@ -6,6 +6,7 @@ https://bugs.torproject.org/15502 <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <title>Worker deblobifier for Tor Browser Bug 15502</title> + <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script> <script type="text/javascript;version=1.7" src="bug15502_utils.js"></script> </head> <body> @@ -14,7 +15,7 @@ https://bugs.torproject.org/15502 <pre id="test"> <script type="text/javascript;version=1.7"> -Task.spawn(function* () { +spawnTask(function* () { sendMessage(window.parent, "ready"); let blobURL = yield receiveMessage(window.parent), result = yield workerIO("bug15502_worker_deblobify.js", blobURL); diff --git a/dom/base/test/test_tor_bug15502.html b/dom/base/test/test_tor_bug15502.html index 06bcc1c..18b8459 100644 --- a/dom/base/test/test_tor_bug15502.html +++ b/dom/base/test/test_tor_bug15502.html @@ -7,6 +7,7 @@ https://bugs.torproject.org/15502 <meta http-equiv="content-type" content="text/html; charset=utf-8"> <title>Test for Tor Browser Bug 15502</title> <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script> <script type="text/javascript;version=1.7" src="bug15502_utils.js"></script> <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> </head> @@ -17,8 +18,14 @@ https://bugs.torproject.org/15502 <script class="testbody" type="application/javascript;version=1.7"> SimpleTest.waitForExplicitFinish(); -// __prefs__. Import the `Serivces.prefs` object. -let prefs = SpecialPowers.Cu.import("resource://gre/modules/Services.jsm").Services.prefs; +// __setPref(key, value)__. +// Set a pref value asynchronously, returning a prmoise that resolves +// when it succeeds. +let setPref = function* (key, value) { + return new Promise(function(resolve, reject) { + SpecialPowers.pushPrefEnv({"set": [[key, value]]}, resolve); + }); +}; // ## Testing constants let domain1 = "http://example.com", @@ -47,7 +54,7 @@ let tabIO = function* (domain, child, input) { // and then attempt to retrieve the object from the blobURL in `domainB`, using // the page `deblobPage`. let blobTest = function* (isolationOn, domainA, domainB, blobPage, deblobPage) { - prefs.setIntPref("privacy.thirdparty.isolate", isolationOn ? 2 : 0); + yield setPref("privacy.thirdparty.isolate", isolationOn ? 2 : 0); let input = "" + Math.random(), blobURL = yield tabIO(domainA, blobPage, input), result = yield tabIO(domainB, deblobPage, blobURL), @@ -71,9 +78,9 @@ let blobTest = function* (isolationOn, domainA, domainB, blobPage, deblobPage) { // ## The main test -// Run a Task.jsm coroutine that tests various combinations of domains +// Run a coroutine that tests various combinations of domains // methods, and isolation states for reading and writing blob URLs. -Task.spawn(function* () { +spawnTask(function* () { for (let isolate of [false, true]) { for (let domainB of [domain1, domain2]) { for (let blob of [page_blob, worker_blob]) {
1 0
0 0
[tor-browser/tor-browser-38.1.0esr-5.0-1] Revert "Bug #15502. Isolate blob URLs to first party; no blobURLs in Web Workers"
by mikeperry@torproject.org 28 Jul '15

28 Jul '15
commit b4d97bc75ff672725fd80e0c640748a74c6edc3e Author: Arthur Edelstein <arthuredelstein(a)gmail.com> Date: Thu Jul 2 12:54:18 2015 -0700 Revert "Bug #15502. Isolate blob URLs to first party; no blobURLs in Web Workers" This reverts commit 7a8d11b1ef502688c97d7900c57361c4be6ae13a. --- .../pdfjs/content/PdfStreamConverter.jsm | 7 +----- .../extensions/pdfjs/content/build/pdf.worker.js | 9 +------- dom/base/ThirdPartyUtil.cpp | 9 -------- dom/base/nsHostObjectProtocolHandler.cpp | 23 ++------------------ dom/workers/URL.cpp | 7 ------ netwerk/base/mozIThirdPartyUtil.idl | 14 ------------ 6 files changed, 4 insertions(+), 65 deletions(-) diff --git a/browser/extensions/pdfjs/content/PdfStreamConverter.jsm b/browser/extensions/pdfjs/content/PdfStreamConverter.jsm index 26515be..11db211 100644 --- a/browser/extensions/pdfjs/content/PdfStreamConverter.jsm +++ b/browser/extensions/pdfjs/content/PdfStreamConverter.jsm @@ -250,12 +250,6 @@ ChromeActions.prototype = { filename = 'document.pdf'; } var blobUri = data.blobUrl ? NetUtil.newURI(data.blobUrl) : originalUri; - var netChannel; - try { - netChannel = NetUtil.newChannel(blobUri); - } catch (e) { - netChannel = NetUtil.newChannel(originalUri); - } var extHelperAppSvc = Cc['@mozilla.org/uriloader/external-helper-app-service;1']. getService(Ci.nsIExternalHelperAppService); @@ -263,6 +257,7 @@ ChromeActions.prototype = { getService(Ci.nsIWindowWatcher).activeWindow; var docIsPrivate = this.isInPrivateBrowsing(); + var netChannel = NetUtil.newChannel(blobUri); if ('nsIPrivateBrowsingChannel' in Ci && netChannel instanceof Ci.nsIPrivateBrowsingChannel) { netChannel.setPrivate(docIsPrivate); diff --git a/browser/extensions/pdfjs/content/build/pdf.worker.js b/browser/extensions/pdfjs/content/build/pdf.worker.js index a5dfe2f..c9de2ea 100644 --- a/browser/extensions/pdfjs/content/build/pdf.worker.js +++ b/browser/extensions/pdfjs/content/build/pdf.worker.js @@ -1152,14 +1152,7 @@ PDFJS.createObjectURL = (function createObjectURLClosure() { if (!PDFJS.disableCreateObjectURL && typeof URL !== 'undefined' && URL.createObjectURL) { var blob = PDFJS.createBlob(data, contentType); - try { - return URL.createObjectURL(blob); - } catch(e) { - // URL.createObjectURL has thrown an error; continue to - // data schema fallback. - // TODO: Remove this try-catch when we re-enable - // createObjectURL in workers. - } + return URL.createObjectURL(blob); } var buffer = 'data:' + contentType + ';base64,'; diff --git a/dom/base/ThirdPartyUtil.cpp b/dom/base/ThirdPartyUtil.cpp index eb09b43..d0aed3a 100644 --- a/dom/base/ThirdPartyUtil.cpp +++ b/dom/base/ThirdPartyUtil.cpp @@ -746,12 +746,3 @@ ThirdPartyUtil::GetFirstPartyHostForIsolation(nsIURI *aFirstPartyURI, aHost.Append("--"); return NS_OK; } - -NS_IMETHODIMP -ThirdPartyUtil::GetFirstPartyHostFromCaller(nsACString& aHost) { - nsCOMPtr<nsIURI> uri; - nsresult rv = GetFirstPartyIsolationURI(nullptr, - nsContentUtils::GetDocumentFromCaller(), getter_AddRefs(uri)); - NS_ENSURE_SUCCESS(rv, rv); - return GetFirstPartyHostForIsolation(uri, aHost); -} diff --git a/dom/base/nsHostObjectProtocolHandler.cpp b/dom/base/nsHostObjectProtocolHandler.cpp index 8c440f4..aac33f9 100644 --- a/dom/base/nsHostObjectProtocolHandler.cpp +++ b/dom/base/nsHostObjectProtocolHandler.cpp @@ -16,7 +16,6 @@ #include "mozilla/dom/File.h" #include "mozilla/Preferences.h" #include "mozilla/LoadInfo.h" -#include "mozIThirdPartyUtil.h" using mozilla::dom::FileImpl; using mozilla::ErrorResult; @@ -30,20 +29,9 @@ struct DataInfo nsCOMPtr<nsISupports> mObject; nsCOMPtr<nsIPrincipal> mPrincipal; nsCString mStack; - nsCString mFirstPartyHost; }; static nsClassHashtable<nsCStringHashKey, DataInfo>* gDataTable; -static nsCOMPtr<mozIThirdPartyUtil> gThirdPartyUtilService; - -static nsCString GetFirstPartyHostFromCaller() { - if (!gThirdPartyUtilService) { - gThirdPartyUtilService = do_GetService(THIRDPARTYUTIL_CONTRACTID); - } - nsCString host; - gThirdPartyUtilService->GetFirstPartyHostFromCaller(host); - return host; -} // Memory reporting for the hash table. namespace mozilla { @@ -325,8 +313,6 @@ nsHostObjectProtocolHandler::AddDataEntry(const nsACString& aScheme, info->mObject = aObject; info->mPrincipal = aPrincipal; - // Record the first party host that originated this object. - info->mFirstPartyHost = GetFirstPartyHostFromCaller(); mozilla::BlobURLsReporter::GetJSStackForBlob(info); gDataTable->Put(aUri, info); @@ -451,10 +437,7 @@ GetDataObject(nsIURI* aURI) aURI->GetSpec(spec); DataInfo* info = GetDataInfo(spec); - // Deny access to this object if the current first-party host - // doesn't match the originating first-party host. - return (info && info->mFirstPartyHost == GetFirstPartyHostFromCaller()) - ? info->mObject : nullptr; + return info ? info->mObject : nullptr; } // ----------------------------------------------------------------------- @@ -512,9 +495,7 @@ nsHostObjectProtocolHandler::NewChannel2(nsIURI* uri, DataInfo* info = GetDataInfo(spec); - // Deny access to this URI if the current first party host - // doesn't match the first party host when it was created. - if (!info || (info->mFirstPartyHost != GetFirstPartyHostFromCaller())) { + if (!info) { return NS_ERROR_DOM_BAD_URI; } diff --git a/dom/workers/URL.cpp b/dom/workers/URL.cpp index 2ad1276..fbf6987 100644 --- a/dom/workers/URL.cpp +++ b/dom/workers/URL.cpp @@ -889,13 +889,6 @@ URL::CreateObjectURL(const GlobalObject& aGlobal, File& aBlob, JSContext* cx = aGlobal.Context(); WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx); - if (!workerPrivate->IsChromeWorker()) { - workerPrivate->ReportError(cx, "Worker attempted to use createObjectURL; denied.", nullptr); - NS_NAMED_LITERAL_STRING(argStr, "URL.createObjectURL"); - aRv.ThrowTypeError(MSG_METHOD_THIS_UNWRAPPING_DENIED, &argStr); - return; - } - nsRefPtr<FileImpl> blobImpl = aBlob.Impl(); MOZ_ASSERT(blobImpl); diff --git a/netwerk/base/mozIThirdPartyUtil.idl b/netwerk/base/mozIThirdPartyUtil.idl index a06841d..68a7099 100644 --- a/netwerk/base/mozIThirdPartyUtil.idl +++ b/netwerk/base/mozIThirdPartyUtil.idl @@ -262,20 +262,6 @@ interface mozIThirdPartyUtil : nsISupports */ AUTF8String getFirstPartyHostForIsolation(in nsIURI aFirstPartyURI); - /** - * getFirstPartyHostFromCaller - * - * Obtain the host or pseudo-host for the first party URI belonging - * to the calling document. See getFirstPartyHostForIsolation(...) for - * examples. - * - * @return host or pseudo host. - * - * @throws if the calling document's first party URI lacks a host - * and the scheme is not a whitelisted one for which we - * generate a pseudo host. - */ - AUTF8String getFirstPartyHostFromCaller(); }; %{ C++
1 0
0 0
[torbutton/master] Bug 16268: non-en-US Tor Browser has Firefox branding in about box.
by mikeperry@torproject.org 28 Jul '15

28 Jul '15
commit d7ff1cc7c2b785a2e44e2a568ae0d66a890f225b Author: Kathy Brade <brade(a)pearlcrescent.com> Date: Mon Jul 27 13:40:29 2015 -0400 Bug 16268: non-en-US Tor Browser has Firefox branding in about box. Import aboutDialog.dtd and aboutTor.properties from Transifex. Improved import-translations.sh to check that all .dtd and .properties files are imported. Work around a Transifex issue that caused some entities to be encoded twice. --- trans_tools/import-translations.sh | 88 ++++++++++++++++++++++++------------ 1 file changed, 60 insertions(+), 28 deletions(-) diff --git a/trans_tools/import-translations.sh b/trans_tools/import-translations.sh index c29ed4c..28816ff 100755 --- a/trans_tools/import-translations.sh +++ b/trans_tools/import-translations.sh @@ -1,4 +1,4 @@ -#!/bin/sh -e +#!/bin/bash -e # This var comes from the TBB locale list. # XXX: Find some way to keep this, tor-launcher, and Tor Browser in sync @@ -11,6 +11,48 @@ BUNDLE_LOCALES="ar de es fa fr it ko nl pl pt ru tr vi zh-CN" # and translations are available. BUNDLE_LOCALES="$BUNDLE_LOCALES eu ja sv" +LOCALE_DIR=../src/chrome/locale + +# FILEMAP is an array of "localeFile:translationBranch" strings. +FILEMAP=( "aboutDialog.dtd:torbutton-aboutdialogdtd" + "aboutTor.dtd:abouttor-homepage" + "aboutTor.properties:torbutton-abouttorproperties" + "brand.dtd:torbutton-branddtd" + "brand.properties:torbutton-brandproperties" + "browser.properties:torbutton-browserproperties" + "torbutton.dtd:torbutton-torbuttondtd" + "torbutton.properties:torbutton-torbuttonproperties" + ) + +# Verify that the FILEMAP contains an entry for each Torbutton file. +FILES_ARE_MISSING=0 +for DEST_PATH in $LOCALE_DIR/en/*.dtd $LOCALE_DIR/en/*.properties; +do + IS_FILE_IN_MAP=0 + DEST_FILE=${DEST_PATH##*/} + for KEYVAL in "${FILEMAP[@]}"; + do + FILE="${KEYVAL%%:*}" + if [ $FILE = $DEST_FILE ]; + then + IS_FILE_IN_MAP=1 + break; + fi + done + + if [ $IS_FILE_IN_MAP -eq 0 ]; + then + echo "Please add $DEST_FILE to FILEMAP." 1>&2 + FILES_ARE_MISSING=1 + fi +done + +if [ $FILES_ARE_MISSING -ne 0 ]; +then + exit 1 +fi + +# Clone or update our translation repo. if [ -d translation ]; then cd translation @@ -20,32 +62,22 @@ else git clone https://git.torproject.org/translation.git fi +# Update each translated file for each locale. +echo "Locales: $BUNDLE_LOCALES" cd translation -for i in $BUNDLE_LOCALES -do - UL="`echo $i|tr - _`" - mkdir -p ../../src/chrome/locale/$i/ - git checkout abouttor-homepage - git merge origin/abouttor-homepage - cp $UL/aboutTor.dtd ../../src/chrome/locale/$i/ - - git checkout torbutton-torbuttondtd - git merge origin/torbutton-torbuttondtd - cp $UL/torbutton.dtd ../../src/chrome/locale/$i/ - - git checkout torbutton-branddtd - git merge origin/torbutton-branddtd - cp $UL/brand.dtd ../../src/chrome/locale/$i/ - - git checkout torbutton-torbuttonproperties - git merge origin/torbutton-torbuttonproperties - cp $UL/torbutton.properties ../../src/chrome/locale/$i/ - - git checkout torbutton-browserproperties - git merge origin/torbutton-browserproperties - cp $UL/browser.properties ../../src/chrome/locale/$i/ - - git checkout torbutton-brandproperties - git merge origin/torbutton-brandproperties - cp $UL/brand.properties ../../src/chrome/locale/$i/ +for KEYVAL in "${FILEMAP[@]}"; do + FILE="${KEYVAL%%:*}" + BRANCH="${KEYVAL##*:}" + echo "Updating ${FILE}..." + git checkout -q "$BRANCH" + git merge -q origin/"$BRANCH" + for i in $BUNDLE_LOCALES; + do + UL="`echo $i|tr - _`" + mkdir -p ../$LOCALE_DIR/$i/ +# Use sed to work around a Transifex "double entity" issue. + sed -e 's/\&amp;brandShortName;/\&brandShortName;/g' \ + -e 's/\&amp;vendorShortName;/\&vendorShortName;/g' \ + $UL/"$FILE" > ../$LOCALE_DIR/$i/"$FILE" + done done
1 0
0 0
[tor-browser/tor-browser-38.1.0esr-5.0-1] Merge remote-tracking branch 'brade/bug16236-01' into tor-browser-38.1.0esr-5.0-1
by mikeperry@torproject.org 27 Jul '15

27 Jul '15
commit 5ba1b3465b136c061afca8fdcfd38ccf77b02d88 Merge: 41a0771 b7a65a6 Author: Mike Perry <mikeperry-git(a)torproject.org> Date: Mon Jul 27 08:57:50 2015 -0700 Merge remote-tracking branch 'brade/bug16236-01' into tor-browser-38.1.0esr-5.0-1 toolkit/mozapps/update/updater/updater.cpp | 9 ++++++++- toolkit/xre/nsUpdateDriver.cpp | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-)
1 0
0 0
[tor-browser/tor-browser-38.1.0esr-5.0-1] Bug 16236: Windows updater: avoid writing to the registry.
by mikeperry@torproject.org 27 Jul '15

27 Jul '15
commit b7a65a6dcfc1963fef42b4a0d4b5013dbc8a36ad Author: Kathy Brade <brade(a)pearlcrescent.com> Date: Wed Jul 22 15:58:52 2015 -0400 Bug 16236: Windows updater: avoid writing to the registry. Mozilla moves "in use" files that cannot be deleted during an update to a "tobedeleted" directory and then makes a call to MoveFileEx(..., MOVEFILE_DELAY_UNTIL_REBOOT) to request that the file be deleted later. To avoid writing to the Windows Registry, we simply try to remove the "tobedeleted" directory and its contents during browser startup. --- toolkit/mozapps/update/updater/updater.cpp | 9 ++++++++- toolkit/xre/nsUpdateDriver.cpp | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/toolkit/mozapps/update/updater/updater.cpp b/toolkit/mozapps/update/updater/updater.cpp index acb610c..6e55fe2 100644 --- a/toolkit/mozapps/update/updater/updater.cpp +++ b/toolkit/mozapps/update/updater/updater.cpp @@ -866,7 +866,7 @@ static int rename_file(const NS_tchar *spath, const NS_tchar *dpath, return OK; } -#ifdef XP_WIN +#if defined(XP_WIN) && !defined(TOR_BROWSER_UPDATE) // Remove the directory pointed to by path and all of its files and // sub-directories. If a file is in use move it to the tobedeleted directory // and attempt to schedule removal of the file on reboot @@ -1005,6 +1005,8 @@ static int backup_discard(const NS_tchar *path) backup, path)); return WRITE_ERROR; } + +#if !defined(TOR_BROWSER_UPDATE) // The MoveFileEx call to remove the file on OS reboot will fail if the // process doesn't have write access to the HKEY_LOCAL_MACHINE registry key // but this is ok since the installer / uninstaller will delete the @@ -1017,6 +1019,7 @@ static int backup_discard(const NS_tchar *path) LOG(("backup_discard: failed to schedule OS reboot removal of " \ "file: " LOG_S, path)); } +#endif } #else if (rv) @@ -2280,8 +2283,10 @@ ProcessReplaceRequest() if (NS_taccess(deleteDir, F_OK)) { NS_tmkdir(deleteDir, 0755); } +#if !defined(TOR_BROWSER_UPDATE) remove_recursive_on_reboot(tmpDir, deleteDir); #endif +#endif } #ifdef XP_MACOSX @@ -3360,6 +3365,7 @@ int NS_main(int argc, NS_tchar **argv) if (!sStagedUpdate && !sReplaceRequest && _wrmdir(DELETE_DIR)) { LOG(("NS_main: unable to remove directory: " LOG_S ", err: %d", DELETE_DIR, errno)); +#if !defined(TOR_BROWSER_UPDATE) // The directory probably couldn't be removed due to it containing files // that are in use and will be removed on OS reboot. The call to remove the // directory on OS reboot is done after the calls to remove the files so the @@ -3376,6 +3382,7 @@ int NS_main(int argc, NS_tchar **argv) LOG(("NS_main: failed to schedule OS reboot removal of " \ "directory: " LOG_S, DELETE_DIR)); } +#endif } #endif /* XP_WIN */ diff --git a/toolkit/xre/nsUpdateDriver.cpp b/toolkit/xre/nsUpdateDriver.cpp index ef4c5fb..085f439 100644 --- a/toolkit/xre/nsUpdateDriver.cpp +++ b/toolkit/xre/nsUpdateDriver.cpp @@ -1111,6 +1111,20 @@ ProcessUpdates(nsIFile *greDir, nsIFile *appDir, nsIFile *updRootDir, bool restart, bool isOSUpdate, nsIFile *osApplyToDir, ProcessType *pid) { +#if defined(XP_WIN) && defined(TOR_BROWSER_UPDATE) + // Try to remove the "tobedeleted" directory which, if present, contains + // files that could not be removed during a previous update (e.g., DLLs + // that were in use and therefore locked by Windows). + nsCOMPtr<nsIFile> deleteDir; + nsresult winrv = appDir->Clone(getter_AddRefs(deleteDir)); + if (NS_SUCCEEDED(winrv)) { + winrv = deleteDir->AppendNative(NS_LITERAL_CSTRING("tobedeleted")); + if (NS_SUCCEEDED(winrv)) { + winrv = deleteDir->Remove(true); + } + } +#endif + nsresult rv; nsCOMPtr<nsIFile> updatesDir;
1 0
0 0
[torbutton/master] Bug 16639: Check for Updates menu item can cause update failure.
by mikeperry@torproject.org 27 Jul '15

27 Jul '15
commit 84497608ae13239b67d2b656647c64a70badd72c Author: Kathy Brade <brade(a)pearlcrescent.com> Date: Thu Jul 23 15:30:51 2015 -0400 Bug 16639: Check for Updates menu item can cause update failure. Check the state of the active update (if any) and open the update prompt in the correct mode. --- src/chrome/content/torbutton.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/chrome/content/torbutton.js b/src/chrome/content/torbutton.js index 6539ea9..1d81960 100644 --- a/src/chrome/content/torbutton.js +++ b/src/chrome/content/torbutton.js @@ -893,9 +893,23 @@ function torbutton_notify_if_update_needed() { } function torbutton_check_for_update() { + // Open the update prompt in the correct mode. The update state + // checks used here were adapted from isPending() and isApplied() in + // Mozilla's browser/base/content/aboutDialog.js code. + let updateMgr = Cc["@mozilla.org/updates/update-manager;1"] + .getService(Ci.nsIUpdateManager); + let update = updateMgr.activeUpdate; + let updateState = (update) ? update.state : undefined; + let pendingStates = [ "pending", "pending-service", + "applied", "applied-service" ]; + let isPending = (updateState && (pendingStates.indexOf(updateState) >= 0)); + let prompter = Cc["@mozilla.org/updates/update-prompt;1"] .createInstance(Ci.nsIUpdatePrompt); - prompter.checkForUpdates(); + if (isPending) + prompter.showUpdateDownloaded(update, false); + else + prompter.checkForUpdates(); } // Pass undefined for a parameter to have this function determine it.
1 0
0 0
  • ← Newer
  • 1
  • ...
  • 1723
  • 1724
  • 1725
  • 1726
  • 1727
  • 1728
  • 1729
  • ...
  • 1861
  • Older →

HyperKitty Powered by HyperKitty version 1.3.12.