diff options
Diffstat (limited to 'dom')
73 files changed, 1269 insertions, 403 deletions
diff --git a/dom/asmjscache/AsmJSCache.cpp b/dom/asmjscache/AsmJSCache.cpp index 4afcc6d6b..be54987a1 100644 --- a/dom/asmjscache/AsmJSCache.cpp +++ b/dom/asmjscache/AsmJSCache.cpp @@ -69,13 +69,19 @@ namespace asmjscache { namespace { +class ParentRunnable; + // Anything smaller should compile fast enough that caching will just add // overhead. -// static const size_t sMinCachedModuleLength = 10000; +static const size_t sMinCachedModuleLength = 10000; // The number of characters to hash into the Metadata::Entry::mFastHash. static const unsigned sNumFastHashChars = 4096; +// Track all live parent actors. +typedef nsTArray<const ParentRunnable*> ParentActorArray; +StaticAutoPtr<ParentActorArray> sLiveParentActors; + nsresult WriteMetadataFile(nsIFile* aMetadataFile, const Metadata& aMetadata) { @@ -236,6 +242,94 @@ EvictEntries(nsIFile* aDirectory, const nsACString& aGroup, } } +/******************************************************************************* + * Client + ******************************************************************************/ + +class Client + : public quota::Client +{ + static Client* sInstance; + + bool mShutdownRequested; + +public: + Client(); + + static bool + IsShuttingDownOnBackgroundThread() + { + AssertIsOnBackgroundThread(); + + if (sInstance) { + return sInstance->IsShuttingDown(); + } + + return QuotaManager::IsShuttingDown(); + } + + static bool + IsShuttingDownOnNonBackgroundThread() + { + MOZ_ASSERT(!IsOnBackgroundThread()); + + return QuotaManager::IsShuttingDown(); + } + + bool + IsShuttingDown() const + { + AssertIsOnBackgroundThread(); + + return mShutdownRequested; + } + + NS_INLINE_DECL_REFCOUNTING(Client, override) + + virtual Type + GetType() override; + + virtual nsresult + InitOrigin(PersistenceType aPersistenceType, + const nsACString& aGroup, + const nsACString& aOrigin, + const AtomicBool& aCanceled, + UsageInfo* aUsageInfo) override; + + virtual nsresult + GetUsageForOrigin(PersistenceType aPersistenceType, + const nsACString& aGroup, + const nsACString& aOrigin, + const AtomicBool& aCanceled, + UsageInfo* aUsageInfo) override; + + virtual void + OnOriginClearCompleted(PersistenceType aPersistenceType, + const nsACString& aOrigin) + override; + + virtual void + ReleaseIOThreadObjects() override; + + virtual void + AbortOperations(const nsACString& aOrigin) override; + + virtual void + AbortOperationsForProcess(ContentParentId aContentParentId) override; + + virtual void + StartIdleMaintenance() override; + + virtual void + StopIdleMaintenance() override; + + virtual void + ShutdownWorkThreads() override; + +private: + ~Client(); +}; + // FileDescriptorHolder owns a file descriptor and its memory mapping. // FileDescriptorHolder is derived by two runnable classes (that is, // (Parent|Child)Runnable. @@ -897,6 +991,13 @@ ParentRunnable::FinishOnOwningThread() FileDescriptorHolder::Finish(); mDirectoryLock = nullptr; + + MOZ_ASSERT(sLiveParentActors); + sLiveParentActors->RemoveElement(this); + + if (sLiveParentActors->IsEmpty()) { + sLiveParentActors = nullptr; + } } NS_IMETHODIMP @@ -1140,6 +1241,10 @@ AllocEntryParent(OpenMode aOpenMode, { AssertIsOnBackgroundThread(); + if (NS_WARN_IF(Client::IsShuttingDownOnBackgroundThread())) { + return nullptr; + } + if (NS_WARN_IF(aPrincipalInfo.type() == PrincipalInfo::TNullPrincipalInfo)) { MOZ_ASSERT(false); return nullptr; @@ -1148,6 +1253,12 @@ AllocEntryParent(OpenMode aOpenMode, RefPtr<ParentRunnable> runnable = new ParentRunnable(aPrincipalInfo, aOpenMode, aWriteParams); + if (!sLiveParentActors) { + sLiveParentActors = new ParentActorArray(); + } + + sLiveParentActors->AppendElement(runnable); + nsresult rv = NS_DispatchToMainThread(runnable); NS_ENSURE_SUCCESS(rv, nullptr); @@ -1520,7 +1631,6 @@ DeallocEntryChild(PAsmJSCacheEntryChild* aActor) static_cast<ChildRunnable*>(aActor)->Release(); } -/* namespace { JS::AsmJSCacheResult @@ -1583,7 +1693,6 @@ OpenFile(nsIPrincipal* aPrincipal, } } // namespace -*/ typedef uint32_t AsmJSCookieType; static const uint32_t sAsmJSCookie = 0x600d600d; @@ -1596,9 +1705,6 @@ OpenEntryForRead(nsIPrincipal* aPrincipal, const uint8_t** aMemory, intptr_t* aHandle) { - return false; - -/* if (size_t(aLimit - aBegin) < sMinCachedModuleLength) { return false; } @@ -1638,7 +1744,6 @@ OpenEntryForRead(nsIPrincipal* aPrincipal, // failure) at which point the file will be closed. childRunnable.Forget(reinterpret_cast<ChildRunnable**>(aHandle)); return true; -*/ } void @@ -1663,9 +1768,6 @@ OpenEntryForWrite(nsIPrincipal* aPrincipal, uint8_t** aMemory, intptr_t* aHandle) { - return JS::AsmJSCache_ESR52; - -/* if (size_t(aEnd - aBegin) < sMinCachedModuleLength) { return JS::AsmJSCache_ModuleTooSmall; } @@ -1699,7 +1801,6 @@ OpenEntryForWrite(nsIPrincipal* aPrincipal, // failure) at which point the file will be closed childRunnable.Forget(reinterpret_cast<ChildRunnable**>(aHandle)); return JS::AsmJSCache_Success; -*/ } void @@ -1722,128 +1823,163 @@ CloseEntryForWrite(size_t aSize, } } -class Client : public quota::Client +/******************************************************************************* + * Client + ******************************************************************************/ + +Client* Client::sInstance = nullptr; + +Client::Client() + : mShutdownRequested(false) { - ~Client() {} + AssertIsOnBackgroundThread(); + MOZ_ASSERT(!sInstance, "We expect this to be a singleton!"); -public: - NS_IMETHOD_(MozExternalRefCountType) - AddRef() override; + sInstance = this; +} - NS_IMETHOD_(MozExternalRefCountType) - Release() override; +Client::~Client() +{ + AssertIsOnBackgroundThread(); + MOZ_ASSERT(sInstance == this, "We expect this to be a singleton!"); - virtual Type - GetType() override - { - return ASMJS; - } + sInstance = nullptr; +} - virtual nsresult - InitOrigin(PersistenceType aPersistenceType, - const nsACString& aGroup, - const nsACString& aOrigin, - const AtomicBool& aCanceled, - UsageInfo* aUsageInfo) override - { - if (!aUsageInfo) { - return NS_OK; - } - return GetUsageForOrigin(aPersistenceType, - aGroup, - aOrigin, - aCanceled, - aUsageInfo); - } +Client::Type +Client::GetType() +{ + return ASMJS; +} - virtual nsresult - GetUsageForOrigin(PersistenceType aPersistenceType, - const nsACString& aGroup, - const nsACString& aOrigin, - const AtomicBool& aCanceled, - UsageInfo* aUsageInfo) override - { - QuotaManager* qm = QuotaManager::Get(); - MOZ_ASSERT(qm, "We were being called by the QuotaManager"); +nsresult +Client::InitOrigin(PersistenceType aPersistenceType, + const nsACString& aGroup, + const nsACString& aOrigin, + const AtomicBool& aCanceled, + UsageInfo* aUsageInfo) +{ + if (!aUsageInfo) { + return NS_OK; + } + return GetUsageForOrigin(aPersistenceType, + aGroup, + aOrigin, + aCanceled, + aUsageInfo); +} - nsCOMPtr<nsIFile> directory; - nsresult rv = qm->GetDirectoryForOrigin(aPersistenceType, aOrigin, - getter_AddRefs(directory)); - NS_ENSURE_SUCCESS(rv, rv); - MOZ_ASSERT(directory, "We're here because the origin directory exists"); +nsresult +Client::GetUsageForOrigin(PersistenceType aPersistenceType, + const nsACString& aGroup, + const nsACString& aOrigin, + const AtomicBool& aCanceled, + UsageInfo* aUsageInfo) +{ + QuotaManager* qm = QuotaManager::Get(); + MOZ_ASSERT(qm, "We were being called by the QuotaManager"); - rv = directory->Append(NS_LITERAL_STRING(ASMJSCACHE_DIRECTORY_NAME)); - NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr<nsIFile> directory; + nsresult rv = qm->GetDirectoryForOrigin(aPersistenceType, aOrigin, + getter_AddRefs(directory)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } - DebugOnly<bool> exists; - MOZ_ASSERT(NS_SUCCEEDED(directory->Exists(&exists)) && exists); + MOZ_ASSERT(directory, "We're here because the origin directory exists"); - nsCOMPtr<nsISimpleEnumerator> entries; - rv = directory->GetDirectoryEntries(getter_AddRefs(entries)); - NS_ENSURE_SUCCESS(rv, rv); + rv = directory->Append(NS_LITERAL_STRING(ASMJSCACHE_DIRECTORY_NAME)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } - bool hasMore; - while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && - hasMore && !aCanceled) { - nsCOMPtr<nsISupports> entry; - rv = entries->GetNext(getter_AddRefs(entry)); - NS_ENSURE_SUCCESS(rv, rv); + DebugOnly<bool> exists; + MOZ_ASSERT(NS_SUCCEEDED(directory->Exists(&exists)) && exists); - nsCOMPtr<nsIFile> file = do_QueryInterface(entry); - NS_ENSURE_TRUE(file, NS_NOINTERFACE); + nsCOMPtr<nsISimpleEnumerator> entries; + rv = directory->GetDirectoryEntries(getter_AddRefs(entries)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } - int64_t fileSize; - rv = file->GetFileSize(&fileSize); - NS_ENSURE_SUCCESS(rv, rv); + bool hasMore; + while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && + hasMore && !aCanceled) { + nsCOMPtr<nsISupports> entry; + rv = entries->GetNext(getter_AddRefs(entry)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } - MOZ_ASSERT(fileSize >= 0, "Negative size?!"); + nsCOMPtr<nsIFile> file = do_QueryInterface(entry); + if (NS_WARN_IF(!file)) { + return NS_NOINTERFACE; + } - // Since the client is not explicitly storing files, append to database - // usage which represents implicit storage allocation. - aUsageInfo->AppendToDatabaseUsage(uint64_t(fileSize)); + int64_t fileSize; + rv = file->GetFileSize(&fileSize); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; } - NS_ENSURE_SUCCESS(rv, rv); - return NS_OK; + MOZ_ASSERT(fileSize >= 0, "Negative size?!"); + + // Since the client is not explicitly storing files, append to database + // usage which represents implicit storage allocation. + aUsageInfo->AppendToDatabaseUsage(uint64_t(fileSize)); + } + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; } - virtual void - OnOriginClearCompleted(PersistenceType aPersistenceType, - const nsACString& aOrigin) - override - { } + return NS_OK; +} - virtual void - ReleaseIOThreadObjects() override - { } +void +Client::OnOriginClearCompleted(PersistenceType aPersistenceType, + const nsACString& aOrigin) +{ +} - virtual void - AbortOperations(const nsACString& aOrigin) override - { } +void +Client::ReleaseIOThreadObjects() +{ +} - virtual void - AbortOperationsForProcess(ContentParentId aContentParentId) override - { } +void +Client::AbortOperations(const nsACString& aOrigin) +{ +} - virtual void - StartIdleMaintenance() override - { } +void +Client::AbortOperationsForProcess(ContentParentId aContentParentId) +{ +} - virtual void - StopIdleMaintenance() override - { } +void +Client::StartIdleMaintenance() +{ +} - virtual void - ShutdownWorkThreads() override - { } +void +Client::StopIdleMaintenance() +{ +} -private: - nsAutoRefCnt mRefCnt; - NS_DECL_OWNINGTHREAD -}; +void +Client::ShutdownWorkThreads() +{ + AssertIsOnBackgroundThread(); + + if (sLiveParentActors) { + nsIThread* currentThread = NS_GetCurrentThread(); + MOZ_ASSERT(currentThread); -NS_IMPL_ADDREF(asmjscache::Client) -NS_IMPL_RELEASE(asmjscache::Client) + do { + MOZ_ALWAYS_TRUE(NS_ProcessNextEvent(currentThread)); + } while (!sLiveParentActors); + } +} quota::Client* CreateClient() diff --git a/dom/asmjscache/test/test_cachingBasic.html b/dom/asmjscache/test/test_cachingBasic.html index e84fdba8b..f491fe9fa 100644 --- a/dom/asmjscache/test/test_cachingBasic.html +++ b/dom/asmjscache/test/test_cachingBasic.html @@ -44,7 +44,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=929236 evalAsync(code); break; case 1: - ok(!jsFuns.isAsmJSModuleLoadedFromCache(module), 'module not loaded from cache'); + ok(jsFuns.isAsmJSModuleLoadedFromCache(module), 'module loaded from cache'); SimpleTest.finish(); break; default: diff --git a/dom/asmjscache/test/test_cachingMulti.html b/dom/asmjscache/test/test_cachingMulti.html index ca092fda0..ceaf75812 100644 --- a/dom/asmjscache/test/test_cachingMulti.html +++ b/dom/asmjscache/test/test_cachingMulti.html @@ -36,7 +36,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=944821 code2 += "return g" + i + ";\n"; code2 += "}\n"; code2 += "ok(jsFuns.isAsmJSModule(f), 'f is an asm.js module')\n"; - code2 += "if (assertCacheHit) ok(!jsFuns.isAsmJSModuleLoadedFromCache(f), 'cache disabled');\n"; + code2 += "if (assertCacheHit) ok(jsFuns.isAsmJSModuleLoadedFromCache(f), 'cache hit');\n"; code2 += "var gX = f();\n"; code2 += "ok(jsFuns.isAsmJSFunction(gX), 'gX is an asm.js function')\n"; code2 += "ok(gX() === " + i + ", 'gX returns the correct result')\n"; diff --git a/dom/asmjscache/test/test_workers.html b/dom/asmjscache/test/test_workers.html index 992ed785b..6704459f6 100644 --- a/dom/asmjscache/test/test_workers.html +++ b/dom/asmjscache/test/test_workers.html @@ -31,7 +31,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=941830 var workerBlob = new Blob([workerCode], {type:"application/javascript"}); var mainCode = asmjsCode; - mainCode += "ok(!jsFuns.isAsmJSModuleLoadedFromCache(f), 'f is not a cache hit')\n"; + mainCode += "ok(jsFuns.isAsmJSModuleLoadedFromCache(f), 'f is a cache hit')\n"; mainCode += "var g42 = f();\n"; mainCode += "ok(jsFuns.isAsmJSFunction(g42), 'g42 is an asm.js function');\n"; mainCode += "ok(g42() === 42, 'g42 returns the correct result');\n"; diff --git a/dom/base/FileReader.cpp b/dom/base/FileReader.cpp index 003edc61f..63a0ef2ee 100644 --- a/dom/base/FileReader.cpp +++ b/dom/base/FileReader.cpp @@ -452,8 +452,8 @@ FileReader::GetAsText(Blob *aBlob, } } - nsDependentCSubstring data(aFileData, aDataLen); - return nsContentUtils::ConvertStringFromEncoding(encoding, data, aResult); + return nsContentUtils::ConvertStringFromEncoding( + encoding, aFileData, aDataLen, aResult); } nsresult diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index 290af152b..8b20d0196 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -1854,16 +1854,6 @@ Navigator::GetUserAgent(nsPIDOMWindowInner* aWindow, nsIURI* aURI, { MOZ_ASSERT(NS_IsMainThread()); - if (!aIsCallerChrome) { - const nsAdoptingString& override = - mozilla::Preferences::GetString("general.useragent.override"); - - if (override) { - aUserAgent = override; - return NS_OK; - } - } - nsresult rv; nsCOMPtr<nsIHttpProtocolHandler> service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv)); diff --git a/dom/base/moz.build b/dom/base/moz.build index d237acb03..0bc9902e4 100644 --- a/dom/base/moz.build +++ b/dom/base/moz.build @@ -472,7 +472,7 @@ include('/ipc/chromium/chromium-config.mozbuild') FINAL_LIBRARY = 'xul' -if CONFIG['MOZ_BUILD_APP'] in ['browser', 'mobile/android', 'xulrunner']: +if CONFIG['MOZ_BUILD_APP'] in ['mobile/android', 'xulrunner'] or CONFIG['MOZ_PHOENIX']: DEFINES['HAVE_SIDEBAR'] = True if CONFIG['MOZ_X11']: diff --git a/dom/base/nsContentSink.cpp b/dom/base/nsContentSink.cpp index 3d6f069d2..85b3d07bf 100644 --- a/dom/base/nsContentSink.cpp +++ b/dom/base/nsContentSink.cpp @@ -305,6 +305,11 @@ nsContentSink::ProcessHeaderData(nsIAtom* aHeader, const nsAString& aValue, mDocument->SetHeaderData(aHeader, aValue); if (aHeader == nsGkAtoms::setcookie) { + // Don't allow setting cookies in cookie-averse documents. + if (mDocument->IsCookieAverse()) { + return NS_OK; + } + // Note: Necko already handles cookies set via the channel. We can't just // call SetCookie on the channel because we want to do some security checks // here. diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index 29d28f8ce..1cc352685 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -4128,9 +4128,15 @@ nsContentUtils::GetSubdocumentWithOuterWindowId(nsIDocument *aDocument, /* static */ nsresult nsContentUtils::ConvertStringFromEncoding(const nsACString& aEncoding, - const nsACString& aInput, + const char* aInput, + uint32_t aInputLen, nsAString& aOutput) { + CheckedInt32 len = aInputLen; + if (!len.isValid()) { + return NS_ERROR_OUT_OF_MEMORY; + } + nsAutoCString encoding; if (aEncoding.IsEmpty()) { encoding.AssignLiteral("UTF-8"); @@ -4142,7 +4148,7 @@ nsContentUtils::ConvertStringFromEncoding(const nsACString& aEncoding, nsAutoPtr<TextDecoder> decoder(new TextDecoder()); decoder->InitWithEncoding(encoding, false); - decoder->Decode(aInput.BeginReading(), aInput.Length(), false, + decoder->Decode(aInput, len.value(), false, aOutput, rv); return rv.StealNSResult(); } diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index 278fbd008..f688eeecf 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -554,9 +554,17 @@ public: * string (meaning UTF-8) */ static nsresult ConvertStringFromEncoding(const nsACString& aEncoding, - const nsACString& aInput, + const char* aInput, + uint32_t aInputLen, nsAString& aOutput); + static nsresult ConvertStringFromEncoding(const nsACString& aEncoding, + const nsACString& aInput, + nsAString& aOutput) { + return ConvertStringFromEncoding( + aEncoding, aInput.BeginReading(), aInput.Length(), aOutput); + } + /** * Determine whether a buffer begins with a BOM for UTF-8, UTF-16LE, * UTF-16BE diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index 8e6920a0e..4926b6c0a 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -61,6 +61,7 @@ #include "nsGenericHTMLElement.h" #include "mozilla/dom/CDATASection.h" #include "mozilla/dom/ProcessingInstruction.h" +#include "nsDSURIContentListener.h" #include "nsDOMString.h" #include "nsNodeUtils.h" #include "nsLayoutUtils.h" // for GetFrameForPoint @@ -2456,6 +2457,15 @@ nsDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel, NS_ENSURE_SUCCESS(rv, rv); } + // XFO needs to be checked after CSP because it is ignored if + // the CSP defines frame-ancestors. + if (!nsDSURIContentListener::CheckFrameOptions(aChannel, docShell, NodePrincipal())) { + MOZ_LOG(gCspPRLog, LogLevel::Debug, + ("XFO doesn't like frame's ancestry, not loading.")); + // stop! ERROR page! + aChannel->Cancel(NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION); + } + return NS_OK; } diff --git a/dom/base/nsDocument.h b/dom/base/nsDocument.h index 17d936055..fc6749c9f 100644 --- a/dom/base/nsDocument.h +++ b/dom/base/nsDocument.h @@ -1491,7 +1491,6 @@ private: void PostUnblockOnloadEvent(); void DoUnblockOnload(); - nsresult CheckFrameOptions(); nsresult InitCSP(nsIChannel* aChannel); /** diff --git a/dom/base/nsGkAtomList.h b/dom/base/nsGkAtomList.h index 7827ad66b..0b76b2bea 100644 --- a/dom/base/nsGkAtomList.h +++ b/dom/base/nsGkAtomList.h @@ -2230,6 +2230,8 @@ GK_ATOM(scrollbar_end_backward, "scrollbar-end-backward") GK_ATOM(scrollbar_end_forward, "scrollbar-end-forward") GK_ATOM(scrollbar_thumb_proportional, "scrollbar-thumb-proportional") GK_ATOM(overlay_scrollbars, "overlay-scrollbars") +GK_ATOM(windows_accent_color_applies, "windows-accent-color-applies") +GK_ATOM(windows_accent_color_is_dark, "windows-accent-color-is-dark") GK_ATOM(windows_default_theme, "windows-default-theme") GK_ATOM(mac_graphite_theme, "mac-graphite-theme") GK_ATOM(mac_yosemite_theme, "mac-yosemite-theme") @@ -2259,6 +2261,8 @@ GK_ATOM(_moz_scrollbar_end_backward, "-moz-scrollbar-end-backward") GK_ATOM(_moz_scrollbar_end_forward, "-moz-scrollbar-end-forward") GK_ATOM(_moz_scrollbar_thumb_proportional, "-moz-scrollbar-thumb-proportional") GK_ATOM(_moz_overlay_scrollbars, "-moz-overlay-scrollbars") +GK_ATOM(_moz_windows_accent_color_applies, "-moz-windows-accent-color-applies") +GK_ATOM(_moz_windows_accent_color_is_dark, "-moz-windows-accent-color-is-dark") GK_ATOM(_moz_windows_default_theme, "-moz-windows-default-theme") GK_ATOM(_moz_mac_graphite_theme, "-moz-mac-graphite-theme") GK_ATOM(_moz_mac_yosemite_theme, "-moz-mac-yosemite-theme") diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 8ff4b84ce..f784031f6 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -6187,7 +6187,7 @@ nsGlobalWindow::GetScrollMaxY(ErrorResult& aError) FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideBottom), aError, 0); } -CSSIntPoint +CSSPoint nsGlobalWindow::GetScrollXY(bool aDoFlush) { MOZ_ASSERT(IsOuterWindow()); @@ -6211,30 +6211,30 @@ nsGlobalWindow::GetScrollXY(bool aDoFlush) return GetScrollXY(true); } - return sf->GetScrollPositionCSSPixels(); + return CSSPoint::FromAppUnits(scrollPos); } -int32_t +double nsGlobalWindow::GetScrollXOuter() { MOZ_RELEASE_ASSERT(IsOuterWindow()); return GetScrollXY(false).x; } -int32_t +double nsGlobalWindow::GetScrollX(ErrorResult& aError) { FORWARD_TO_OUTER_OR_THROW(GetScrollXOuter, (), aError, 0); } -int32_t +double nsGlobalWindow::GetScrollYOuter() { MOZ_RELEASE_ASSERT(IsOuterWindow()); return GetScrollXY(false).y; } -int32_t +double nsGlobalWindow::GetScrollY(ErrorResult& aError) { FORWARD_TO_OUTER_OR_THROW(GetScrollYOuter, (), aError, 0); diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index eab91c2e4..dbceeab74 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -1050,15 +1050,15 @@ public: void SetInnerHeight(JSContext* aCx, JS::Handle<JS::Value> aValue, mozilla::dom::CallerType aCallerType, mozilla::ErrorResult& aError); - int32_t GetScrollXOuter(); - int32_t GetScrollX(mozilla::ErrorResult& aError); - int32_t GetPageXOffset(mozilla::ErrorResult& aError) + double GetScrollXOuter(); + double GetScrollX(mozilla::ErrorResult& aError); + double GetPageXOffset(mozilla::ErrorResult& aError) { return GetScrollX(aError); } - int32_t GetScrollYOuter(); - int32_t GetScrollY(mozilla::ErrorResult& aError); - int32_t GetPageYOffset(mozilla::ErrorResult& aError) + double GetScrollYOuter(); + double GetScrollY(mozilla::ErrorResult& aError); + double GetPageYOffset(mozilla::ErrorResult& aError) { return GetScrollY(aError); } @@ -1579,7 +1579,7 @@ public: // If aDoFlush is true, we'll flush our own layout; otherwise we'll try to // just flush our parent and only flush ourselves if we think we need to. // Outer windows only. - mozilla::CSSIntPoint GetScrollXY(bool aDoFlush); + mozilla::CSSPoint GetScrollXY(bool aDoFlush); int32_t GetScrollBoundaryOuter(mozilla::Side aSide); diff --git a/dom/base/nsIDocument.h b/dom/base/nsIDocument.h index 5b10c9914..8f35e9ba5 100644 --- a/dom/base/nsIDocument.h +++ b/dom/base/nsIDocument.h @@ -1923,6 +1923,34 @@ public: return mMarkedCCGeneration; } + /** + * Returns whether this document is cookie-averse. See + * https://html.spec.whatwg.org/multipage/dom.html#cookie-averse-document-object + */ + bool IsCookieAverse() const + { + // If we are a document that "has no browsing context." + if (!GetInnerWindow()) { + return true; + } + + // If we are a document "whose URL's scheme is not a network scheme." + // NB: Explicitly allow file: URIs to store cookies. + nsCOMPtr<nsIURI> codebaseURI; + NodePrincipal()->GetURI(getter_AddRefs(codebaseURI)); + + if (!codebaseURI) { + return true; + } + + nsAutoCString scheme; + codebaseURI->GetScheme(scheme); + return !scheme.EqualsLiteral("http") && + !scheme.EqualsLiteral("https") && + !scheme.EqualsLiteral("ftp") && + !scheme.EqualsLiteral("file"); + } + bool IsLoadedAsData() { return mLoadedAsData; diff --git a/dom/base/nsPluginArray.cpp b/dom/base/nsPluginArray.cpp index b9c946ca3..5b9378ae0 100644 --- a/dom/base/nsPluginArray.cpp +++ b/dom/base/nsPluginArray.cpp @@ -372,9 +372,21 @@ nsPluginArray::EnsurePlugins() nsCString permString; nsresult rv = pluginHost->GetPermissionStringForTag(pluginTag, 0, permString); if (rv == NS_OK) { - nsIPrincipal* principal = mWindow->GetExtantDoc()->NodePrincipal(); - nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager(); - permMgr->TestPermissionFromPrincipal(principal, permString.get(), &permission); + nsCOMPtr<nsIDocument> currentDoc = mWindow->GetExtantDoc(); + + // The top-level content document gets the final say on whether or not + // a plugin is going to be hidden or not, regardless of the origin + // that a subframe is hosted at. This is to avoid spamming the user + // with the hidden plugin notification bar when third-party iframes + // attempt to access navigator.plugins after the user has already + // expressed that the top-level document has this permission. + nsCOMPtr<nsIDocument> topDoc = currentDoc->GetTopLevelContentDocument(); + + if (topDoc) { + nsIPrincipal* principal = topDoc->NodePrincipal(); + nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager(); + permMgr->TestPermissionFromPrincipal(principal, permString.get(), &permission); + } } } } diff --git a/dom/base/nsTreeSanitizer.cpp b/dom/base/nsTreeSanitizer.cpp index dc53ea5fa..323c851c1 100644 --- a/dom/base/nsTreeSanitizer.cpp +++ b/dom/base/nsTreeSanitizer.cpp @@ -169,6 +169,7 @@ nsIAtom** const kAttributesHTML[] = { &nsGkAtoms::contextmenu, &nsGkAtoms::controls, &nsGkAtoms::coords, + &nsGkAtoms::crossorigin, &nsGkAtoms::datetime, &nsGkAtoms::dir, &nsGkAtoms::disabled, @@ -185,6 +186,7 @@ nsIAtom** const kAttributesHTML[] = { &nsGkAtoms::hreflang, &nsGkAtoms::icon, &nsGkAtoms::id, + &nsGkAtoms::integrity, &nsGkAtoms::ismap, &nsGkAtoms::itemid, &nsGkAtoms::itemprop, diff --git a/dom/base/test/test_viewport_scroll.html b/dom/base/test/test_viewport_scroll.html index 9b812360b..7db02b781 100644 --- a/dom/base/test/test_viewport_scroll.html +++ b/dom/base/test/test_viewport_scroll.html @@ -28,10 +28,10 @@ function subtest(winProp, elemProp, win, correctElement, elemToSet, otherElem1, win.scrollTo(50, 50); elemToSet[elemProp] = 100; if (elemToSet == correctElement) { - is(win[winProp], 100, "Setting " + elemToSet.name + "." + elemProp + " should scroll"); + is(Math.round(win[winProp]), 100, "Setting " + elemToSet.name + "." + elemProp + " should scroll"); is(elemToSet[elemProp], 100, "Reading back " + elemToSet.name + "." + elemProp + " after scrolling"); } else { - is(win[winProp], 50, "Setting " + elemToSet.name + "." + elemProp + " should not scroll"); + is(Math.round(win[winProp]), 50, "Setting " + elemToSet.name + "." + elemProp + " should not scroll"); is(elemToSet[elemProp], 0, "Reading back " + elemToSet.name + "." + elemProp + " after not scrolling"); } if (otherElem1 == correctElement) { diff --git a/dom/bindings/moz.build b/dom/bindings/moz.build index fadaac69b..eb00482c6 100644 --- a/dom/bindings/moz.build +++ b/dom/bindings/moz.build @@ -139,7 +139,7 @@ FINAL_LIBRARY = 'xul' SPHINX_TREES['webidl'] = 'docs' SPHINX_PYTHON_PACKAGE_DIRS += ['mozwebidlcodegen'] -if CONFIG['MOZ_BUILD_APP'] in ['browser', 'mobile/android', 'xulrunner']: +if CONFIG['MOZ_BUILD_APP'] in ['mobile/android', 'xulrunner'] or CONFIG['MOZ_PHOENIX']: # This is needed for Window.webidl DEFINES['HAVE_SIDEBAR'] = True diff --git a/dom/browser-element/mochitest/browserElement_ScrollEvent.js b/dom/browser-element/mochitest/browserElement_ScrollEvent.js index 5c4b4dcf9..06dc91b86 100644 --- a/dom/browser-element/mochitest/browserElement_ScrollEvent.js +++ b/dom/browser-element/mochitest/browserElement_ScrollEvent.js @@ -16,8 +16,8 @@ function runTest() { iframe.addEventListener("mozbrowserscroll", function(e) { ok(true, "got mozbrowserscroll event."); ok(e.detail, "event.detail is not null."); - ok(e.detail.top === 4000, "top position is correct."); - ok(e.detail.left === 4000, "left position is correct."); + ok(Math.round(e.detail.top) == 4000, "top position is correct."); + ok(Math.round(e.detail.left) == 4000, "left position is correct."); SimpleTest.finish(); }); diff --git a/dom/crypto/WebCryptoTask.cpp b/dom/crypto/WebCryptoTask.cpp index 57a7da186..f5fc7b5bc 100644 --- a/dom/crypto/WebCryptoTask.cpp +++ b/dom/crypto/WebCryptoTask.cpp @@ -716,6 +716,11 @@ private: return NS_ERROR_DOM_INVALID_ACCESS_ERR; } + // Check whether the integer addition would overflow. + if (std::numeric_limits<CryptoBuffer::size_type>::max() - 16 < mData.Length()) { + return NS_ERROR_DOM_DATA_ERR; + } + // Initialize the output buffer (enough space for padding / a full tag) uint32_t dataLen = mData.Length(); uint32_t maxLen = dataLen + 16; diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp index b64761270..e81cd20bc 100644 --- a/dom/html/HTMLMediaElement.cpp +++ b/dom/html/HTMLMediaElement.cpp @@ -4550,6 +4550,11 @@ void HTMLMediaElement::FirstFrameLoaded() ChangeDelayLoadStatus(false); + // FIXME: This is a workaround for DoneCreatingElement() not being called + // at the appropriate time when cloning elements, to preserve the "muted" + // status. See bug 1424871. + if (HasAttr(kNameSpaceID_None, nsGkAtoms::muted)) SetMuted(true); + if (mDecoder && mAllowSuspendAfterFirstFrame && mPaused && !HasAttr(kNameSpaceID_None, nsGkAtoms::autoplay) && mPreloadAction == HTMLMediaElement::PRELOAD_METADATA) { diff --git a/dom/html/nsHTMLDocument.cpp b/dom/html/nsHTMLDocument.cpp index 5e6302941..7d66aab04 100644 --- a/dom/html/nsHTMLDocument.cpp +++ b/dom/html/nsHTMLDocument.cpp @@ -1255,6 +1255,11 @@ nsHTMLDocument::GetCookie(nsAString& aCookie, ErrorResult& rv) rv.Throw(NS_ERROR_DOM_SECURITY_ERR); return; } + + // If the document is a cookie-averse document, return an empty string. + if (IsCookieAverse()) { + return; + } // not having a cookie service isn't an error nsCOMPtr<nsICookieService> service = do_GetService(NS_COOKIESERVICE_CONTRACTID); @@ -1310,6 +1315,11 @@ nsHTMLDocument::SetCookie(const nsAString& aCookie, ErrorResult& rv) return; } + // If the document is a cookie-averse document, do nothing. + if (IsCookieAverse()) { + return; + } + // not having a cookie service isn't an error nsCOMPtr<nsICookieService> service = do_GetService(NS_COOKIESERVICE_CONTRACTID); if (service && mDocumentURI) { diff --git a/dom/indexedDB/ActorsParent.cpp b/dom/indexedDB/ActorsParent.cpp index 702d5c985..9d4e72f2f 100644 --- a/dom/indexedDB/ActorsParent.cpp +++ b/dom/indexedDB/ActorsParent.cpp @@ -7,6 +7,7 @@ #include "ActorsParent.h" #include <algorithm> +#include <stdint.h> // UINTPTR_MAX, uintptr_t #include "FileInfo.h" #include "FileManager.h" #include "IDBObjectStore.h" @@ -859,6 +860,11 @@ ReadCompressedIndexDataValuesFromBlob(const uint8_t* aBlobData, "ReadCompressedIndexDataValuesFromBlob", js::ProfileEntry::Category::STORAGE); + if (uintptr_t(aBlobData) > UINTPTR_MAX - aBlobDataLength) { + IDB_REPORT_INTERNAL_ERR(); + return NS_ERROR_FILE_CORRUPTED; + } + const uint8_t* blobDataIter = aBlobData; const uint8_t* blobDataEnd = aBlobData + aBlobDataLength; @@ -878,7 +884,8 @@ ReadCompressedIndexDataValuesFromBlob(const uint8_t* aBlobData, if (NS_WARN_IF(blobDataIter == blobDataEnd) || NS_WARN_IF(keyBufferLength > uint64_t(UINT32_MAX)) || - NS_WARN_IF(blobDataIter + keyBufferLength > blobDataEnd)) { + NS_WARN_IF(keyBufferLength > uintptr_t(blobDataEnd)) || + NS_WARN_IF(blobDataIter > blobDataEnd - keyBufferLength)) { IDB_REPORT_INTERNAL_ERR(); return NS_ERROR_FILE_CORRUPTED; } @@ -896,7 +903,8 @@ ReadCompressedIndexDataValuesFromBlob(const uint8_t* aBlobData, if (sortKeyBufferLength > 0) { if (NS_WARN_IF(blobDataIter == blobDataEnd) || NS_WARN_IF(sortKeyBufferLength > uint64_t(UINT32_MAX)) || - NS_WARN_IF(blobDataIter + sortKeyBufferLength > blobDataEnd)) { + NS_WARN_IF(sortKeyBufferLength > uintptr_t(blobDataEnd)) || + NS_WARN_IF(blobDataIter > blobDataEnd - sortKeyBufferLength)) { IDB_REPORT_INTERNAL_ERR(); return NS_ERROR_FILE_CORRUPTED; } @@ -18177,11 +18185,25 @@ QuotaClient::ShutdownWorkThreads() mShutdownRequested = true; + // Shutdown maintenance thread pool (this spins the event loop until all + // threads are gone). This should release any maintenance related quota + // objects. if (mMaintenanceThreadPool) { mMaintenanceThreadPool->Shutdown(); mMaintenanceThreadPool = nullptr; } + // Let any runnables dispatched from dying maintenance threads to be + // processed. This should release any maintenance related directory locks. + if (mCurrentMaintenance) { + nsIThread* currentThread = NS_GetCurrentThread(); + MOZ_ASSERT(currentThread); + + do { + MOZ_ALWAYS_TRUE(NS_ProcessNextEvent(currentThread)); + } while (!mCurrentMaintenance); + } + RefPtr<ConnectionPool> connectionPool = gConnectionPool.get(); if (connectionPool) { connectionPool->Shutdown(); @@ -18401,7 +18423,8 @@ Maintenance::Start() AssertIsOnBackgroundThread(); MOZ_ASSERT(mState == State::Initial); - if (IsAborted()) { + if (NS_WARN_IF(QuotaClient::IsShuttingDownOnBackgroundThread()) || + IsAborted()) { return NS_ERROR_ABORT; } @@ -18425,7 +18448,8 @@ Maintenance::CreateIndexedDatabaseManager() MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mState == State::CreateIndexedDatabaseManager); - if (IsAborted()) { + if (NS_WARN_IF(QuotaClient::IsShuttingDownOnNonBackgroundThread()) || + IsAborted()) { return NS_ERROR_ABORT; } @@ -18450,7 +18474,8 @@ Maintenance::OpenDirectory() MOZ_ASSERT(!mDirectoryLock); MOZ_ASSERT(QuotaManager::Get()); - if (IsAborted()) { + if (NS_WARN_IF(QuotaClient::IsShuttingDownOnBackgroundThread()) || + IsAborted()) { return NS_ERROR_ABORT; } @@ -18474,7 +18499,8 @@ Maintenance::DirectoryOpen() MOZ_ASSERT(mState == State::DirectoryOpenPending); MOZ_ASSERT(mDirectoryLock); - if (IsAborted()) { + if (NS_WARN_IF(QuotaClient::IsShuttingDownOnBackgroundThread()) || + IsAborted()) { return NS_ERROR_ABORT; } @@ -18504,7 +18530,8 @@ Maintenance::DirectoryWork() // We have to find all database files that match any persistence type and any // origin. We ignore anything out of the ordinary for now. - if (IsAborted()) { + if (NS_WARN_IF(QuotaClient::IsShuttingDownOnNonBackgroundThread()) || + IsAborted()) { return NS_ERROR_ABORT; } @@ -18691,8 +18718,10 @@ Maintenance::DirectoryWork() continue; } + nsCString suffix; nsCString group; nsCString origin; + bool isApp; nsTArray<nsString> databasePaths; while (true) { @@ -18748,19 +18777,18 @@ Maintenance::DirectoryWork() // Found a database. if (databasePaths.IsEmpty()) { + MOZ_ASSERT(suffix.IsEmpty()); MOZ_ASSERT(group.IsEmpty()); MOZ_ASSERT(origin.IsEmpty()); int64_t dummyTimeStamp; - nsCString dummySuffix; - bool dummyIsApp; if (NS_WARN_IF(NS_FAILED( quotaManager->GetDirectoryMetadata2(originDir, &dummyTimeStamp, - dummySuffix, + suffix, group, origin, - &dummyIsApp)))) { + &isApp)))) { // Not much we can do here... continue; } @@ -18776,6 +18804,22 @@ Maintenance::DirectoryWork() group, origin, Move(databasePaths))); + + nsCOMPtr<nsIFile> directory; + + // Idle maintenance may occur before origin is initailized. + // Ensure origin is initialized first. It will initialize all origins + // for temporary storage including IDB origins. + rv = quotaManager->EnsureOriginIsInitialized(persistenceType, + suffix, + group, + origin, + isApp, + getter_AddRefs(directory)); + + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } } } } @@ -18827,6 +18871,11 @@ Maintenance::BeginDatabaseMaintenance() } }; + if (NS_WARN_IF(QuotaClient::IsShuttingDownOnBackgroundThread()) || + IsAborted()) { + return NS_ERROR_ABORT; + } + RefPtr<nsThreadPool> threadPool; for (DirectoryInfo& directoryInfo : mDirectoryInfos) { @@ -19013,6 +19062,11 @@ DatabaseMaintenance::PerformMaintenanceOnDatabase() } }; + if (NS_WARN_IF(QuotaClient::IsShuttingDownOnNonBackgroundThread()) || + mMaintenance->IsAborted()) { + return; + } + nsCOMPtr<nsIFile> databaseFile = GetFileForPath(mDatabasePath); MOZ_ASSERT(databaseFile); @@ -19029,10 +19083,6 @@ DatabaseMaintenance::PerformMaintenanceOnDatabase() AutoClose autoClose(connection); - if (mMaintenance->IsAborted()) { - return; - } - AutoProgressHandler progressHandler(mMaintenance); if (NS_WARN_IF(NS_FAILED(progressHandler.Register(connection)))) { return; @@ -19051,20 +19101,12 @@ DatabaseMaintenance::PerformMaintenanceOnDatabase() return; } - if (mMaintenance->IsAborted()) { - return; - } - MaintenanceAction maintenanceAction; rv = DetermineMaintenanceAction(connection, databaseFile, &maintenanceAction); if (NS_WARN_IF(NS_FAILED(rv))) { return; } - if (mMaintenance->IsAborted()) { - return; - } - switch (maintenanceAction) { case MaintenanceAction::Nothing: break; @@ -19091,6 +19133,11 @@ DatabaseMaintenance::CheckIntegrity(mozIStorageConnection* aConnection, MOZ_ASSERT(aConnection); MOZ_ASSERT(aOk); + if (NS_WARN_IF(QuotaClient::IsShuttingDownOnNonBackgroundThread()) || + mMaintenance->IsAborted()) { + return NS_ERROR_ABORT; + } + nsresult rv; // First do a full integrity_check. Scope statements tightly here because @@ -19208,6 +19255,11 @@ DatabaseMaintenance::DetermineMaintenanceAction( MOZ_ASSERT(aDatabaseFile); MOZ_ASSERT(aMaintenanceAction); + if (NS_WARN_IF(QuotaClient::IsShuttingDownOnNonBackgroundThread()) || + mMaintenance->IsAborted()) { + return NS_ERROR_ABORT; + } + int32_t schemaVersion; nsresult rv = aConnection->GetSchemaVersion(&schemaVersion); if (NS_WARN_IF(NS_FAILED(rv))) { @@ -19417,6 +19469,11 @@ DatabaseMaintenance::IncrementalVacuum(mozIStorageConnection* aConnection) MOZ_ASSERT(!IsOnBackgroundThread()); MOZ_ASSERT(aConnection); + if (NS_WARN_IF(QuotaClient::IsShuttingDownOnNonBackgroundThread()) || + mMaintenance->IsAborted()) { + return; + } + nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING( "PRAGMA incremental_vacuum;" )); @@ -19434,6 +19491,11 @@ DatabaseMaintenance::FullVacuum(mozIStorageConnection* aConnection, MOZ_ASSERT(aConnection); MOZ_ASSERT(aDatabaseFile); + if (NS_WARN_IF(QuotaClient::IsShuttingDownOnNonBackgroundThread()) || + mMaintenance->IsAborted()) { + return; + } + nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING( "VACUUM;" )); diff --git a/dom/interfaces/security/nsIContentSecurityPolicy.idl b/dom/interfaces/security/nsIContentSecurityPolicy.idl index ade5b1243..51ca46f2a 100644 --- a/dom/interfaces/security/nsIContentSecurityPolicy.idl +++ b/dom/interfaces/security/nsIContentSecurityPolicy.idl @@ -98,6 +98,11 @@ interface nsIContentSecurityPolicy : nsISerializable readonly attribute bool blockAllMixedContent; /** + * Returns whether this policy enforces the frame-ancestors directive. + */ + readonly attribute bool enforcesFrameAncestors; + + /** * Obtains the referrer policy (as integer) for this browsing context as * specified in CSP. If there are multiple policies and... * - only one sets a referrer policy: that policy is returned diff --git a/dom/ipc/ContentProcess.cpp b/dom/ipc/ContentProcess.cpp index 66125f332..2413d8808 100644 --- a/dom/ipc/ContentProcess.cpp +++ b/dom/ipc/ContentProcess.cpp @@ -8,10 +8,6 @@ #include "ContentProcess.h" -#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX) -#include "mozilla/WindowsVersion.h" -#endif - #if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX) #include <stdlib.h> #endif @@ -33,9 +29,8 @@ static bool IsSandboxTempDirRequired() { // On Windows, a sandbox-writable temp directory is only used - // for Vista or later with sandbox pref level >= 1. - return (IsVistaOrLater() && - (Preferences::GetInt("security.sandbox.content.level") >= 1)); + // when sandbox pref level >= 1. + return Preferences::GetInt("security.sandbox.content.level") >= 1; } static void diff --git a/dom/locales/en-US/chrome/security/csp.properties b/dom/locales/en-US/chrome/security/csp.properties index fc7fc04ba..4124ef8aa 100644 --- a/dom/locales/en-US/chrome/security/csp.properties +++ b/dom/locales/en-US/chrome/security/csp.properties @@ -91,6 +91,10 @@ ignoringReportOnlyDirective = Ignoring sandbox directive when delivered in a rep # LOCALIZATION NOTE (deprecatedReferrerDirective): # %1$S is the value of the deprecated Referrer Directive. deprecatedReferrerDirective = Referrer Directive ‘%1$S’ has been deprecated. Please use the Referrer-Policy header instead. +# LOCALIZATION NOTE (IgnoringSrcBecauseOfDirective): +# %1$S is the name of the src that is ignored. +# %2$S is the name of the directive that causes the src to be ignored. +IgnoringSrcBecauseOfDirective=Ignoring ‘%1$S’ because of ‘%2$S’ directive. # CSP Errors: # LOCALIZATION NOTE (couldntParseInvalidSource): diff --git a/dom/media/Benchmark.cpp b/dom/media/Benchmark.cpp index a4761f1b1..1ba6e561c 100644 --- a/dom/media/Benchmark.cpp +++ b/dom/media/Benchmark.cpp @@ -22,7 +22,7 @@ namespace mozilla { // Update this version number to force re-running the benchmark. Such as when // an improvement to FFVP9 or LIBVPX is deemed worthwhile. -const uint32_t VP9Benchmark::sBenchmarkVersionID = 1; +const uint32_t VP9Benchmark::sBenchmarkVersionID = 2; const char* VP9Benchmark::sBenchmarkFpsPref = "media.benchmark.vp9.fps"; const char* VP9Benchmark::sBenchmarkFpsVersionCheck = "media.benchmark.vp9.versioncheck"; diff --git a/dom/media/DecoderDoctorDiagnostics.cpp b/dom/media/DecoderDoctorDiagnostics.cpp index 91c2d8dfb..778e8c4c5 100644 --- a/dom/media/DecoderDoctorDiagnostics.cpp +++ b/dom/media/DecoderDoctorDiagnostics.cpp @@ -576,16 +576,9 @@ DecoderDoctorDocumentWatcher::SynthesizeAnalysis() // going through expected decoders from most to least desirable. #if defined(XP_WIN) if (!formatsRequiringWMF.IsEmpty()) { - if (IsVistaOrLater()) { - DD_INFO("DecoderDoctorDocumentWatcher[%p, doc=%p]::SynthesizeAnalysis() - unplayable formats: %s -> Cannot play media because WMF was not found", - this, mDocument, NS_ConvertUTF16toUTF8(formatsRequiringWMF).get()); - ReportAnalysis(mDocument, sMediaWMFNeeded, false, formatsRequiringWMF); - } else { - DD_INFO("DecoderDoctorDocumentWatcher[%p, doc=%p]::SynthesizeAnalysis() - unplayable formats: %s -> Cannot play media before Windows Vista", - this, mDocument, NS_ConvertUTF16toUTF8(formatsRequiringWMF).get()); - ReportAnalysis(mDocument, sMediaUnsupportedBeforeWindowsVista, - false, formatsRequiringWMF); - } + DD_INFO("DecoderDoctorDocumentWatcher[%p, doc=%p]::SynthesizeAnalysis() - unplayable formats: %s -> Cannot play media because WMF was not found", + this, mDocument, NS_ConvertUTF16toUTF8(formatsRequiringWMF).get()); + ReportAnalysis(mDocument, sMediaWMFNeeded, false, formatsRequiringWMF); return; } #endif diff --git a/dom/media/MediaManager.cpp b/dom/media/MediaManager.cpp index 96e2c23e0..97a6855d9 100644 --- a/dom/media/MediaManager.cpp +++ b/dom/media/MediaManager.cpp @@ -1853,20 +1853,18 @@ MediaManager::GetNonE10sParent() MediaManager::StartupInit() { #ifdef WIN32 - if (IsVistaOrLater() && !IsWin8OrLater()) { - // Bug 1107702 - Older Windows fail in GetAdaptersInfo (and others) if the - // first(?) call occurs after the process size is over 2GB (kb/2588507). - // Attempt to 'prime' the pump by making a call at startup. - unsigned long out_buf_len = sizeof(IP_ADAPTER_INFO); - PIP_ADAPTER_INFO pAdapterInfo = (IP_ADAPTER_INFO *) moz_xmalloc(out_buf_len); - if (GetAdaptersInfo(pAdapterInfo, &out_buf_len) == ERROR_BUFFER_OVERFLOW) { - free(pAdapterInfo); - pAdapterInfo = (IP_ADAPTER_INFO *) moz_xmalloc(out_buf_len); - GetAdaptersInfo(pAdapterInfo, &out_buf_len); - } - if (pAdapterInfo) { - free(pAdapterInfo); - } + // Bug 1107702 - Some Windows versions fail in GetAdaptersInfo (and others) + // if the first(?) call occurs after the process size is over 2GB (kb/2588507). + // Attempt to 'prime' the pump by making a call at startup. + unsigned long out_buf_len = sizeof(IP_ADAPTER_INFO); + PIP_ADAPTER_INFO pAdapterInfo = (IP_ADAPTER_INFO *) moz_xmalloc(out_buf_len); + if (GetAdaptersInfo(pAdapterInfo, &out_buf_len) == ERROR_BUFFER_OVERFLOW) { + free(pAdapterInfo); + pAdapterInfo = (IP_ADAPTER_INFO *) moz_xmalloc(out_buf_len); + GetAdaptersInfo(pAdapterInfo, &out_buf_len); + } + if (pAdapterInfo) { + free(pAdapterInfo); } #endif } @@ -2130,19 +2128,11 @@ if (privileged) { case MediaSourceEnum::Application: case MediaSourceEnum::Window: // Deny screensharing request if support is disabled, or - // the requesting document is not from a host on the whitelist, or - // we're on WinXP until proved that it works + // the requesting document is not from a host on the whitelist if (!Preferences::GetBool(((videoType == MediaSourceEnum::Browser)? "media.getusermedia.browser.enabled" : "media.getusermedia.screensharing.enabled"), false) || -#if defined(XP_WIN) - ( - // Allow tab sharing for all platforms including XP - (videoType != MediaSourceEnum::Browser) && - !Preferences::GetBool("media.getusermedia.screensharing.allow_on_old_platforms", - false) && !IsVistaOrLater()) || -#endif (!privileged && !HostIsHttps(*docURI))) { RefPtr<MediaStreamError> error = new MediaStreamError(aWindow, diff --git a/dom/media/eme/MediaKeySystemAccess.cpp b/dom/media/eme/MediaKeySystemAccess.cpp index 7007d3a03..4cff464e7 100644 --- a/dom/media/eme/MediaKeySystemAccess.cpp +++ b/dom/media/eme/MediaKeySystemAccess.cpp @@ -140,26 +140,12 @@ MediaKeySystemAccess::GetKeySystemStatus(const nsAString& aKeySystem, aOutMessage = NS_LITERAL_CSTRING("Adobe EME disabled"); return MediaKeySystemStatus::Cdm_disabled; } -#ifdef XP_WIN - // Win Vista and later only. - if (!IsVistaOrLater()) { - aOutMessage = NS_LITERAL_CSTRING("Minimum Windows version (Vista) not met for Adobe EME"); - return MediaKeySystemStatus::Cdm_not_supported; - } -#endif return EnsureCDMInstalled(aKeySystem, aOutMessage); } } if (IsWidevineKeySystem(aKeySystem)) { if (Preferences::GetBool("media.gmp-widevinecdm.visible", false)) { -#ifdef XP_WIN - // Win Vista and later only. - if (!IsVistaOrLater()) { - aOutMessage = NS_LITERAL_CSTRING("Minimum Windows version (Vista) not met for Widevine EME"); - return MediaKeySystemStatus::Cdm_not_supported; - } -#endif if (!Preferences::GetBool("media.gmp-widevinecdm.enabled", false)) { aOutMessage = NS_LITERAL_CSTRING("Widevine EME disabled"); return MediaKeySystemStatus::Cdm_disabled; diff --git a/dom/media/fmp4/MP4Decoder.cpp b/dom/media/fmp4/MP4Decoder.cpp index 4cf07ddbd..fdd6f2c7e 100644 --- a/dom/media/fmp4/MP4Decoder.cpp +++ b/dom/media/fmp4/MP4Decoder.cpp @@ -52,14 +52,6 @@ IsWhitelistedH264Codec(const nsAString& aCodec) return false; } -#ifdef XP_WIN - // Disable 4k video on windows vista since it performs poorly. - if (!IsWin7OrLater() && - level >= H264_LEVEL_5) { - return false; - } -#endif - // Just assume what we can play on all platforms the codecs/formats that // WMF can play, since we don't have documentation about what other // platforms can play... According to the WMF documentation: diff --git a/dom/media/gtest/TestGMPCrossOrigin.cpp b/dom/media/gtest/TestGMPCrossOrigin.cpp index 036282153..33ac98388 100644 --- a/dom/media/gtest/TestGMPCrossOrigin.cpp +++ b/dom/media/gtest/TestGMPCrossOrigin.cpp @@ -1521,11 +1521,6 @@ TEST(GeckoMediaPlugins, GMPPluginVoucher) { #if defined(XP_WIN) TEST(GeckoMediaPlugins, GMPOutputProtection) { - // Output Protection is not available pre-Vista. - if (!IsVistaOrLater()) { - return; - } - RefPtr<GMPStorageTest> runner = new GMPStorageTest(); runner->DoTest(&GMPStorageTest::TestOutputProtection); } diff --git a/dom/media/platforms/PDMFactory.cpp b/dom/media/platforms/PDMFactory.cpp index a72d910f5..c1e58fdc2 100644 --- a/dom/media/platforms/PDMFactory.cpp +++ b/dom/media/platforms/PDMFactory.cpp @@ -47,10 +47,6 @@ #include "MP4Decoder.h" #include "mozilla/dom/RemoteVideoDecoder.h" -#ifdef XP_WIN -#include "mozilla/WindowsVersion.h" -#endif - #include "mp4_demuxer/H264.h" namespace mozilla { @@ -367,16 +363,7 @@ PDMFactory::CreatePDMs() } #endif #ifdef XP_WIN - if (MediaPrefs::PDMWMFEnabled() && IsVistaOrLater() && !IsWin7AndPre2000Compatible()) { - // *Only* use WMF on Vista and later, as if Firefox is run in Windows 95 - // compatibility mode on Windows 7 (it does happen!) we may crash trying - // to startup WMF. So we need to detect the OS version here, as in - // compatibility mode IsVistaOrLater() and friends behave as if we're on - // the emulated version of Windows. See bug 1279171. - // Additionally, we don't want to start the RemoteDecoderModule if we - // expect it's not going to work (i.e. on Windows older than Vista). - // IsWin7AndPre2000Compatible() uses GetVersionEx as the user specified OS version can - // be reflected when compatibility mode is in effect. + if (MediaPrefs::PDMWMFEnabled()) { m = new WMFDecoderModule(); RefPtr<PlatformDecoderModule> remote = new dom::RemoteDecoderModule(m); StartupPDM(remote); diff --git a/dom/media/platforms/wmf/WMF.h b/dom/media/platforms/wmf/WMF.h index 5ede0d361..6988ef083 100644 --- a/dom/media/platforms/wmf/WMF.h +++ b/dom/media/platforms/wmf/WMF.h @@ -7,18 +7,6 @@ #ifndef WMF_H_ #define WMF_H_ -#if WINVER < _WIN32_WINNT_WIN7 -#error \ -You must include WMF.h before including mozilla headers, \ -otherwise mozconfig.h will be included \ -and that sets WINVER to WinXP, \ -which makes Windows Media Foundation unavailable. -#endif - -#pragma push_macro("WINVER") -#undef WINVER -#define WINVER _WIN32_WINNT_WIN7 - #include <windows.h> #include <mfapi.h> #include <mfidl.h> @@ -35,7 +23,7 @@ which makes Windows Media Foundation unavailable. #include <codecapi.h> // The Windows headers helpfully declare min and max macros, which don't -// compile in the prescence of std::min and std::max and unified builds. +// compile in the presence of std::min and std::max and unified builds. // So undef them here. #ifdef min #undef min @@ -97,8 +85,4 @@ HRESULT MFCreateDXGISurfaceBuffer(REFIID riid, } // end namespace wmf } // end namespace mozilla - - -#pragma pop_macro("WINVER") - #endif diff --git a/dom/media/platforms/wmf/WMFUtils.cpp b/dom/media/platforms/wmf/WMFUtils.cpp index 8aec8a8af..055012d0f 100644 --- a/dom/media/platforms/wmf/WMFUtils.cpp +++ b/dom/media/platforms/wmf/WMFUtils.cpp @@ -205,31 +205,17 @@ LoadDLLs() HRESULT MFStartup() { - if (!IsVistaOrLater() || IsWin7AndPre2000Compatible()) { - // *Only* use WMF on Vista and later, as if Firefox is run in Windows 95 - // compatibility mode on Windows 7 (it does happen!) we may crash trying - // to startup WMF. So we need to detect the OS version here, as in - // compatibility mode IsVistaOrLater() and friends behave as if we're on - // the emulated version of Windows. See bug 1279171. - // Using GetVersionEx API which takes compatibility mode into account. - return E_FAIL; - } - HRESULT hr = LoadDLLs(); if (FAILED(hr)) { return hr; } - const int MF_VISTA_VERSION = (0x0001 << 16 | MF_API_VERSION); const int MF_WIN7_VERSION = (0x0002 << 16 | MF_API_VERSION); // decltype is unusable for functions having default parameters DECL_FUNCTION_PTR(MFStartup, ULONG, DWORD); ENSURE_FUNCTION_PTR_(MFStartup, Mfplat.dll) - if (!IsWin7OrLater()) - return MFStartupPtr(MF_VISTA_VERSION, MFSTARTUP_FULL); - else - return MFStartupPtr(MF_WIN7_VERSION, MFSTARTUP_FULL); + return MFStartupPtr(MF_WIN7_VERSION, MFSTARTUP_FULL); } HRESULT diff --git a/dom/media/systemservices/MediaParent.cpp b/dom/media/systemservices/MediaParent.cpp index 109a44a28..89a495f6a 100644 --- a/dom/media/systemservices/MediaParent.cpp +++ b/dom/media/systemservices/MediaParent.cpp @@ -37,6 +37,7 @@ mozilla::LazyLogModule gMediaParentLog("MediaParent"); namespace mozilla { namespace media { +StaticMutex sOriginKeyStoreMutex; static OriginKeyStore* sOriginKeyStore = nullptr; class OriginKeyStore : public nsISupports @@ -332,6 +333,7 @@ class OriginKeyStore : public nsISupports private: virtual ~OriginKeyStore() { + StaticMutexAutoLock lock(sOriginKeyStoreMutex); sOriginKeyStore = nullptr; LOG((__FUNCTION__)); } @@ -340,6 +342,7 @@ public: static OriginKeyStore* Get() { MOZ_ASSERT(NS_IsMainThread()); + StaticMutexAutoLock lock(sOriginKeyStoreMutex); if (!sOriginKeyStore) { sOriginKeyStore = new OriginKeyStore(); } @@ -384,8 +387,8 @@ Parent<Super>::RecvGetOriginKey(const uint32_t& aRequestId, return false; } - // Then over to stream-transport thread to do the actual file io. - // Stash a pledge to hold the answer and get an id for this request. + // Then over to stream-transport thread (a thread pool) to do the actual + // file io. Stash a pledge to hold the answer and get an id for this request. RefPtr<Pledge<nsCString>> p = new Pledge<nsCString>(); uint32_t id = mOutstandingPledges.Append(*p); @@ -397,12 +400,17 @@ Parent<Super>::RecvGetOriginKey(const uint32_t& aRequestId, rv = sts->Dispatch(NewRunnableFrom([this, that, id, profileDir, aOrigin, aPrivateBrowsing, aPersist]() -> nsresult { MOZ_ASSERT(!NS_IsMainThread()); - mOriginKeyStore->mOriginKeys.SetProfileDir(profileDir); + StaticMutexAutoLock lock(sOriginKeyStoreMutex); + if (!sOriginKeyStore) { + return NS_ERROR_FAILURE; + } + sOriginKeyStore->mOriginKeys.SetProfileDir(profileDir); + nsCString result; if (aPrivateBrowsing) { - mOriginKeyStore->mPrivateBrowsingOriginKeys.GetOriginKey(aOrigin, result); + sOriginKeyStore->mPrivateBrowsingOriginKeys.GetOriginKey(aOrigin, result); } else { - mOriginKeyStore->mOriginKeys.GetOriginKey(aOrigin, result, aPersist); + sOriginKeyStore->mOriginKeys.GetOriginKey(aOrigin, result, aPersist); } // Pass result back to main thread. @@ -450,19 +458,21 @@ Parent<Super>::RecvSanitizeOriginKeys(const uint64_t& aSinceWhen, if (NS_WARN_IF(NS_FAILED(rv))) { return false; } - // Over to stream-transport thread to do the file io. + // Over to stream-transport thread (a thread pool) to do the file io. nsCOMPtr<nsIEventTarget> sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID); MOZ_ASSERT(sts); - RefPtr<OriginKeyStore> store(mOriginKeyStore); - - rv = sts->Dispatch(NewRunnableFrom([profileDir, store, aSinceWhen, + rv = sts->Dispatch(NewRunnableFrom([profileDir, aSinceWhen, aOnlyPrivateBrowsing]() -> nsresult { MOZ_ASSERT(!NS_IsMainThread()); - store->mPrivateBrowsingOriginKeys.Clear(aSinceWhen); + StaticMutexAutoLock lock(sOriginKeyStoreMutex); + if (!sOriginKeyStore) { + return NS_ERROR_FAILURE; + } + sOriginKeyStore->mPrivateBrowsingOriginKeys.Clear(aSinceWhen); if (!aOnlyPrivateBrowsing) { - store->mOriginKeys.SetProfileDir(profileDir); - store->mOriginKeys.Clear(aSinceWhen); + sOriginKeyStore->mOriginKeys.SetProfileDir(profileDir); + sOriginKeyStore->mOriginKeys.Clear(aSinceWhen); } return NS_OK; }), NS_DISPATCH_NORMAL); diff --git a/dom/media/webrtc/MediaEngineWebRTC.cpp b/dom/media/webrtc/MediaEngineWebRTC.cpp index 522f23f61..1a2dc9a04 100644 --- a/dom/media/webrtc/MediaEngineWebRTC.cpp +++ b/dom/media/webrtc/MediaEngineWebRTC.cpp @@ -268,11 +268,7 @@ MediaEngineWebRTC::EnumerateVideoDevices(dom::MediaSourceEnum aMediaSource, bool MediaEngineWebRTC::SupportsDuplex() { -#ifndef XP_WIN return mFullDuplex; -#else - return IsVistaOrLater() && mFullDuplex; -#endif } void diff --git a/dom/plugins/base/nsPluginHost.cpp b/dom/plugins/base/nsPluginHost.cpp index 6ee23f38b..bd71d6f65 100644 --- a/dom/plugins/base/nsPluginHost.cpp +++ b/dom/plugins/base/nsPluginHost.cpp @@ -2024,45 +2024,9 @@ struct CompareFilesByTime } // namespace -bool -nsPluginHost::ShouldAddPlugin(nsPluginTag* aPluginTag) -{ -#if defined(XP_WIN) && (defined(__x86_64__) || defined(_M_X64)) - // On 64-bit windows, the only plugins we should load are flash and - // silverlight. Use library filename and MIME type to check. - if (StringBeginsWith(aPluginTag->FileName(), NS_LITERAL_CSTRING("NPSWF"), nsCaseInsensitiveCStringComparator()) && - (aPluginTag->HasMimeType(NS_LITERAL_CSTRING("application/x-shockwave-flash")) || - aPluginTag->HasMimeType(NS_LITERAL_CSTRING("application/x-shockwave-flash-test")))) { - return true; - } - if (StringBeginsWith(aPluginTag->FileName(), NS_LITERAL_CSTRING("npctrl"), nsCaseInsensitiveCStringComparator()) && - (aPluginTag->HasMimeType(NS_LITERAL_CSTRING("application/x-silverlight-test")) || - aPluginTag->HasMimeType(NS_LITERAL_CSTRING("application/x-silverlight-2")) || - aPluginTag->HasMimeType(NS_LITERAL_CSTRING("application/x-silverlight")))) { - return true; - } - // Accept the test plugin MIME types, so mochitests still work. - if (aPluginTag->HasMimeType(NS_LITERAL_CSTRING("application/x-test")) || - aPluginTag->HasMimeType(NS_LITERAL_CSTRING("application/x-Second-Test")) || - aPluginTag->HasMimeType(NS_LITERAL_CSTRING("application/x-java-test"))) { - return true; - } -#ifdef PLUGIN_LOGGING - PLUGIN_LOG(PLUGIN_LOG_NORMAL, - ("ShouldAddPlugin : Ignoring non-flash plugin library %s\n", aPluginTag->FileName().get())); -#endif // PLUGIN_LOGGING - return false; -#else - return true; -#endif // defined(XP_WIN) && (defined(__x86_64__) || defined(_M_X64)) -} - void nsPluginHost::AddPluginTag(nsPluginTag* aPluginTag) { - if (!ShouldAddPlugin(aPluginTag)) { - return; - } aPluginTag->mNext = mPlugins; mPlugins = aPluginTag; @@ -2078,22 +2042,6 @@ nsPluginHost::AddPluginTag(nsPluginTag* aPluginTag) } } -static bool -PluginInfoIsFlash(const nsPluginInfo& info) -{ - if (!info.fName || strcmp(info.fName, "Shockwave Flash") != 0) { - return false; - } - for (uint32_t i = 0; i < info.fVariantCount; ++i) { - if (info.fMimeTypeArray[i] && - (!strcmp(info.fMimeTypeArray[i], "application/x-shockwave-flash") || - !strcmp(info.fMimeTypeArray[i], "application/x-shockwave-flash-test"))) { - return true; - } - } - return false; -} - typedef NS_NPAPIPLUGIN_CALLBACK(char *, NP_GETMIMEDESCRIPTION)(void); nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir, @@ -2114,8 +2062,6 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir, ("nsPluginHost::ScanPluginsDirectory dir=%s\n", dirPath.get())); #endif - bool flashOnly = Preferences::GetBool("plugin.load_flash_only", true); - nsCOMPtr<nsISimpleEnumerator> iter; rv = pluginsDir->GetDirectoryEntries(getter_AddRefs(iter)); if (NS_FAILED(rv)) @@ -2218,8 +2164,7 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir, res = pluginFile.GetPluginInfo(info, &library); } // if we don't have mime type don't proceed, this is not a plugin - if (NS_FAILED(res) || !info.fMimeTypeArray || - (flashOnly && !PluginInfoIsFlash(info))) { + if (NS_FAILED(res) || !info.fMimeTypeArray) { RefPtr<nsInvalidPluginTag> invalidTag = new nsInvalidPluginTag(filePath.get(), fileModTime); pluginFile.FreePluginInfo(info); @@ -2867,14 +2812,12 @@ nsPluginHost::WritePluginInfo() return rv; } - bool flashOnly = Preferences::GetBool("plugin.load_flash_only", true); - PR_fprintf(fd, "Generated File. Do not edit.\n"); PR_fprintf(fd, "\n[HEADER]\nVersion%c%s%c%c%c\nArch%c%s%c%c\n", PLUGIN_REGISTRY_FIELD_DELIMITER, kPluginRegistryVersion, - flashOnly ? 't' : 'f', + 'f', //flashOnly PLUGIN_REGISTRY_FIELD_DELIMITER, PLUGIN_REGISTRY_END_OF_LINE_MARKER, PLUGIN_REGISTRY_FIELD_DELIMITER, @@ -3071,9 +3014,8 @@ nsPluginHost::ReadPluginInfo() // If we're reading an old registry, ignore it // If we flipped the flash-only pref, ignore it - bool flashOnly = Preferences::GetBool("plugin.load_flash_only", true); nsAutoCString expectedVersion(kPluginRegistryVersion); - expectedVersion.Append(flashOnly ? 't' : 'f'); + expectedVersion.Append('f'); //flashOnly if (!expectedVersion.Equals(values[1])) { return rv; @@ -3214,10 +3156,6 @@ nsPluginHost::ReadPluginInfo() MOZ_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_BASIC, ("LoadCachedPluginsInfo : Loading Cached plugininfo for %s\n", tag->FileName().get())); - if (!ShouldAddPlugin(tag)) { - continue; - } - tag->mNext = mCachedPlugins; mCachedPlugins = tag; } diff --git a/dom/plugins/ipc/hangui/plugin-hang-ui.exe.manifest b/dom/plugins/ipc/hangui/plugin-hang-ui.exe.manifest index 8d6149c58..f5b7345f9 100644 --- a/dom/plugins/ipc/hangui/plugin-hang-ui.exe.manifest +++ b/dom/plugins/ipc/hangui/plugin-hang-ui.exe.manifest @@ -32,7 +32,6 @@ <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/> <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/> - <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> </application> </compatibility> </assembly> diff --git a/dom/plugins/test/unit/xpcshell.ini b/dom/plugins/test/unit/xpcshell.ini index 8dae66b20..69b6731b2 100644 --- a/dom/plugins/test/unit/xpcshell.ini +++ b/dom/plugins/test/unit/xpcshell.ini @@ -5,7 +5,7 @@ tail = tags = addons firefox-appdir = browser support-files = - !/toolkit/mozapps/extensions/test/xpcshell/head_addons.js + !/toolkit/mozapps/webextensions/test/xpcshell/head_addons.js [test_allowed_types.js] skip-if = appname == "thunderbird" diff --git a/dom/security/nsCSPContext.cpp b/dom/security/nsCSPContext.cpp index 815c7734d..5e435d4ca 100644 --- a/dom/security/nsCSPContext.cpp +++ b/dom/security/nsCSPContext.cpp @@ -156,10 +156,13 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType, nsAutoString nonce; bool parserCreated = false; if (!isPreload) { - nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(aRequestContext); - if (htmlElement) { - rv = htmlElement->GetAttribute(NS_LITERAL_STRING("nonce"), nonce); - NS_ENSURE_SUCCESS(rv, rv); + if (aContentType == nsIContentPolicy::TYPE_SCRIPT || + aContentType == nsIContentPolicy::TYPE_STYLESHEET) { + nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(aRequestContext); + if (htmlElement) { + rv = htmlElement->GetAttribute(NS_LITERAL_STRING("nonce"), nonce); + NS_ENSURE_SUCCESS(rv, rv); + } } nsCOMPtr<nsIScriptElement> script = do_QueryInterface(aRequestContext); @@ -343,6 +346,20 @@ nsCSPContext::GetBlockAllMixedContent(bool *outBlockAllMixedContent) } NS_IMETHODIMP +nsCSPContext::GetEnforcesFrameAncestors(bool *outEnforcesFrameAncestors) +{ + *outEnforcesFrameAncestors = false; + for (uint32_t i = 0; i < mPolicies.Length(); i++) { + if (!mPolicies[i]->getReportOnlyFlag() && + mPolicies[i]->hasDirective(nsIContentSecurityPolicy::FRAME_ANCESTORS_DIRECTIVE)) { + *outEnforcesFrameAncestors = true; + return NS_OK; + } + } + return NS_OK; +} + +NS_IMETHODIMP nsCSPContext::GetReferrerPolicy(uint32_t* outPolicy, bool* outIsSet) { *outIsSet = false; diff --git a/dom/security/nsCSPParser.cpp b/dom/security/nsCSPParser.cpp index a662c9cd1..86aa4e001 100644 --- a/dom/security/nsCSPParser.cpp +++ b/dom/security/nsCSPParser.cpp @@ -136,6 +136,7 @@ nsCSPParser::nsCSPParser(cspTokens& aTokens, , mUnsafeInlineKeywordSrc(nullptr) , mChildSrc(nullptr) , mFrameSrc(nullptr) + , mParsingFrameAncestorsDir(false) , mTokens(aTokens) , mSelfURI(aSelfURI) , mPolicy(nullptr) @@ -531,7 +532,7 @@ nsCSPParser::keywordSource() // Special case handling for 'self' which is not stored internally as a keyword, // but rather creates a nsCSPHostSrc using the selfURI if (CSP_IsKeyword(mCurToken, CSP_SELF)) { - return CSP_CreateHostSrcFromURI(mSelfURI); + return CSP_CreateHostSrcFromSelfURI(mSelfURI); } if (CSP_IsKeyword(mCurToken, CSP_STRICT_DYNAMIC)) { @@ -807,6 +808,7 @@ nsCSPParser::sourceExpression() if (nsCSPHostSrc *cspHost = hostSource()) { // Do not forget to set the parsed scheme. cspHost->setScheme(parsedScheme); + cspHost->setWithinFrameAncestorsDir(mParsingFrameAncestorsDir); return cspHost; } // Error was reported in hostSource() @@ -1209,6 +1211,9 @@ nsCSPParser::directive() mStrictDynamic = false; mUnsafeInlineKeywordSrc = nullptr; + mParsingFrameAncestorsDir = + CSP_IsDirective(mCurDir[0], nsIContentSecurityPolicy::FRAME_ANCESTORS_DIRECTIVE); + // Try to parse all the srcs by handing the array off to directiveValue nsTArray<nsCSPBaseSrc*> srcs; directiveValue(srcs); diff --git a/dom/security/nsCSPParser.h b/dom/security/nsCSPParser.h index 30954b10f..1bfc56c65 100644 --- a/dom/security/nsCSPParser.h +++ b/dom/security/nsCSPParser.h @@ -252,6 +252,10 @@ class nsCSPParser { nsCSPChildSrcDirective* mChildSrc; nsCSPDirective* mFrameSrc; + // cache variable to let nsCSPHostSrc know that it's within + // the frame-ancestors directive. + bool mParsingFrameAncestorsDir; + cspTokens mTokens; nsIURI* mSelfURI; nsCSPPolicy* mPolicy; diff --git a/dom/security/nsCSPUtils.cpp b/dom/security/nsCSPUtils.cpp index 63b4aae2c..a5f683b01 100644 --- a/dom/security/nsCSPUtils.cpp +++ b/dom/security/nsCSPUtils.cpp @@ -266,20 +266,21 @@ CSP_ContentTypeToDirective(nsContentPolicyType aType) } nsCSPHostSrc* -CSP_CreateHostSrcFromURI(nsIURI* aURI) +CSP_CreateHostSrcFromSelfURI(nsIURI* aSelfURI) { // Create the host first nsCString host; - aURI->GetHost(host); + aSelfURI->GetAsciiHost(host); nsCSPHostSrc *hostsrc = new nsCSPHostSrc(NS_ConvertUTF8toUTF16(host)); + hostsrc->setGeneratedFromSelfKeyword(); // Add the scheme. nsCString scheme; - aURI->GetScheme(scheme); + aSelfURI->GetScheme(scheme); hostsrc->setScheme(NS_ConvertUTF8toUTF16(scheme)); int32_t port; - aURI->GetPort(&port); + aSelfURI->GetPort(&port); // Only add port if it's not default port. if (port > 0) { nsAutoString portStr; @@ -348,13 +349,17 @@ CSP_IsQuotelessKeyword(const nsAString& aKey) * @param aUpgradeInsecure * Whether the policy makes use of the directive * 'upgrade-insecure-requests'. + * @param aFromSelfURI + * Whether a scheme was generated from the keyword 'self' + * which then allows schemeless sources to match ws and wss. */ bool permitsScheme(const nsAString& aEnforcementScheme, nsIURI* aUri, bool aReportOnly, - bool aUpgradeInsecure) + bool aUpgradeInsecure, + bool aFromSelfURI) { nsAutoCString scheme; nsresult rv = aUri->GetScheme(scheme); @@ -373,8 +378,20 @@ permitsScheme(const nsAString& aEnforcementScheme, // allow scheme-less sources where the protected resource is http // and the load is https, see: // http://www.w3.org/TR/CSP2/#match-source-expression - if (aEnforcementScheme.EqualsASCII("http") && - scheme.EqualsASCII("https")) { + if (aEnforcementScheme.EqualsASCII("http")) { + if (scheme.EqualsASCII("https")) { + return true; + } + if ((scheme.EqualsASCII("ws") || scheme.EqualsASCII("wss")) && aFromSelfURI) { + return true; + } + } + if (aEnforcementScheme.EqualsASCII("https")) { + if (scheme.EqualsLiteral("wss") && aFromSelfURI) { + return true; + } + } + if (aEnforcementScheme.EqualsASCII("ws") && scheme.EqualsASCII("wss")) { return true; } @@ -483,7 +500,7 @@ nsCSPSchemeSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirect if (mInvalidated) { return false; } - return permitsScheme(mScheme, aUri, aReportOnly, aUpgradeInsecure); + return permitsScheme(mScheme, aUri, aReportOnly, aUpgradeInsecure, false); } bool @@ -503,6 +520,8 @@ nsCSPSchemeSrc::toString(nsAString& outStr) const nsCSPHostSrc::nsCSPHostSrc(const nsAString& aHost) : mHost(aHost) + , mGeneratedFromSelfKeyword(false) + , mWithinFrameAncstorsDir(false) { ToLowerCase(mHost); } @@ -611,7 +630,7 @@ nsCSPHostSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected // http://www.w3.org/TR/CSP11/#match-source-expression // 4.3) scheme matching: Check if the scheme matches. - if (!permitsScheme(mScheme, aUri, aReportOnly, aUpgradeInsecure)) { + if (!permitsScheme(mScheme, aUri, aReportOnly, aUpgradeInsecure, mGeneratedFromSelfKeyword)) { return false; } @@ -642,7 +661,7 @@ nsCSPHostSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected // Before we can check if the host matches, we have to // extract the host part from aUri. nsAutoCString uriHost; - nsresult rv = aUri->GetHost(uriHost); + nsresult rv = aUri->GetAsciiHost(uriHost); NS_ENSURE_SUCCESS(rv, false); nsString decodedUriHost; @@ -686,6 +705,11 @@ nsCSPHostSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected rv = url->GetFilePath(uriPath); NS_ENSURE_SUCCESS(rv, false); + if (mWithinFrameAncstorsDir) { + // no path matching for frame-ancestors to not leak any path information. + return true; + } + nsString decodedUriPath; CSP_PercentDecodeStr(NS_ConvertUTF8toUTF16(uriPath), decodedUriPath); diff --git a/dom/security/nsCSPUtils.h b/dom/security/nsCSPUtils.h index b33c8932a..cfbe83256 100644 --- a/dom/security/nsCSPUtils.h +++ b/dom/security/nsCSPUtils.h @@ -186,7 +186,7 @@ nsresult CSP_AppendCSPFromHeader(nsIContentSecurityPolicy* aCsp, class nsCSPHostSrc; -nsCSPHostSrc* CSP_CreateHostSrcFromURI(nsIURI* aURI); +nsCSPHostSrc* CSP_CreateHostSrcFromSelfURI(nsIURI* aSelfURI); bool CSP_IsValidDirective(const nsAString& aDir); bool CSP_IsDirective(const nsAString& aValue, CSPDirective aDir); bool CSP_IsKeyword(const nsAString& aValue, enum CSPKeyword aKey); @@ -256,6 +256,12 @@ class nsCSPHostSrc : public nsCSPBaseSrc { void setPort(const nsAString& aPort); void appendPath(const nsAString &aPath); + inline void setGeneratedFromSelfKeyword() const + { mGeneratedFromSelfKeyword = true;} + + inline void setWithinFrameAncestorsDir(bool aValue) const + { mWithinFrameAncstorsDir = aValue; } + inline void getScheme(nsAString& outStr) const { outStr.Assign(mScheme); }; @@ -273,6 +279,8 @@ class nsCSPHostSrc : public nsCSPBaseSrc { nsString mHost; nsString mPort; nsString mPath; + mutable bool mGeneratedFromSelfKeyword; + mutable bool mWithinFrameAncstorsDir; }; /* =============== nsCSPKeywordSrc ============ */ diff --git a/dom/security/nsMixedContentBlocker.cpp b/dom/security/nsMixedContentBlocker.cpp index a9aca5333..4e80dce3f 100644 --- a/dom/security/nsMixedContentBlocker.cpp +++ b/dom/security/nsMixedContentBlocker.cpp @@ -337,7 +337,11 @@ nsMixedContentBlocker::AsyncOnChannelRedirect(nsIChannel* aOldChannel, nullptr, // aExtra requestingPrincipal, &decision); - NS_ENSURE_SUCCESS(rv, rv); + if (NS_FAILED(rv)) { + autoCallback.DontCallback(); + aOldChannel->Cancel(NS_ERROR_DOM_BAD_URI); + return NS_BINDING_FAILED; + } if (nsMixedContentBlocker::sSendHSTSPriming) { // The LoadInfo passed in is for the original channel, HSTS priming needs to @@ -358,6 +362,7 @@ nsMixedContentBlocker::AsyncOnChannelRedirect(nsIChannel* aOldChannel, // If the channel is about to load mixed content, abort the channel if (!NS_CP_ACCEPTED(decision)) { autoCallback.DontCallback(); + aOldChannel->Cancel(NS_ERROR_DOM_BAD_URI); return NS_BINDING_FAILED; } diff --git a/dom/security/test/csp/file_ignore_xfo.html b/dom/security/test/csp/file_ignore_xfo.html new file mode 100644 index 000000000..6746a3adb --- /dev/null +++ b/dom/security/test/csp/file_ignore_xfo.html @@ -0,0 +1,10 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Bug 1024557: Ignore x-frame-options if CSP with frame-ancestors exists</title> +</head> +<body> +<div id="cspmessage">Ignoring XFO because of CSP</div> +</body> +</html> diff --git a/dom/security/test/csp/file_ignore_xfo.html^headers^ b/dom/security/test/csp/file_ignore_xfo.html^headers^ new file mode 100644 index 000000000..e93f9e3ec --- /dev/null +++ b/dom/security/test/csp/file_ignore_xfo.html^headers^ @@ -0,0 +1,3 @@ +Content-Security-Policy: frame-ancestors http://mochi.test:8888 +X-Frame-Options: deny +Cache-Control: no-cache diff --git a/dom/security/test/csp/file_image_nonce.html b/dom/security/test/csp/file_image_nonce.html new file mode 100644 index 000000000..5d57bb837 --- /dev/null +++ b/dom/security/test/csp/file_image_nonce.html @@ -0,0 +1,39 @@ +<!DOCTYPE HTML> +<html> + <head> + <meta charset='utf-8'> + <title>Bug 1355801: Nonce should not apply to images</title> + </head> +<body> + +<img id='matchingNonce' src='http://mochi.test:8888/tests/image/test/mochitest/blue.png?a' nonce='abc'></img> +<img id='nonMatchingNonce' src='http://mochi.test:8888/tests/image/test/mochitest/blue.png?b' nonce='bca'></img> +<img id='noNonce' src='http://mochi.test:8888/tests/image/test/mochitest/blue.png?c'></img> + +<script type='application/javascript'> + var matchingNonce = document.getElementById('matchingNonce'); + matchingNonce.onload = function(e) { + window.parent.postMessage({result: 'img-with-matching-nonce-loaded'}, '*'); + }; + matchingNonce.onerror = function(e) { + window.parent.postMessage({result: 'img-with-matching-nonce-blocked'}, '*'); + } + + var nonMatchingNonce = document.getElementById('nonMatchingNonce'); + nonMatchingNonce.onload = function(e) { + window.parent.postMessage({result: 'img-with_non-matching-nonce-loaded'}, '*'); + }; + nonMatchingNonce.onerror = function(e) { + window.parent.postMessage({result: 'img-with_non-matching-nonce-blocked'}, '*'); + } + + var noNonce = document.getElementById('noNonce'); + noNonce.onload = function(e) { + window.parent.postMessage({result: 'img-without-nonce-loaded'}, '*'); + }; + noNonce.onerror = function(e) { + window.parent.postMessage({result: 'img-without-nonce-blocked'}, '*'); + } +</script> +</body> +</html> diff --git a/dom/security/test/csp/file_image_nonce.html^headers^ b/dom/security/test/csp/file_image_nonce.html^headers^ new file mode 100644 index 000000000..0d63558c4 --- /dev/null +++ b/dom/security/test/csp/file_image_nonce.html^headers^ @@ -0,0 +1,2 @@ +Content-Security-Policy: img-src 'nonce-abc'; +Cache-Control: no-cache diff --git a/dom/security/test/csp/file_punycode_host_src.js b/dom/security/test/csp/file_punycode_host_src.js new file mode 100644 index 000000000..3505faf70 --- /dev/null +++ b/dom/security/test/csp/file_punycode_host_src.js @@ -0,0 +1,2 @@ +const LOADED = true; +parent.postMessage({result: 'script-allowed'}, "*");
\ No newline at end of file diff --git a/dom/security/test/csp/file_punycode_host_src.sjs b/dom/security/test/csp/file_punycode_host_src.sjs new file mode 100644 index 000000000..3189cc063 --- /dev/null +++ b/dom/security/test/csp/file_punycode_host_src.sjs @@ -0,0 +1,45 @@ +// custom *.sjs for Bug 1224225 +// Punycode in CSP host sources + +const HTML_PART1 = + "<!DOCTYPE HTML>" + + "<html><head><meta charset=\"utf-8\">" + + "<title>Bug 1224225 - CSP source matching should work for punycoded domain names</title>" + + "</head>" + + "<body>" + + "<script id='script' src='"; + +const TESTCASE1 = "http://sub2.ält.example.org/"; +const TESTCASE2 = "http://sub2.xn--lt-uia.example.org/" + +const HTML_PART2 = "tests/dom/security/test/csp/file_punycode_host_src.js'></script>" + + "</body>" + + "</html>"; + +function handleRequest(request, response) +{ + // avoid confusing cache behaviors + response.setHeader("Cache-Control", "no-cache", false); + response.setHeader("Content-Type", "text/html", false); + + Components.utils.importGlobalProperties(["URLSearchParams"]); + const query = new URLSearchParams(request.queryString); + + + if (query.get("csp")) { + response.setHeader("Content-Security-Policy", query.get("csp"), false); + } + if (query.get("action") == "script-unicode-csp-punycode") { + response.write(HTML_PART1 + TESTCASE1 + HTML_PART2); + return + } + if (query.get("action") == "script-punycode-csp-punycode") { + response.write(HTML_PART1 + TESTCASE2 + HTML_PART2); + return + } + + + // we should never get here, but just in case + // return something unexpected + response.write("do'h"); +} diff --git a/dom/security/test/csp/file_ro_ignore_xfo.html b/dom/security/test/csp/file_ro_ignore_xfo.html new file mode 100644 index 000000000..85e7f0092 --- /dev/null +++ b/dom/security/test/csp/file_ro_ignore_xfo.html @@ -0,0 +1,10 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Bug 1024557: Ignore x-frame-options if CSP with frame-ancestors exists</title> +</head> +<body> +<div id="cspmessage">Ignoring XFO because of CSP_RO</div> +</body> +</html>
\ No newline at end of file diff --git a/dom/security/test/csp/file_ro_ignore_xfo.html^headers^ b/dom/security/test/csp/file_ro_ignore_xfo.html^headers^ new file mode 100644 index 000000000..ab8366f06 --- /dev/null +++ b/dom/security/test/csp/file_ro_ignore_xfo.html^headers^ @@ -0,0 +1,3 @@ +Content-Security-Policy-Report-Only: frame-ancestors http://mochi.test:8888 +X-Frame-Options: deny +Cache-Control: no-cache diff --git a/dom/security/test/csp/file_upgrade_insecure_navigation.sjs b/dom/security/test/csp/file_upgrade_insecure_navigation.sjs new file mode 100644 index 000000000..51afa39bf --- /dev/null +++ b/dom/security/test/csp/file_upgrade_insecure_navigation.sjs @@ -0,0 +1,79 @@ +// Custom *.sjs file specifically for the needs of +// https://bugzilla.mozilla.org/show_bug.cgi?id=1271173 + +"use strict"; +Components.utils.importGlobalProperties(["URLSearchParams"]); + +const TEST_NAVIGATIONAL_UPGRADE = ` + <!DOCTYPE html> + <html> + <head><meta charset="utf-8"></head> + <body> + <a href="http://example.com/tests/dom/security/test/csp/file_upgrade_insecure_navigation.sjs?action=framenav" id="testlink">clickme</a> + <script type="text/javascript"> + // before navigating the current frame we open the window and check that uir applies + var myWin = window.open("http://example.com/tests/dom/security/test/csp/file_upgrade_insecure_navigation.sjs?action=docnav"); + + window.addEventListener("message", receiveMessage, false); + function receiveMessage(event) { + myWin.close(); + var link = document.getElementById('testlink'); + link.click(); + } + </script> + </body> + </html>`; + +const FRAME_NAV = ` + <!DOCTYPE html> + <html> + <head><meta charset="utf-8"></head> + <body> + <script type="text/javascript"> + parent.postMessage({result: document.documentURI}, "*"); + </script> + </body> + </html>`; + +const DOC_NAV = ` + <!DOCTYPE html> + <html> + <head><meta charset="utf-8"></head> + <body> + <script type="text/javascript"> + // call back to the main testpage signaling whether the upgraded succeeded + window.opener.parent.postMessage({result: document.documentURI}, "*"); + // let the opener (iframe) now that we can now close the window and move on with the test. + window.opener.postMessage({result: "readyToMoveOn"}, "*"); + </script> + </body> + </html>`; + +function handleRequest(request, response) { + const query = new URLSearchParams(request.queryString); + + response.setHeader("Cache-Control", "no-cache", false); + response.setHeader("Content-Type", "text/html", false); + if (query.get("csp")) { + response.setHeader("Content-Security-Policy", query.get("csp"), false); + } + + if (query.get("action") === "perform_navigation") { + response.write(TEST_NAVIGATIONAL_UPGRADE); + return; + } + + if (query.get("action") === "framenav") { + response.write(FRAME_NAV); + return; + } + + if (query.get("action") === "docnav") { + response.write(DOC_NAV); + return; + } + + // we should never get here, but just in case + // return something unexpected + response.write("do'h"); +} diff --git a/dom/security/test/csp/file_websocket_explicit.html b/dom/security/test/csp/file_websocket_explicit.html new file mode 100644 index 000000000..51462ab74 --- /dev/null +++ b/dom/security/test/csp/file_websocket_explicit.html @@ -0,0 +1,31 @@ +<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Bug 1345615: Allow websocket schemes when using 'self' in CSP</title>
+ <meta http-equiv="Content-Security-Policy" content="connect-src ws:">
+</head>
+<body>
+ <script type="application/javascript">
+ /* load socket using ws */
+ var wsSocket = new WebSocket("ws://example.com/tests/dom/security/test/csp/file_websocket_self");
+ wsSocket.onopen = function(e) {
+ window.parent.postMessage({result: "explicit-ws-loaded"}, "*");
+ wsSocket.close();
+ };
+ wsSocket.onerror = function(e) {
+ window.parent.postMessage({result: "explicit-ws-blocked"}, "*");
+ };
+
+ /* load socket using wss */
+ var wssSocket = new WebSocket("wss://example.com/tests/dom/security/test/csp/file_websocket_self");
+ wssSocket.onopen = function(e) {
+ window.parent.postMessage({result: "explicit-wss-loaded"}, "*");
+ wssSocket.close();
+ };
+ wssSocket.onerror = function(e) {
+ window.parent.postMessage({result: "explicit-wss-blocked"}, "*");
+ };
+ </script>
+</body>
+</html>
diff --git a/dom/security/test/csp/file_websocket_self.html b/dom/security/test/csp/file_websocket_self.html new file mode 100644 index 000000000..3ff5f0558 --- /dev/null +++ b/dom/security/test/csp/file_websocket_self.html @@ -0,0 +1,31 @@ +<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Bug 1345615: Allow websocket schemes when using 'self' in CSP</title>
+ <meta http-equiv="Content-Security-Policy" content="connect-src 'self'">
+</head>
+<body>
+ <script type="application/javascript">
+ /* load socket using ws */
+ var wsSocket = new WebSocket("ws://example.com/tests/dom/security/test/csp/file_websocket_self");
+ wsSocket.onopen = function(e) {
+ window.parent.postMessage({result: "self-ws-loaded"}, "*");
+ wsSocket.close();
+ };
+ wsSocket.onerror = function(e) {
+ window.parent.postMessage({result: "self-ws-blocked"}, "*");
+ };
+
+ /* load socket using wss */
+ var wssSocket = new WebSocket("wss://example.com/tests/dom/security/test/csp/file_websocket_self");
+ wssSocket.onopen = function(e) {
+ window.parent.postMessage({result: "self-wss-loaded"}, "*");
+ wssSocket.close();
+ };
+ wssSocket.onerror = function(e) {
+ window.parent.postMessage({result: "self-wss-blocked"}, "*");
+ };
+ </script>
+</body>
+</html>
diff --git a/dom/security/test/csp/file_websocket_self_wsh.py b/dom/security/test/csp/file_websocket_self_wsh.py new file mode 100644 index 000000000..5fe508a91 --- /dev/null +++ b/dom/security/test/csp/file_websocket_self_wsh.py @@ -0,0 +1,7 @@ +from mod_pywebsocket import msgutil
+
+def web_socket_do_extra_handshake(request):
+ pass
+
+def web_socket_transfer_data(request):
+ pass
diff --git a/dom/security/test/csp/mochitest.ini b/dom/security/test/csp/mochitest.ini index 8add999c3..2102cbe70 100644 --- a/dom/security/test/csp/mochitest.ini +++ b/dom/security/test/csp/mochitest.ini @@ -206,6 +206,18 @@ support-files = file_iframe_srcdoc.sjs file_iframe_sandbox_srcdoc.html file_iframe_sandbox_srcdoc.html^headers^ + file_ignore_xfo.html + file_ignore_xfo.html^headers^ + file_ro_ignore_xfo.html + file_ro_ignore_xfo.html^headers^ + file_upgrade_insecure_navigation.sjs + file_image_nonce.html + file_image_nonce.html^headers^ + file_punycode_host_src.sjs + file_punycode_host_src.js + file_websocket_self.html + file_websocket_explicit.html + file_websocket_self_wsh.py [test_base-uri.html] [test_blob_data_schemes.html] @@ -292,9 +304,15 @@ tags = mcb [test_strict_dynamic.html] [test_strict_dynamic_parser_inserted.html] [test_strict_dynamic_default_src.html] +[test_upgrade_insecure_navigation.html] [test_iframe_sandbox_srcdoc.html] [test_iframe_srcdoc.html] [test_sandbox_allow_scripts.html] support-files = file_sandbox_allow_scripts.html file_sandbox_allow_scripts.html^headers^ +[test_ignore_xfo.html] +[test_image_nonce.html] +[test_punycode_host_src.html] +[test_websocket_self.html] +skip-if = toolkit == 'android' diff --git a/dom/security/test/csp/test_ignore_xfo.html b/dom/security/test/csp/test_ignore_xfo.html new file mode 100644 index 000000000..fb3aadc6c --- /dev/null +++ b/dom/security/test/csp/test_ignore_xfo.html @@ -0,0 +1,59 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Bug 1024557: Ignore x-frame-options if CSP with frame-ancestors exists</title> + <!-- Including SimpleTest.js so we can use waitForExplicitFinish !--> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<iframe style="width:100%;" id="csp_testframe"></iframe> +<iframe style="width:100%;" id="csp_ro_testframe"></iframe> + +<script class="testbody" type="text/javascript"> + +/* + * We load two frames using: + * x-frame-options: deny + * where the first frame uses a csp and the second a csp_ro including frame-ancestors. + * We make sure that xfo is ignored for regular csp but not for csp_ro. + */ + +SimpleTest.waitForExplicitFinish(); + +var testcounter = 0; +function checkFinished() { + testcounter++; + if (testcounter < 2) { + return; + } + SimpleTest.finish(); +} + +// 1) test XFO with CSP +var csp_testframe = document.getElementById("csp_testframe"); +csp_testframe.onload = function() { + var msg = csp_testframe.contentWindow.document.getElementById("cspmessage"); + is(msg.innerHTML, "Ignoring XFO because of CSP", "Loading frame with with XFO and CSP"); + checkFinished(); +} +csp_testframe.onerror = function() { + ok(false, "sanity: should not fire onerror for csp_testframe"); +} +csp_testframe.src = "file_ignore_xfo.html"; + +// 2) test XFO with CSP_RO +var csp_ro_testframe = document.getElementById("csp_ro_testframe"); +csp_ro_testframe.onload = function() { + var msg = csp_ro_testframe.contentWindow.document.getElementById("cspmessage"); + is(msg, null, "Blocking frame with with XFO and CSP_RO"); + checkFinished(); +} +csp_ro_testframe.onerror = function() { + ok(false, "sanity: should not fire onerror for csp_ro_testframe"); +} +csp_ro_testframe.src = "file_ro_ignore_xfo.html"; + +</script> +</body> +</html> diff --git a/dom/security/test/csp/test_image_nonce.html b/dom/security/test/csp/test_image_nonce.html new file mode 100644 index 000000000..ff6d636b6 --- /dev/null +++ b/dom/security/test/csp/test_image_nonce.html @@ -0,0 +1,60 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Bug 1139297 - Implement CSP upgrade-insecure-requests directive</title> + <!-- Including SimpleTest.js so we can use waitForExplicitFinish !--> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<iframe style="width:100%;" id="testframe"></iframe> + +<script class="testbody" type="text/javascript"> + +/* Description of the test: + * We load three images: (a) with a matching nonce, + (b) with a non matching nonce, + * (c) with no nonce + * and make sure that all three images get blocked because + * "img-src nonce-bla" should not allow an image load, not + * even if the nonce matches*. + */ + +SimpleTest.waitForExplicitFinish(); + +var counter = 0; + +function finishTest() { + window.removeEventListener("message", receiveMessage); + SimpleTest.finish(); +} + +function checkResults(aResult) { + counter++; + if (aResult === "img-with-matching-nonce-blocked" || + aResult === "img-with_non-matching-nonce-blocked" || + aResult === "img-without-nonce-blocked") { + ok (true, "correct result for: " + aResult); + } + else { + ok(false, "unexpected result: " + aResult + "\n\n"); + } + if (counter < 3) { + return; + } + finishTest(); +} + +// a postMessage handler that is used by sandboxed iframes without +// 'allow-same-origin' to bubble up results back to this main page. +window.addEventListener("message", receiveMessage); +function receiveMessage(event) { + checkResults(event.data.result); +} + +document.getElementById("testframe").src = "file_image_nonce.html"; + +</script> +</body> +</html> diff --git a/dom/security/test/csp/test_punycode_host_src.html b/dom/security/test/csp/test_punycode_host_src.html new file mode 100644 index 000000000..8d891725c --- /dev/null +++ b/dom/security/test/csp/test_punycode_host_src.html @@ -0,0 +1,81 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Bug 1224225 - CSP source matching should work for punycoded domain names</title> + <!-- Including SimpleTest.js so we can use waitForExplicitFinish !--> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<iframe style="width:100%;" id="testframe"></iframe> + +<script class="testbody" type="text/javascript"> + +/* Description of the test: + * We load scripts within an iframe and make sure that the + * CSP matching is same for punycode domain names as well as IDNA. + */ + +SimpleTest.waitForExplicitFinish(); + + +var curTest; +var counter = -1; + +const tests = [ + { // test 1 + description: "loads script as sub2.ält.example.org, but whitelist in CSP as sub2.xn--lt-uia.example.org", + action: "script-unicode-csp-punycode", + csp: "script-src http://sub2.xn--lt-uia.example.org;", + expected: "script-allowed", + + }, + { // test 2 + description: "loads script as sub2.xn--lt-uia.example.org, and whitelist in CSP as sub2.xn--lt-uia.example.org", + action: "script-punycode-csp-punycode", + csp: "script-src http://sub2.xn--lt-uia.example.org;", + expected: "script-allowed", + + }, + { // test 3 + description: "loads script as sub2.xn--lt-uia.example.org, and whitelist in CSP as sub2.xn--lt-uia.example.org", + action: "script-punycode-csp-punycode", + csp: "script-src *.xn--lt-uia.example.org;", + expected: "script-allowed", + + }, + +]; + +function finishTest() { + window.removeEventListener("message", receiveMessage); + SimpleTest.finish(); +} + +function checkResults(result) { + is(result, curTest.expected, curTest.description); + loadNextTest(); +} + +window.addEventListener("message", receiveMessage); +function receiveMessage(event) { + checkResults(event.data.result); +} + +function loadNextTest() { + counter++; + if (counter == tests.length) { + finishTest(); + return; + } + curTest = tests[counter]; + var testframe = document.getElementById("testframe"); + testframe.src = `file_punycode_host_src.sjs?action=${curTest.action}&csp=${curTest.csp}`; +} + +loadNextTest(); + +</script> +</body> +</html> diff --git a/dom/security/test/csp/test_upgrade_insecure_navigation.html b/dom/security/test/csp/test_upgrade_insecure_navigation.html new file mode 100644 index 000000000..db6a6a1be --- /dev/null +++ b/dom/security/test/csp/test_upgrade_insecure_navigation.html @@ -0,0 +1,103 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Bug 1271173 - Missing spec on Upgrade Insecure Requests(Navigational Upgrades) </title> + <!-- Including SimpleTest.js so we can use waitForExplicitFinish !--> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<iframe style="width:100%;" id="testframe"></iframe> +<iframe style="width:100%;" id="sandboxedtestframe" + sandbox="allow-scripts allow-top-navigation allow-same-origin allow-pointer-lock allow-popups"></iframe> + +<script class="testbody" type="text/javascript"> +/* + * Description of the test: + * We load a page into an iframe that performs a navigational request. + * We make sure that upgrade-insecure-requests applies and the page + * gets upgraded to https if same origin. + * Please note that uir only applies to sandboxed iframes if + * the value 'allow-same-origin' is specified. + */ + +SimpleTest.waitForExplicitFinish(); + +var tests = [ + { + csp: "upgrade-insecure-requests;", + result: "https", + origin: "http://example.com", + desc: "upgrade-insecure-requests same origin should upgrade" + }, + { + csp: "", + result: "http", + origin: "http://example.com", + desc: "No upgrade-insecure-requests same origin should not upgrade" + }, + { + csp: "upgrade-insecure-requests;", + result: "http", + origin: "http://mochi.test:8888", + desc: "upgrade-insecure-requests cross origin should not upgrade" + }, + { + csp: "", + result: "http", + origin: "http://mochi.test:8888", + desc: "No upgrade-insecure-requests cross origin should not upgrade" + }, +]; + +// initializing to -1 so we start at index 0 when we start the test +var counter = -1; + +function finishTest() { + window.removeEventListener("message", receiveMessage, false); + SimpleTest.finish(); +} + +var subtests = 0; + +window.addEventListener("message", receiveMessage, false); +function receiveMessage(event) { + var result = event.data.result; + // query the scheme from the URL before comparing the result + var scheme = result.substring(0, result.indexOf(":")); + is(scheme, tests[counter].result, tests[counter].desc); + + // @hardcoded 4: + // each test run contains of two subtests (frame and top-level) + // and we load each test into a regular iframe and into a + // sandboxed iframe. only move on to the next test once all + // four results from the subtests have bubbled up. + subtests++; + if (subtests != 4) { + return; + } + subtests = 0; + loadNextTest(); +} + +function loadNextTest() { + counter++; + if (counter == tests.length) { + finishTest(); + return; + } + + var src = tests[counter].origin; + src += "/tests/dom/security/test/csp/file_upgrade_insecure_navigation.sjs"; + src += "?csp=" + escape(tests[counter].csp); + src += "&action=perform_navigation"; + document.getElementById("testframe").src = src; + document.getElementById("sandboxedtestframe").src = src; +} + +// start running the tests +loadNextTest(); + +</script> +</body> +</html> diff --git a/dom/security/test/csp/test_websocket_self.html b/dom/security/test/csp/test_websocket_self.html new file mode 100644 index 000000000..a03c32704 --- /dev/null +++ b/dom/security/test/csp/test_websocket_self.html @@ -0,0 +1,61 @@ +<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Bug 1345615: Allow websocket schemes when using 'self' in CSP</title>
+ <!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<iframe style="width:100%;" id="test_ws_self_frame"></iframe>
+<iframe style="width:100%;" id="test_ws_explicit_frame"></iframe>
+
+<script class="testbody" type="text/javascript">
+
+/* Description of the test:
+ * We load an iframe using connect-src 'self' and one
+ * iframe using connect-src ws: and make
+ * sure that in both cases ws: as well as wss: is allowed to load.
+ */
+
+SimpleTest.waitForExplicitFinish();
+
+function finishTest() {
+ window.removeEventListener("message", receiveMessage);
+ SimpleTest.finish();
+}
+
+const TOTAL_TESTS = 4;
+var counter = 0;
+
+function checkResults(result) {
+ counter++;
+ if (result === "self-ws-loaded" || result === "self-wss-loaded" ||
+ result === "explicit-ws-loaded" || result === "explicit-wss-loaded") {
+ ok(true, "Evaluating: " + result);
+ }
+ else {
+ ok(false, "Evaluating: " + result);
+ }
+ if (counter < TOTAL_TESTS) {
+ return;
+ }
+ finishTest();
+}
+
+window.addEventListener("message", receiveMessage);
+function receiveMessage(event) {
+ checkResults(event.data.result);
+}
+
+const HOST = "http://example.com/tests/dom/security/test/csp/";
+var test_ws_self_frame = document.getElementById("test_ws_self_frame");
+test_ws_self_frame.src = HOST + "file_websocket_self.html";
+
+var test_ws_explicit_frame = document.getElementById("test_ws_explicit_frame");
+test_ws_explicit_frame.src = HOST + "file_websocket_explicit.html";
+
+</script>
+</body>
+</html>
diff --git a/dom/security/test/gtest/TestCSPParser.cpp b/dom/security/test/gtest/TestCSPParser.cpp index fafa7b5d9..8d168d81c 100644 --- a/dom/security/test/gtest/TestCSPParser.cpp +++ b/dom/security/test/gtest/TestCSPParser.cpp @@ -204,6 +204,8 @@ TEST(CSPParser, Directives) { static const PolicyTest policies[] = { + { "connect-src xn--mnchen-3ya.de", + "connect-src http://xn--mnchen-3ya.de"}, { "default-src http://www.example.com", "default-src http://www.example.com" }, { "script-src http://www.example.com", diff --git a/dom/tests/mochitest/general/test_domWindowUtils_scrollXY.html b/dom/tests/mochitest/general/test_domWindowUtils_scrollXY.html index c6ee89ee3..cf27e5d87 100644 --- a/dom/tests/mochitest/general/test_domWindowUtils_scrollXY.html +++ b/dom/tests/mochitest/general/test_domWindowUtils_scrollXY.html @@ -31,13 +31,13 @@ function checkGetScrollXYState(flush, vals, testName) { let scrollX = {}, scrollY = {}; domWindowUtils.getScrollXY(flush, scrollX, scrollY); - is(scrollX.value, vals[0], "getScrollXY x for test: " + testName); - is(scrollY.value, vals[1], "getScrollXY y for test: " + testName); + is(Math.round(scrollX.value), vals[0], "getScrollXY x for test: " + testName); + is(Math.round(scrollY.value), vals[1], "getScrollXY y for test: " + testName); } function checkWindowScrollState(vals, testName) { - is(cwindow.scrollX, vals[0], "scrollX for test: " + testName); - is(cwindow.scrollY, vals[1], "scrollY for test: " + testName); + is(Math.round(cwindow.scrollX), vals[0], "scrollX for test: " + testName); + is(Math.round(cwindow.scrollY), vals[1], "scrollY for test: " + testName); } // Check initial state (0, 0) @@ -67,8 +67,8 @@ let scrollX = {}, scrollY = {}; domWindowUtils.getScrollXY(false, scrollX, scrollY); - is(scrollX.value, 0, "scrollX is zero for display:none iframe"); - is(scrollY.value, 0, "scrollY is zero for display:none iframe"); + is(Math.round(scrollX.value), 0, "scrollX is zero for display:none iframe"); + is(Math.round(scrollY.value), 0, "scrollY is zero for display:none iframe"); } SimpleTest.waitForExplicitFinish(); diff --git a/dom/url/URL.h b/dom/url/URL.h index 16b4678ba..45e4dd289 100644 --- a/dom/url/URL.h +++ b/dom/url/URL.h @@ -155,6 +155,12 @@ public: GetHref(aRetval, aRv); } + void + ToJSON(nsAString& aResult, ErrorResult& aRv) const + { + GetHref(aResult, aRv); + } + // URLSearchParamsObserver void URLSearchParamsUpdated(URLSearchParams* aSearchParams) override; diff --git a/dom/url/tests/test_url.html b/dom/url/tests/test_url.html index 3f3f727d6..d07a752bb 100644 --- a/dom/url/tests/test_url.html +++ b/dom/url/tests/test_url.html @@ -438,5 +438,11 @@ url = new URL("data:text/html,<a href=\"http://example.org/?q\">Link</a>"); is(url.href, "data:text/html,<a%20href=\"http://example.org/?q\">Link</a>"); </script> + + <script> + var u = new URL('http://www.example.org'); + ok(u.toJSON(), 'http://www.example.org', "URL.toJSON()"); + is(JSON.stringify(u), "\"http://www.example.org/\"", "JSON.stringify(u) works"); + </script> </body> </html> diff --git a/dom/webidl/URL.webidl b/dom/webidl/URL.webidl index 0baa9913c..4d491e1b3 100644 --- a/dom/webidl/URL.webidl +++ b/dom/webidl/URL.webidl @@ -44,9 +44,12 @@ interface URL { attribute USVString pathname; [Throws] attribute USVString search; - readonly attribute URLSearchParams searchParams; + [SameObject] readonly attribute URLSearchParams searchParams; [Throws] attribute USVString hash; + + [Throws] + USVString toJSON(); }; partial interface URL { diff --git a/dom/webidl/Window.webidl b/dom/webidl/Window.webidl index 055a274cc..36b1f0313 100644 --- a/dom/webidl/Window.webidl +++ b/dom/webidl/Window.webidl @@ -182,14 +182,10 @@ partial interface Window { [ChromeOnly] void mozScrollSnap(); // The four properties below are double per spec at the moment, but whether // that will continue is unclear. - //[Replaceable, Throws] readonly attribute double scrollX; - //[Replaceable, Throws] readonly attribute double pageXOffset; - //[Replaceable, Throws] readonly attribute double scrollY; - //[Replaceable, Throws] readonly attribute double pageYOffset; - [Replaceable, Throws] readonly attribute long scrollX; - [Replaceable, Throws] readonly attribute long pageXOffset; - [Replaceable, Throws] readonly attribute long scrollY; - [Replaceable, Throws] readonly attribute long pageYOffset; + [Replaceable, Throws] readonly attribute double scrollX; + [Throws] readonly attribute double pageXOffset; + [Replaceable, Throws] readonly attribute double scrollY; + [Throws] readonly attribute double pageYOffset; // client // These are writable because we allow chrome to write them. And they need diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index efa90230d..f24c366e8 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -18,7 +18,6 @@ PREPROCESSED_WEBIDL_FILES = [ WEBIDL_FILES = [ 'AbstractWorker.webidl', - 'AddonManager.webidl', 'AnalyserNode.webidl', 'Animatable.webidl', 'Animation.webidl', @@ -592,6 +591,9 @@ WEBIDL_FILES = [ 'XULElement.webidl', ] +if CONFIG['MOZ_WEBEXTENSIONS']: + WEBIDL_FILES += ['AddonManager.webidl'] + if CONFIG['MOZ_AUDIO_CHANNEL_MANAGER']: WEBIDL_FILES += [ 'AudioChannelManager.webidl', @@ -692,7 +694,6 @@ else: ] GENERATED_EVENTS_WEBIDL_FILES = [ - 'AddonEvent.webidl', 'AnimationPlaybackEvent.webidl', 'AutocompleteErrorEvent.webidl', 'BlobEvent.webidl', @@ -734,6 +735,9 @@ GENERATED_EVENTS_WEBIDL_FILES = [ 'WebGLContextEvent.webidl', ] +if CONFIG['MOZ_WEBEXTENSIONS']: + GENERATED_EVENTS_WEBIDL_FILES += ['AddonEvent.webidl'] + if CONFIG['MOZ_WEBRTC']: GENERATED_EVENTS_WEBIDL_FILES += [ 'RTCDataChannelEvent.webidl', @@ -764,12 +768,12 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': 'MozWifiStatusChangeEvent.webidl', ] -if CONFIG['MOZ_BUILD_APP'] in ['browser', 'xulrunner'] or CONFIG['MOZ_SUITE']: +if CONFIG['MOZ_BUILD_APP'] in ['xulrunner'] or CONFIG['MOZ_PHOENIX'] or CONFIG['MOZ_SUITE']: WEBIDL_FILES += [ 'BrowserFeedWriter.webidl', ] -if CONFIG['MOZ_BUILD_APP'] in ['browser', 'mobile/android', 'xulrunner']: +if CONFIG['MOZ_BUILD_APP'] in ['mobile/android', 'xulrunner'] or CONFIG['MOZ_PHOENIX']: WEBIDL_FILES += [ 'External.webidl', ] |