diff options
Diffstat (limited to 'dom')
132 files changed, 1134 insertions, 977 deletions
diff --git a/dom/animation/AnimationEffectReadOnly.cpp b/dom/animation/AnimationEffectReadOnly.cpp index bf2e2197d..63d633c2f 100644 --- a/dom/animation/AnimationEffectReadOnly.cpp +++ b/dom/animation/AnimationEffectReadOnly.cpp @@ -23,7 +23,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AnimationEffectReadOnly) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument, mTiming, mAnimation) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(AnimationEffectReadOnly) diff --git a/dom/animation/AnimationTimeline.cpp b/dom/animation/AnimationTimeline.cpp index 643106807..f4a1ecc9a 100644 --- a/dom/animation/AnimationTimeline.cpp +++ b/dom/animation/AnimationTimeline.cpp @@ -21,7 +21,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AnimationTimeline) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow, mAnimations) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(AnimationTimeline) diff --git a/dom/base/Attr.cpp b/dom/base/Attr.cpp index 6eb3b49fd..71b559392 100644 --- a/dom/base/Attr.cpp +++ b/dom/base/Attr.cpp @@ -59,8 +59,6 @@ Attr::Attr(nsDOMAttributeMap *aAttrMap, NS_IMPL_CYCLE_COLLECTION_CLASS(Attr) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Attr) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS - if (!nsINode::Traverse(tmp, cb)) { return NS_SUCCESS_INTERRUPTED_TRAVERSE; } diff --git a/dom/base/CustomElementRegistry.cpp b/dom/base/CustomElementRegistry.cpp index 00ee3d42f..3f202d33b 100644 --- a/dom/base/CustomElementRegistry.cpp +++ b/dom/base/CustomElementRegistry.cpp @@ -138,7 +138,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CustomElementRegistry) } NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWhenDefinedPromiseMap) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(CustomElementRegistry) diff --git a/dom/base/DOMException.cpp b/dom/base/DOMException.cpp index dfda47316..9fbb2f242 100644 --- a/dom/base/DOMException.cpp +++ b/dom/base/DOMException.cpp @@ -165,7 +165,6 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(Exception) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Exception) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocation) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mData) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Exception) diff --git a/dom/base/DOMIntersectionObserver.cpp b/dom/base/DOMIntersectionObserver.cpp index e671b7da9..389b93071 100644 --- a/dom/base/DOMIntersectionObserver.cpp +++ b/dom/base/DOMIntersectionObserver.cpp @@ -52,7 +52,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMIntersectionObserver) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMIntersectionObserver) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback) diff --git a/dom/base/File.cpp b/dom/base/File.cpp index 7d86dfe8a..1d5ab73e7 100755 --- a/dom/base/File.cpp +++ b/dom/base/File.cpp @@ -138,7 +138,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Blob) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Blob) diff --git a/dom/base/FormData.cpp b/dom/base/FormData.cpp index 6095286be..52bdd9210 100644 --- a/dom/base/FormData.cpp +++ b/dom/base/FormData.cpp @@ -84,7 +84,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(FormData) "mFormData[i].GetAsBlob()", 0); } - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(FormData) diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp index 13ba19c8c..9106778df 100644 --- a/dom/base/FragmentOrElement.cpp +++ b/dom/base/FragmentOrElement.cpp @@ -1878,10 +1878,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(FragmentOrElement) NS_IMPL_CYCLE_COLLECTION_DESCRIBE(FragmentOrElement, tmp->mRefCnt.get()) } - // Always need to traverse script objects, so do that before we check - // if we're uncollectable. - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS - if (!nsINode::Traverse(tmp, cb)) { return NS_SUCCESS_INTERRUPTED_TRAVERSE; } diff --git a/dom/base/Location.cpp b/dom/base/Location.cpp index e312cffe0..1483c32f9 100644 --- a/dom/base/Location.cpp +++ b/dom/base/Location.cpp @@ -80,7 +80,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Location) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInnerWindow) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(Location) @@ -790,10 +789,6 @@ Location::GetSearch(nsAString& aSearch) NS_IMETHODIMP Location::SetSearch(const nsAString& aSearch) { - if (aSearch.IsEmpty()) { - return NS_OK; // Ignore empty string - } - nsresult rv = SetSearchInternal(aSearch); if (NS_FAILED(rv)) { return rv; diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index 286cd0e79..fdf151b6c 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -223,7 +223,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGamepadServiceTest) #endif NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRGetDisplaysPromises) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(Navigator) diff --git a/dom/base/Pose.cpp b/dom/base/Pose.cpp index 1eab4c173..5bc4ca6de 100644 --- a/dom/base/Pose.cpp +++ b/dom/base/Pose.cpp @@ -26,7 +26,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Pose) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Pose) diff --git a/dom/base/ProcessGlobal.cpp b/dom/base/ProcessGlobal.cpp index 641f49f98..6cd29ab7c 100644 --- a/dom/base/ProcessGlobal.cpp +++ b/dom/base/ProcessGlobal.cpp @@ -52,7 +52,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ProcessGlobal) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageManager) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal) tmp->TraverseHostObjectURIs(cb); - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ProcessGlobal) diff --git a/dom/base/nsAttrAndChildArray.cpp b/dom/base/nsAttrAndChildArray.cpp index b285ee003..9fd27262b 100644 --- a/dom/base/nsAttrAndChildArray.cpp +++ b/dom/base/nsAttrAndChildArray.cpp @@ -78,15 +78,8 @@ GetIndexFromCache(const nsAttrAndChildArray* aArray) } -/** - * Due to a compiler bug in VisualAge C++ for AIX, we need to return the - * address of the first index into mBuffer here, instead of simply returning - * mBuffer itself. - * - * See Bug 231104 for more information. - */ #define ATTRS(_impl) \ - reinterpret_cast<InternalAttr*>(&((_impl)->mBuffer[0])) + reinterpret_cast<InternalAttr*>((_impl)->mBuffer) #define NS_IMPL_EXTRA_SIZE \ diff --git a/dom/base/nsContentList.cpp b/dom/base/nsContentList.cpp index 43e65777d..c98859ee3 100644 --- a/dom/base/nsContentList.cpp +++ b/dom/base/nsContentList.cpp @@ -54,7 +54,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsBaseContentList) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsBaseContentList) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mElements) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(nsBaseContentList) diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index 98df92efb..299a8e859 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -13,10 +13,6 @@ #include <float.h> #endif -#if defined(SOLARIS) -#include <ieeefp.h> -#endif - #include "js/TypeDecls.h" #include "js/Value.h" #include "js/RootingAPI.h" diff --git a/dom/base/nsDOMAttributeMap.cpp b/dom/base/nsDOMAttributeMap.cpp index 381f267cd..2a90df7e4 100644 --- a/dom/base/nsDOMAttributeMap.cpp +++ b/dom/base/nsDOMAttributeMap.cpp @@ -65,7 +65,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMAttributeMap) for (auto iter = tmp->mAttributeCache.Iter(); !iter.Done(); iter.Next()) { cb.NoteXPCOMChild(static_cast<nsINode*>(iter.Data().get())); } - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContent) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END diff --git a/dom/base/nsDOMMutationObserver.cpp b/dom/base/nsDOMMutationObserver.cpp index 024ce5e2e..858a30ce5 100644 --- a/dom/base/nsDOMMutationObserver.cpp +++ b/dom/base/nsDOMMutationObserver.cpp @@ -506,7 +506,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMMutationObserver) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMMutationObserver) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mReceivers) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFirstPendingMutation) diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index d4d488379..a6ed419df 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -1590,10 +1590,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument) NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsDocument, tmp->mRefCnt.get()) } - // Always need to traverse script objects, so do that before we check - // if we're uncollectable. - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS - if (!nsINode::Traverse(tmp, cb)) { return NS_SUCCESS_INTERRUPTED_TRAVERSE; } diff --git a/dom/base/nsFrameMessageManager.cpp b/dom/base/nsFrameMessageManager.cpp index f4c4ca0f1..bba4232aa 100644 --- a/dom/base/nsFrameMessageManager.cpp +++ b/dom/base/nsFrameMessageManager.cpp @@ -132,7 +132,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFrameMessageManager) } NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildManagers) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParentManager) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsFrameMessageManager) diff --git a/dom/base/nsGenericDOMDataNode.cpp b/dom/base/nsGenericDOMDataNode.cpp index 9688588e0..0ae15e09e 100644 --- a/dom/base/nsGenericDOMDataNode.cpp +++ b/dom/base/nsGenericDOMDataNode.cpp @@ -98,10 +98,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGenericDOMDataNode) NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsGenericDOMDataNode, tmp->mRefCnt.get()) } - // Always need to traverse script objects, so do that before we check - // if we're uncollectable. - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS - if (!nsINode::Traverse(tmp, cb)) { return NS_SUCCESS_INTERRUPTED_TRAVERSE; } diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index de2ebdefe..ac85e34c0 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -2284,7 +2284,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindow) tmp->TraverseHostObjectURIs(cb); - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow) diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 4a984d294..dfd380fc2 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -625,7 +625,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSContext) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSContext) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobalObjectRef) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsJSContext) @@ -1356,9 +1355,20 @@ nsJSContext::RunCycleCollectorSlice() TimeStamp now = TimeStamp::Now(); // Only run a limited slice if we're within the max running time. - if (TimeBetween(gCCStats.mBeginTime, now) < kMaxICCDuration) { - float sliceMultiplier = std::max(TimeBetween(gCCStats.mEndSliceTime, now) / (float)kICCIntersliceDelay, 1.0f); - budget = js::SliceBudget(js::TimeBudget(kICCSliceBudget * sliceMultiplier)); + uint32_t runningTime = TimeBetween(gCCStats.mBeginTime, now); + if (runningTime < kMaxICCDuration) { + // Try to make up for a delay in running this slice. + float sliceDelayMultiplier = TimeBetween(gCCStats.mEndSliceTime, now) / (float)kICCIntersliceDelay; + float delaySliceBudget = kICCSliceBudget * sliceDelayMultiplier; + + // Increase slice budgets up to |maxLaterSlice| as we approach + // half way through the ICC, to avoid large sync CCs. + float percentToHalfDone = std::min(2.0f * runningTime / kMaxICCDuration, 1.0f); + const float maxLaterSlice = 40.0f; + float laterSliceBudget = maxLaterSlice * percentToHalfDone; + + budget = js::SliceBudget(js::TimeBudget(std::max({delaySliceBudget, + laterSliceBudget, (float)kICCSliceBudget}))); } } } @@ -2618,7 +2628,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSArgArray) tmp->ReleaseJSObjects(); NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSArgArray) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsJSArgArray) diff --git a/dom/base/nsJSTimeoutHandler.cpp b/dom/base/nsJSTimeoutHandler.cpp index 8736cd1dd..ce5d58385 100644 --- a/dom/base/nsJSTimeoutHandler.cpp +++ b/dom/base/nsJSTimeoutHandler.cpp @@ -151,7 +151,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsJSScriptTimeoutHandler) if (tmp->mFunction) { NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFunction) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS } NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END diff --git a/dom/base/nsMappedAttributes.h b/dom/base/nsMappedAttributes.h index 9fa7572dd..f00b888b9 100644 --- a/dom/base/nsMappedAttributes.h +++ b/dom/base/nsMappedAttributes.h @@ -93,20 +93,13 @@ private: nsAttrValue mValue; }; - /** - * Due to a compiler bug in VisualAge C++ for AIX, we need to return the - * address of the first index into mAttrs here, instead of simply - * returning mAttrs itself. - * - * See Bug 231104 for more information. - */ const InternalAttr* Attrs() const { - return reinterpret_cast<const InternalAttr*>(&(mAttrs[0])); + return reinterpret_cast<const InternalAttr*>(mAttrs); } InternalAttr* Attrs() { - return reinterpret_cast<InternalAttr*>(&(mAttrs[0])); + return reinterpret_cast<InternalAttr*>(mAttrs); } uint16_t mAttrCount; diff --git a/dom/base/nsRange.cpp b/dom/base/nsRange.cpp index 4b4ce7885..d45a2c975 100644 --- a/dom/base/nsRange.cpp +++ b/dom/base/nsRange.cpp @@ -351,7 +351,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsRange) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEndParent) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRoot) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSelection) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsRange) diff --git a/dom/base/nsScriptLoader.cpp b/dom/base/nsScriptLoader.cpp index 0eb5bbf31..1e23d6c5f 100644 --- a/dom/base/nsScriptLoader.cpp +++ b/dom/base/nsScriptLoader.cpp @@ -353,7 +353,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsModuleScript) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoader) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsModuleScript) diff --git a/dom/base/nsWrapperCache.cpp b/dom/base/nsWrapperCache.cpp index b91d86598..c5993fe7b 100644 --- a/dom/base/nsWrapperCache.cpp +++ b/dom/base/nsWrapperCache.cpp @@ -133,7 +133,7 @@ nsWrapperCache::CheckCCWrapperTraversal(void* aScriptObjectHolder, // see through the COM layer, so we use a suppression to help it. JS::AutoSuppressGCAnalysis suppress; - aTracer->Traverse(aScriptObjectHolder, callback); + aTracer->TraverseNativeAndJS(aScriptObjectHolder, callback); MOZ_ASSERT(callback.mFound, "Cycle collection participant didn't traverse to preserved " "wrapper! This will probably crash."); diff --git a/dom/base/nsWrapperCache.h b/dom/base/nsWrapperCache.h index 3c69a7ec4..56cae89ed 100644 --- a/dom/base/nsWrapperCache.h +++ b/dom/base/nsWrapperCache.h @@ -331,8 +331,7 @@ private: * causes between the native object and the JS object, so it is important that * any native object that supports preserving of its wrapper * traces/traverses/unlinks the cached JS object (see - * NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER, - * NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS and + * NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER and * NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER). */ enum { WRAPPER_BIT_PRESERVED = 1 << 0 }; @@ -383,7 +382,6 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsWrapperCache, NS_WRAPPERCACHE_IID) NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER \ NS_IMPL_CYCLE_COLLECTION_UNLINK_END \ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class) \ - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS \ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END \ NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(_class) @@ -395,7 +393,6 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsWrapperCache, NS_WRAPPERCACHE_IID) NS_IMPL_CYCLE_COLLECTION_UNLINK_END \ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class) \ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(__VA_ARGS__) \ - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS \ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END \ NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(_class) diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp index 323feca52..8d2bdaac6 100644 --- a/dom/bindings/BindingUtils.cpp +++ b/dom/bindings/BindingUtils.cpp @@ -2558,7 +2558,7 @@ NonVoidByteStringToJsval(JSContext *cx, const nsACString &str, template<typename T> static void -NormalizeUSVStringInternal(JSContext* aCx, T& aString) +NormalizeUSVStringInternal(T& aString) { char16_t* start = aString.BeginWriting(); // Must use const here because we can't pass char** to UTF16CharEnumerator as @@ -2575,15 +2575,15 @@ NormalizeUSVStringInternal(JSContext* aCx, T& aString) } void -NormalizeUSVString(JSContext* aCx, nsAString& aString) +NormalizeUSVString(nsAString& aString) { - NormalizeUSVStringInternal(aCx, aString); + NormalizeUSVStringInternal(aString); } void -NormalizeUSVString(JSContext* aCx, binding_detail::FakeString& aString) +NormalizeUSVString(binding_detail::FakeString& aString) { - NormalizeUSVStringInternal(aCx, aString); + NormalizeUSVStringInternal(aString); } bool diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h index 24b47a545..a3ec70f47 100644 --- a/dom/bindings/BindingUtils.h +++ b/dom/bindings/BindingUtils.h @@ -49,7 +49,7 @@ namespace mozilla { enum UseCounter : int16_t; namespace dom { -template<typename DataType> class MozMap; +template<typename KeyType, typename ValueType> class Record; nsresult UnwrapArgImpl(JS::Handle<JSObject*> src, const nsIID& iid, void** ppArg); @@ -2127,11 +2127,30 @@ ConvertJSValueToString(JSContext* cx, JS::Handle<JS::Value> v, return AssignJSString(cx, result, s); } +template<typename T> +static inline bool +ConvertJSValueToString(JSContext* cx, JS::Handle<JS::Value> v, T& result) +{ + return ConvertJSValueToString(cx, v, eStringify, eStringify, result); +} + void -NormalizeUSVString(JSContext* aCx, nsAString& aString); +NormalizeUSVString(nsAString& aString); void -NormalizeUSVString(JSContext* aCx, binding_detail::FakeString& aString); +NormalizeUSVString(binding_detail::FakeString& aString); + +template<typename T> +static inline bool +ConvertJSValueToUSVString(JSContext* cx, JS::Handle<JS::Value> v, T& result) +{ + if (!ConvertJSValueToString(cx, v, eStringify, eStringify, result)) { + return false; + } + + NormalizeUSVString(result); + return true; +} template<typename T> inline bool @@ -2158,6 +2177,13 @@ bool ConvertJSValueToByteString(JSContext* cx, JS::Handle<JS::Value> v, bool nullable, nsACString& result); +inline bool +ConvertJSValueToByteString(JSContext* cx, JS::Handle<JS::Value> v, + nsACString& result) +{ + return ConvertJSValueToByteString(cx, v, false, result); +} + template<typename T> void DoTraceSequence(JSTracer* trc, FallibleTArray<T>& seq); template<typename T> @@ -2293,31 +2319,26 @@ public: } }; -template<typename T> -static void -TraceMozMapValue(T* aValue, void* aClosure) -{ - JSTracer* trc = static_cast<JSTracer*>(aClosure); - // Act like it's a one-element sequence to leverage all that infrastructure. - SequenceTracer<T>::TraceSequence(trc, aValue, aValue + 1); -} - -template<typename T> -void TraceMozMap(JSTracer* trc, MozMap<T>& map) +template<typename K, typename V> +void TraceRecord(JSTracer* trc, Record<K, V>& record) { - map.EnumerateValues(TraceMozMapValue<T>, trc); + for (auto& entry : record.Entries()) { + // Act like it's a one-element sequence to leverage all that infrastructure. + SequenceTracer<V>::TraceSequence(trc, &entry.mValue, &entry.mValue + 1); + } } -// sequence<MozMap> -template<typename T> -class SequenceTracer<MozMap<T>, false, false, false> +// sequence<record> +template<typename K, typename V> +class SequenceTracer<Record<K, V>, false, false, false> { explicit SequenceTracer() = delete; // Should never be instantiated public: - static void TraceSequence(JSTracer* trc, MozMap<T>* seqp, MozMap<T>* end) { + static void TraceSequence(JSTracer* trc, Record<K, V>* seqp, + Record<K, V>* end) { for (; seqp != end; ++seqp) { - seqp->EnumerateValues(TraceMozMapValue<T>, trc); + TraceRecord(trc, *seqp); } } }; @@ -2395,51 +2416,51 @@ public: SequenceType mSequenceType; }; -// Rooter class for MozMap; this is what we mostly use in the codegen. -template<typename T> -class MOZ_RAII MozMapRooter final : private JS::CustomAutoRooter +// Rooter class for Record; this is what we mostly use in the codegen. +template<typename K, typename V> +class MOZ_RAII RecordRooter final : private JS::CustomAutoRooter { public: - MozMapRooter(JSContext *aCx, MozMap<T>* aMozMap + RecordRooter(JSContext *aCx, Record<K, V>* aRecord MOZ_GUARD_OBJECT_NOTIFIER_PARAM) : JS::CustomAutoRooter(aCx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT), - mMozMap(aMozMap), - mMozMapType(eMozMap) + mRecord(aRecord), + mRecordType(eRecord) { } - MozMapRooter(JSContext *aCx, Nullable<MozMap<T>>* aMozMap + RecordRooter(JSContext *aCx, Nullable<Record<K, V>>* aRecord MOZ_GUARD_OBJECT_NOTIFIER_PARAM) : JS::CustomAutoRooter(aCx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT), - mNullableMozMap(aMozMap), - mMozMapType(eNullableMozMap) + mNullableRecord(aRecord), + mRecordType(eNullableRecord) { } private: - enum MozMapType { - eMozMap, - eNullableMozMap + enum RecordType { + eRecord, + eNullableRecord }; virtual void trace(JSTracer *trc) override { - if (mMozMapType == eMozMap) { - TraceMozMap(trc, *mMozMap); + if (mRecordType == eRecord) { + TraceRecord(trc, *mRecord); } else { - MOZ_ASSERT(mMozMapType == eNullableMozMap); - if (!mNullableMozMap->IsNull()) { - TraceMozMap(trc, mNullableMozMap->Value()); + MOZ_ASSERT(mRecordType == eNullableRecord); + if (!mNullableRecord->IsNull()) { + TraceRecord(trc, mNullableRecord->Value()); } } } union { - MozMap<T>* mMozMap; - Nullable<MozMap<T>>* mNullableMozMap; + Record<K, V>* mRecord; + Nullable<Record<K, V>>* mNullableRecord; }; - MozMapType mMozMapType; + RecordType mRecordType; }; template<typename T> diff --git a/dom/bindings/CallbackObject.cpp b/dom/bindings/CallbackObject.cpp index 7c7d2c6b4..bb01c804c 100644 --- a/dom/bindings/CallbackObject.cpp +++ b/dom/bindings/CallbackObject.cpp @@ -37,7 +37,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CallbackObject) NS_IMPL_CYCLE_COLLECTION_UNLINK(mIncumbentGlobal) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CallbackObject) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIncumbentGlobal) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(CallbackObject) diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 7a6668687..74acb5918 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -84,7 +84,7 @@ def idlTypeNeedsCycleCollection(type): return True elif type.isUnion(): return any(idlTypeNeedsCycleCollection(t) for t in type.flatMemberTypes) - elif type.isMozMap(): + elif type.isRecord(): if idlTypeNeedsCycleCollection(type.inner): raise TypeError("Cycle collection for type %s is not supported" % type) return False @@ -996,6 +996,8 @@ class CGElseChain(CGThing): class CGTemplatedType(CGWrapper): def __init__(self, templateName, child, isConst=False, isReference=False): + if isinstance(child, list): + child = CGList(child, ", ") const = "const " if isConst else "" pre = "%s%s<" % (const, templateName) ref = "&" if isReference else "" @@ -1171,12 +1173,12 @@ class CGHeaders(CGWrapper): declareIncludes.add(filename) elif unrolled.isPrimitive(): bindingHeaders.add("mozilla/dom/PrimitiveConversions.h") - elif unrolled.isMozMap(): + elif unrolled.isRecord(): if dictionary or jsImplementedDescriptors: - declareIncludes.add("mozilla/dom/MozMap.h") + declareIncludes.add("mozilla/dom/Record.h") else: - bindingHeaders.add("mozilla/dom/MozMap.h") - # Also add headers for the type the MozMap is + bindingHeaders.add("mozilla/dom/Record.h") + # Also add headers for the type the record is # parametrized over, if needed. addHeadersForType((t.inner, dictionary)) @@ -1388,8 +1390,8 @@ def UnionTypes(unionTypes, config): # the right header to be able to Release() in our inlined # code. headers.add(CGHeaders.getDeclarationFilename(f.callback)) - elif f.isMozMap(): - headers.add("mozilla/dom/MozMap.h") + elif f.isRecord(): + headers.add("mozilla/dom/Record.h") # And add headers for the type we're parametrized over addHeadersForType(f.inner) @@ -1448,9 +1450,9 @@ def UnionConversions(unionTypes, config): headers.add(CGHeaders.getDeclarationFilename(f.inner)) elif f.isPrimitive(): headers.add("mozilla/dom/PrimitiveConversions.h") - elif f.isMozMap(): - headers.add("mozilla/dom/MozMap.h") - # And the internal type of the MozMap + elif f.isRecord(): + headers.add("mozilla/dom/Record.h") + # And the internal type of the record addHeadersForType(f.inner) # We plan to include UnionTypes.h no matter what, so it's @@ -4290,6 +4292,9 @@ class JSToNativeConversionInfo(): for whether we have a JS::Value. Only used when defaultValue is not None or when True is passed for checkForValue to instantiateJSToNativeConversion. + This expression may not be already-parenthesized, so if + you use it with && or || make sure to put parens + around it. ${passedToJSImpl} replaced by an expression that evaluates to a boolean for whether this value is being passed to a JS- implemented interface. @@ -4355,7 +4360,9 @@ def handleDefaultStringValue(defaultValue, method): passing as the second argument of handleDefault; in particular it does not end with a ';' """ - assert defaultValue.type.isDOMString() or defaultValue.type.isByteString() + assert (defaultValue.type.isDOMString() or + defaultValue.type.isUSVString() or + defaultValue.type.isByteString()) return ("static const %(char_t)s data[] = { %(data)s };\n" "%(method)s(data, ArrayLength(data) - 1)") % { 'char_t': "char" if defaultValue.type.isByteString() else "char16_t", @@ -4365,6 +4372,17 @@ def handleDefaultStringValue(defaultValue, method): } +def recordKeyType(recordType): + assert recordType.keyType.isString() + if recordType.keyType.isByteString(): + return "nsCString" + return "nsString" + + +def recordKeyDeclType(recordType): + return CGGeneric(recordKeyType(recordType)) + + # If this function is modified, modify CGNativeMember.getArg and # CGNativeMember.getRetvalInfo accordingly. The latter cares about the decltype # and holdertype we end up using, because it needs to be able to return the code @@ -4559,7 +4577,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, declArgs = "cx" else: assert (isMember in - ("Sequence", "Variadic", "Dictionary", "OwningUnion", "MozMap")) + ("Sequence", "Variadic", "Dictionary", "OwningUnion", "Record")) # We'll get traced by the sequence or dictionary or union tracer declType = CGGeneric("JSObject*") declArgs = None @@ -4725,39 +4743,41 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, dealWithOptional=isOptional, holderArgs=holderArgs) - if type.isMozMap(): + if type.isRecord(): assert not isEnforceRange and not isClamp if failureCode is None: - notMozMap = ('ThrowErrorMessage(cx, MSG_NOT_OBJECT, "%s");\n' + notRecord = ('ThrowErrorMessage(cx, MSG_NOT_OBJECT, "%s");\n' "%s" % (firstCap(sourceDescription), exceptionCode)) else: - notMozMap = failureCode + notRecord = failureCode nullable = type.nullable() # Be very careful not to change "type": we need it later if nullable: - valueType = type.inner.inner + recordType = type.inner else: - valueType = type.inner + recordType = type + valueType = recordType.inner valueInfo = getJSToNativeConversionInfo( - valueType, descriptorProvider, isMember="MozMap", + valueType, descriptorProvider, isMember="Record", exceptionCode=exceptionCode, lenientFloatCode=lenientFloatCode, isCallbackReturnValue=isCallbackReturnValue, sourceDescription="value in %s" % sourceDescription, nestingLevel=incrementNestingLevel()) if valueInfo.dealWithOptional: - raise TypeError("Shouldn't have optional things in MozMap") + raise TypeError("Shouldn't have optional things in record") if valueInfo.holderType is not None: - raise TypeError("Shouldn't need holders for MozMap") + raise TypeError("Shouldn't need holders for record") - typeName = CGTemplatedType("MozMap", valueInfo.declType) - mozMapType = typeName.define() + declType = CGTemplatedType("Record", [recordKeyDeclType(recordType), + valueInfo.declType]) + typeName = declType.define() if nullable: - typeName = CGTemplatedType("Nullable", typeName) - mozMapRef = "${declName}.SetValue()" + declType = CGTemplatedType("Nullable", declType) + recordRef = "${declName}.SetValue()" else: - mozMapRef = "${declName}" + recordRef = "${declName}" valueConversion = string.Template(valueInfo.template).substitute({ "val": "temp", @@ -4770,68 +4790,122 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, "passedToJSImpl": "${passedToJSImpl}" }) + keyType = recordKeyType(recordType) + if recordType.keyType.isByteString(): + keyConversionFunction = "ConvertJSValueToByteString" + hashKeyType = "nsCStringHashKey" + else: + hashKeyType = "nsStringHashKey" + if recordType.keyType.isDOMString(): + keyConversionFunction = "ConvertJSValueToString" + else: + assert recordType.keyType.isUSVString() + keyConversionFunction = "ConvertJSValueToUSVString" + templateBody = fill( """ - ${mozMapType} &mozMap = ${mozMapRef}; + auto& recordEntries = ${recordRef}.Entries(); - JS::Rooted<JSObject*> mozMapObj(cx, &$${val}.toObject()); - JS::Rooted<JS::IdVector> ids(cx, JS::IdVector(cx)); - if (!JS_Enumerate(cx, mozMapObj, &ids)) { + JS::Rooted<JSObject*> recordObj(cx, &$${val}.toObject()); + JS::AutoIdVector ids(cx); + if (!js::GetPropertyKeys(cx, recordObj, + JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS, &ids)) { + $*{exceptionCode} + } + if (!recordEntries.SetCapacity(ids.length(), mozilla::fallible)) { + JS_ReportOutOfMemory(cx); $*{exceptionCode} } JS::Rooted<JS::Value> propNameValue(cx); JS::Rooted<JS::Value> temp(cx); JS::Rooted<jsid> curId(cx); + JS::Rooted<JS::Value> idVal(cx); + // Use a hashset to keep track of ids seen, to avoid + // introducing nasty O(N^2) behavior scanning for them all the + // time. Ideally we'd use a data structure with O(1) lookup + // _and_ ordering for the MozMap, but we don't have one lying + // around. + nsTHashtable<${hashKeyType}> idsSeen; for (size_t i = 0; i < ids.length(); ++i) { - // Make sure we get the value before converting the name, since - // getting the value can trigger GC but our name is a dependent - // string. curId = ids[i]; - binding_detail::FakeString propName; - bool isSymbol; - if (!ConvertIdToString(cx, curId, propName, isSymbol) || - (!isSymbol && !JS_GetPropertyById(cx, mozMapObj, curId, &temp))) { + + JS::Rooted<JS::PropertyDescriptor> desc(cx); + if (!JS_GetOwnPropertyDescriptorById(cx, recordObj, curId, + &desc)) { $*{exceptionCode} } - if (isSymbol) { + + if (!desc.object() /* == undefined in spec terms */ || + !desc.enumerable()) { continue; } - ${valueType}* slotPtr = mozMap.AddEntry(propName); - if (!slotPtr) { - JS_ReportOutOfMemory(cx); + idVal = js::IdToValue(curId); + ${keyType} propName; + // This will just throw if idVal is a Symbol, like the spec says + // to do. + if (!${keyConversionFunction}(cx, idVal, propName)) { $*{exceptionCode} } - ${valueType}& slot = *slotPtr; + + if (!JS_GetPropertyById(cx, recordObj, curId, &temp)) { + $*{exceptionCode} + } + + ${typeName}::EntryType* entry; + if (idsSeen.Contains(propName)) { + // Find the existing entry. + auto idx = recordEntries.IndexOf(propName); + MOZ_ASSERT(idx != recordEntries.NoIndex, + "Why is it not found?"); + // Now blow it away to make it look like it was just added + // to the array, because it's not obvious that it's + // safe to write to its already-initialized mValue via our + // normal codegen conversions. For example, the value + // could be a union and this would change its type, but + // codegen assumes we won't do that. + entry = recordEntries.ReconstructElementAt(idx); + } else { + // Safe to do an infallible append here, because we did a + // SetCapacity above to the right capacity. + entry = recordEntries.AppendElement(); + idsSeen.PutEntry(propName); + } + entry->mKey = propName; + ${valueType}& slot = entry->mValue; $*{valueConversion} } """, exceptionCode=exceptionCode, - mozMapType=mozMapType, - mozMapRef=mozMapRef, + recordRef=recordRef, + hashKeyType=hashKeyType, + keyType=keyType, + keyConversionFunction=keyConversionFunction, + typeName=typeName, valueType=valueInfo.declType.define(), valueConversion=valueConversion) templateBody = wrapObjectTemplate(templateBody, type, "${declName}.SetNull();\n", - notMozMap) + notRecord) - declType = typeName declArgs = None holderType = None holderArgs = None - # MozMap arguments that might contain traceable things need + # record arguments that might contain traceable things need # to get traced if not isMember and isCallbackReturnValue: # Go ahead and just convert directly into our actual return value declType = CGWrapper(declType, post="&") declArgs = "aRetVal" elif not isMember and typeNeedsRooting(valueType): - holderType = CGTemplatedType("MozMapRooter", valueInfo.declType) - # If our MozMap is nullable, this will set the Nullable to be + holderType = CGTemplatedType("RecordRooter", + [recordKeyDeclType(recordType), + valueInfo.declType]) + # If our record is nullable, this will set the Nullable to be # not-null, but that's ok because we make an explicit SetNull() call # on it as needed if our JS value is actually null. - holderArgs = "cx, &%s" % mozMapRef + holderArgs = "cx, &%s" % recordRef return JSToNativeConversionInfo(templateBody, declType=declType, declArgs=declArgs, @@ -4914,16 +4988,16 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, else: setDictionary = None - mozMapMemberTypes = filter(lambda t: t.isMozMap(), memberTypes) - if len(mozMapMemberTypes) > 0: - assert len(mozMapMemberTypes) == 1 - name = getUnionMemberName(mozMapMemberTypes[0]) - mozMapObject = CGGeneric( + recordMemberTypes = filter(lambda t: t.isRecord(), memberTypes) + if len(recordMemberTypes) > 0: + assert len(recordMemberTypes) == 1 + name = getUnionMemberName(recordMemberTypes[0]) + recordObject = CGGeneric( "done = (failed = !%s.TrySetTo%s(cx, ${val}, tryNext, ${passedToJSImpl})) || !tryNext;\n" % (unionArgumentObj, name)) names.append(name) else: - mozMapObject = None + recordObject = None objectMemberTypes = filter(lambda t: t.isObject(), memberTypes) if len(objectMemberTypes) > 0: @@ -4939,10 +5013,10 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, else: object = None - hasObjectTypes = interfaceObject or sequenceObject or dateObject or callbackObject or object or mozMapObject + hasObjectTypes = interfaceObject or sequenceObject or dateObject or callbackObject or object or recordObject if hasObjectTypes: # "object" is not distinguishable from other types - assert not object or not (interfaceObject or sequenceObject or dateObject or callbackObject or mozMapObject) + assert not object or not (interfaceObject or sequenceObject or dateObject or callbackObject or recordObject) if sequenceObject or dateObject or callbackObject: # An object can be both an sequence object and a callback or # dictionary, but we shouldn't have both in the union's members @@ -4962,9 +5036,9 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, if dateObject: templateBody.prepend(CGGeneric("JS::Rooted<JSObject*> argObj(cx, &${val}.toObject());\n")) - if mozMapObject: + if recordObject: templateBody = CGList([templateBody, - CGIfWrapper(mozMapObject, "!done")]) + CGIfWrapper(recordObject, "!done")]) templateBody = CGIfWrapper(templateBody, "${val}.isObject()") else: @@ -5144,7 +5218,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, if isinstance(defaultValue, IDLNullValue): extraConditionForNull = "!(${haveValue}) || " else: - extraConditionForNull = "${haveValue} && " + extraConditionForNull = "(${haveValue}) && " else: extraConditionForNull = "" templateBody = handleNull(templateBody, declLoc, @@ -5525,7 +5599,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, def getConversionCode(varName): normalizeCode = "" if type.isUSVString(): - normalizeCode = "NormalizeUSVString(cx, %s);\n" % varName + normalizeCode = "NormalizeUSVString(%s);\n" % varName conversionCode = fill(""" if (!ConvertJSValueToString(cx, $${val}, ${nullBehavior}, ${undefinedBehavior}, ${varName})) { @@ -5688,7 +5762,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, haveCallable = "${val}.isObject() && " + haveCallable if defaultValue is not None: assert(isinstance(defaultValue, IDLNullValue)) - haveCallable = "${haveValue} && " + haveCallable + haveCallable = "(${haveValue}) && " + haveCallable template = ( ("if (%s) {\n" % haveCallable) + conversion + @@ -5700,7 +5774,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, haveObject = "${val}.isObject()" if defaultValue is not None: assert(isinstance(defaultValue, IDLNullValue)) - haveObject = "${haveValue} && " + haveObject + haveObject = "(${haveValue}) && " + haveObject template = CGIfElseWrapper(haveObject, CGGeneric(conversion), CGGeneric("${declName} = nullptr;\n")).define() @@ -5724,7 +5798,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, assert not isEnforceRange and not isClamp declArgs = None - if isMember in ("Variadic", "Sequence", "Dictionary", "MozMap"): + if isMember in ("Variadic", "Sequence", "Dictionary", "Record"): # Rooting is handled by the sequence and dictionary tracers. declType = "JS::Value" else: @@ -5768,8 +5842,9 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, return handleJSObjectType(type, isMember, failureCode, exceptionCode, sourceDescription) if type.isDictionary(): - # There are no nullable dictionaries - assert not type.nullable() or isCallbackReturnValue + # There are no nullable dictionary arguments or dictionary members + assert(not type.nullable() or isCallbackReturnValue or + (isMember and isMember != "Dictionary")) # All optional dictionaries always have default values, so we # should be able to assume not isOptional here. assert not isOptional @@ -6256,7 +6331,7 @@ def getMaybeWrapValueFuncForType(type): sequenceWrapLevel = 0 -mozMapWrapLevel = 0 +recordWrapLevel = 0 def getWrapTemplateForType(type, descriptorProvider, result, successCode, @@ -6361,7 +6436,7 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode, if type is None or type.isVoid(): return (setUndefined(), True) - if (type.isSequence() or type.isMozMap()) and type.nullable(): + if (type.isSequence() or type.isRecord()) and type.nullable(): # These are both wrapped in Nullable<> recTemplate, recInfall = getWrapTemplateForType(type.inner, descriptorProvider, "%s.Value()" % result, successCode, @@ -6434,14 +6509,14 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode, return (code, False) - if type.isMozMap(): - # Now do non-nullable MozMap. Our success code is just to break to + if type.isRecord(): + # Now do non-nullable record. Our success code is just to break to # where we define the property on the object. Note that we bump the - # mozMapWrapLevel around this call so that nested MozMap conversions + # recordWrapLevel around this call so that nested record conversions # will use different temp value names. - global mozMapWrapLevel - valueName = "mozMapValue%d" % mozMapWrapLevel - mozMapWrapLevel += 1 + global recordWrapLevel + valueName = "recordValue%d" % recordWrapLevel + recordWrapLevel += 1 innerTemplate = wrapForType( type.inner, descriptorProvider, { @@ -6454,12 +6529,22 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode, 'obj': "returnObj", 'typedArraysAreStructs': typedArraysAreStructs }) - mozMapWrapLevel -= 1 + recordWrapLevel -= 1 + if type.keyType.isByteString(): + # There is no length-taking JS_DefineProperty. So to keep + # things sane with embedded nulls, we want to byte-inflate + # to an nsAString. The only byte-inflation function we + # have around is AppendASCIItoUTF16, which luckily doesn't + # assert anything about the input being ASCII. + expandedKeyDecl = "NS_ConvertASCIItoUTF16 expandedKey(entry.mKey);\n" + keyName = "expandedKey" + else: + expandedKeyDecl = "" + keyName = "entry.mKey" + code = fill( """ - nsTArray<nsString> keys; - ${result}.GetKeys(keys); JS::Rooted<JSObject*> returnObj(cx, JS_NewPlainObject(cx)); if (!returnObj) { $*{exceptionCode} @@ -6467,15 +6552,17 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode, // Scope for 'tmp' { JS::Rooted<JS::Value> tmp(cx); - for (size_t idx = 0; idx < keys.Length(); ++idx) { - auto& ${valueName} = ${result}.Get(keys[idx]); + for (auto& entry : ${result}.Entries()) { + auto& ${valueName} = entry.mValue; // Control block to let us common up the JS_DefineUCProperty calls when there // are different ways to succeed at wrapping the value. do { $*{innerTemplate} } while (0); - if (!JS_DefineUCProperty(cx, returnObj, keys[idx].get(), - keys[idx].Length(), tmp, + $*{expandedKeyDecl} + if (!JS_DefineUCProperty(cx, returnObj, + ${keyName}.BeginReading(), + ${keyName}.Length(), tmp, JSPROP_ENUMERATE)) { $*{exceptionCode} } @@ -6487,6 +6574,8 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode, exceptionCode=exceptionCode, valueName=valueName, innerTemplate=innerTemplate, + expandedKeyDecl=expandedKeyDecl, + keyName=keyName, set=setObject("*returnObj")) return (code, False) @@ -6770,7 +6859,7 @@ def typeMatchesLambda(type, func): return False if type.nullable(): return typeMatchesLambda(type.inner, func) - if type.isSequence() or type.isMozMap(): + if type.isSequence() or type.isRecord(): return typeMatchesLambda(type.inner, func) if type.isUnion(): return any(typeMatchesLambda(t, func) for t in @@ -6866,20 +6955,21 @@ def getRetvalDeclarationForType(returnType, descriptorProvider, if nullable: result = CGTemplatedType("Nullable", result) return result, "ref", rooter, None, None - if returnType.isMozMap(): + if returnType.isRecord(): nullable = returnType.nullable() if nullable: returnType = returnType.inner result, _, _, _, _ = getRetvalDeclarationForType(returnType.inner, descriptorProvider, - isMember="MozMap") + isMember="Record") # While we have our inner type, set up our rooter, if needed if not isMember and typeNeedsRooting(returnType): - rooter = CGGeneric("MozMapRooter<%s> resultRooter(cx, &result);\n" % - result.define()) + rooter = CGGeneric("RecordRooter<%s> resultRooter(cx, &result);\n" % + ("nsString, " + result.define())) else: rooter = None - result = CGTemplatedType("MozMap", result) + result = CGTemplatedType("Record", [recordKeyDeclType(returnType), + result]) if nullable: result = CGTemplatedType("Nullable", result) return result, "ref", rooter, None, None @@ -6976,7 +7066,7 @@ class CGCallGenerator(CGThing): return True if a.type.isSequence(): return True - if a.type.isMozMap(): + if a.type.isRecord(): return True # isObject() types are always a JS::Rooted, whether # nullable or not, and it turns out a const JS::Rooted @@ -7138,7 +7228,7 @@ class MethodNotNewObjectError(Exception): # nested sequences we don't use the same variable name to iterate over # different sequences. sequenceWrapLevel = 0 -mapWrapLevel = 0 +recordWrapLevel = 0 def wrapTypeIntoCurrentCompartment(type, value, isMember=True): @@ -7199,29 +7289,27 @@ def wrapTypeIntoCurrentCompartment(type, value, isMember=True): wrapCode = CGIfWrapper(wrapCode, "!%s.IsNull()" % origValue) return wrapCode - if type.isMozMap(): - origValue = value + if type.isRecord(): origType = type if type.nullable(): type = type.inner - value = "%s.Value()" % value - global mapWrapLevel - key = "mapName%d" % mapWrapLevel - mapWrapLevel += 1 + recordRef = "%s.Value()" % value + else: + recordRef = value + global recordWrapLevel + entryRef = "mapEntry%d" % recordWrapLevel + recordWrapLevel += 1 wrapElement = wrapTypeIntoCurrentCompartment(type.inner, - "%s.Get(%sKeys[%sIndex])" % (value, key, key)) - mapWrapLevel -= 1 + "%s.mValue" % entryRef) + recordWrapLevel -= 1 if not wrapElement: return None wrapCode = CGWrapper(CGIndenter(wrapElement), - pre=(""" - nsTArray<nsString> %sKeys; - %s.GetKeys(%sKeys); - for (uint32_t %sIndex = 0; %sIndex < %sKeys.Length(); ++%sIndex) { - """ % (key, value, key, key, key, key, key)), + pre=("for (auto& %s : %s.Entries()) {\n" % + (entryRef, recordRef)), post="}\n") if origType.nullable(): - wrapCode = CGIfWrapper(wrapCode, "!%s.IsNull()" % origValue) + wrapCode = CGIfWrapper(wrapCode, "!%s.IsNull()" % value) return wrapCode if type.isDictionary(): @@ -8110,11 +8198,11 @@ class CGMethodCall(CGThing): if distinguishingType(s).isSequence()) # Now append all the overloads that take a dictionary or callback - # interface or MozMap. There should be only one of these! + # interface or record. There should be only one of these! genericObjectSigs = [ s for s in possibleSignatures if (distinguishingType(s).isDictionary() or - distinguishingType(s).isMozMap() or + distinguishingType(s).isRecord() or distinguishingType(s).isCallbackInterface())] assert len(genericObjectSigs) <= 1 objectSigs.extend(genericObjectSigs) @@ -9408,7 +9496,7 @@ class CGMemberJITInfo(CGThing): return "JSVAL_TYPE_UNDEFINED" if t.isSequence(): return "JSVAL_TYPE_OBJECT" - if t.isMozMap(): + if t.isRecord(): return "JSVAL_TYPE_OBJECT" if t.isGeckoInterface(): return "JSVAL_TYPE_OBJECT" @@ -9669,17 +9757,22 @@ def getUnionAccessorSignatureType(type, descriptorProvider): # Flat member types have already unwrapped nullables. assert not type.nullable() - if type.isSequence() or type.isMozMap(): + if type.isSequence() or type.isRecord(): if type.isSequence(): wrapperType = "Sequence" else: - wrapperType = "MozMap" + wrapperType = "Record" # We don't use the returned template here, so it's OK to just pass no # sourceDescription. elementInfo = getJSToNativeConversionInfo(type.inner, descriptorProvider, isMember=wrapperType) - return CGTemplatedType(wrapperType, elementInfo.declType, + if wrapperType == "Sequence": + innerType = elementInfo.declType + else: + innerType = [recordKeyDeclType(type), elementInfo.declType] + + return CGTemplatedType(wrapperType, innerType, isConst=True, isReference=True) # Nested unions are unwrapped automatically into our flatMemberTypes. @@ -10040,10 +10133,10 @@ class CGUnionStruct(CGThing): CGCase("e" + vars["name"], CGGeneric("DoTraceSequence(trc, mValue.m%s.Value());\n" % vars["name"]))) - elif t.isMozMap(): + elif t.isRecord(): traceCases.append( CGCase("e" + vars["name"], - CGGeneric("TraceMozMap(trc, mValue.m%s.Value());\n" % + CGGeneric("TraceRecord(trc, mValue.m%s.Value());\n" % vars["name"]))) else: assert t.isSpiderMonkeyInterface() @@ -13172,8 +13265,8 @@ class CGDictionary(CGThing): trace = CGGeneric('%s.TraceSelf(trc);\n' % memberData) if type.nullable(): trace = CGIfWrapper(trace, "!%s.IsNull()" % memberNullable) - elif type.isMozMap(): - # If you implement this, add a MozMap<object> to + elif type.isRecord(): + # If you implement this, add a record<DOMString, object> to # TestInterfaceJSDictionary and test it in test_bug1036214.html # to make sure we end up with the correct security properties. assert False @@ -13583,7 +13676,7 @@ class ForwardDeclarationBuilder: # since we don't know which one we might want self.addInMozillaDom(CGUnionStruct.unionTypeName(t, False)) self.addInMozillaDom(CGUnionStruct.unionTypeName(t, True)) - elif t.isMozMap(): + elif t.isRecord(): self.forwardDeclareForType(t.inner, config) # Don't need to do anything for void, primitive, string, any or object. # There may be some other cases we are missing. @@ -14089,9 +14182,9 @@ class CGNativeMember(ClassMethod): else: returnCode = "aRetVal.SwapElements(${declName});\n" return "void", "", returnCode - if type.isMozMap(): - # If we want to handle MozMap-of-MozMap return values, we're - # going to need to fix example codegen to not produce MozMap<void> + if type.isRecord(): + # If we want to handle record-of-record return values, we're + # going to need to fix example codegen to not produce record<void> # for the relevant argument... assert not isMember # In this case we convert directly into our outparam to start with @@ -14139,13 +14232,14 @@ class CGNativeMember(ClassMethod): if nullable: type = CGTemplatedType("Nullable", type) args.append(Argument("%s&" % type.define(), "aRetVal")) - elif returnType.isMozMap(): + elif returnType.isRecord(): nullable = returnType.nullable() if nullable: returnType = returnType.inner # And now the actual underlying type elementDecl = self.getReturnType(returnType.inner, True) - type = CGTemplatedType("MozMap", CGGeneric(elementDecl)) + type = CGTemplatedType("Record", [recordKeyDeclType(returnType), + CGGeneric(elementDecl)]) if nullable: type = CGTemplatedType("Nullable", type) args.append(Argument("%s&" % type.define(), "aRetVal")) @@ -14206,7 +14300,7 @@ class CGNativeMember(ClassMethod): Nullable as needed. isMember can be false or one of the strings "Sequence", "Variadic", - "MozMap" + "Record" """ if type.isSequence(): nullable = type.nullable() @@ -14217,13 +14311,13 @@ class CGNativeMember(ClassMethod): decl = CGTemplatedType("Sequence", argType) return decl.define(), True, True - if type.isMozMap(): + if type.isRecord(): nullable = type.nullable() if nullable: type = type.inner elementType = type.inner - argType = self.getArgType(elementType, False, "MozMap")[0] - decl = CGTemplatedType("MozMap", argType) + argType = self.getArgType(elementType, False, "Record")[0] + decl = CGTemplatedType("Record", [recordKeyDeclType(type), argType]) return decl.define(), True, True if type.isUnion(): @@ -14994,7 +15088,6 @@ class CGJSImplClass(CGBindingImplClass): NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(${ifaceName}) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mImpl) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(${ifaceName}) NS_IMPL_CYCLE_COLLECTING_ADDREF(${ifaceName}) diff --git a/dom/bindings/Configuration.py b/dom/bindings/Configuration.py index 5c96580a1..f80c19c33 100644 --- a/dom/bindings/Configuration.py +++ b/dom/bindings/Configuration.py @@ -115,7 +115,7 @@ class Configuration(DescriptorProvider): for (t, _) in getAllTypes(self.descriptors, self.dictionaries, self.callbacks): while True: - if t.isMozMap(): + if t.isRecord(): t = t.inner elif t.unroll() != t: t = t.unroll() diff --git a/dom/bindings/Exceptions.cpp b/dom/bindings/Exceptions.cpp index a3f807688..8ace37051 100644 --- a/dom/bindings/Exceptions.cpp +++ b/dom/bindings/Exceptions.cpp @@ -305,7 +305,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(JSStackFrame) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCaller) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAsyncCaller) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(JSStackFrame) NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mStack) diff --git a/dom/bindings/MozMap.h b/dom/bindings/MozMap.h deleted file mode 100644 index 1e920c098..000000000 --- a/dom/bindings/MozMap.h +++ /dev/null @@ -1,121 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/** - * Class for representing MozMap arguments. This is an nsTHashtable - * under the hood, but we don't want to leak that implementation - * detail. - */ - -#ifndef mozilla_dom_MozMap_h -#define mozilla_dom_MozMap_h - -#include "nsTHashtable.h" -#include "nsHashKeys.h" -#include "nsStringGlue.h" -#include "nsTArray.h" -#include "mozilla/Attributes.h" -#include "mozilla/Move.h" - -namespace mozilla { -namespace dom { - -namespace binding_detail { -template<typename DataType> -class MozMapEntry : public nsStringHashKey -{ -public: - explicit MozMapEntry(const nsAString* aKeyTypePointer) - : nsStringHashKey(aKeyTypePointer) - { - } - - // Move constructor so we can do MozMaps of MozMaps. - MozMapEntry(MozMapEntry<DataType>&& aOther) - : nsStringHashKey(aOther), - mData(Move(aOther.mData)) - { - } - - DataType mData; -}; - -} // namespace binding_detail - -template<typename DataType> -class MozMap : protected nsTHashtable<binding_detail::MozMapEntry<DataType>> -{ -public: - typedef typename binding_detail::MozMapEntry<DataType> EntryType; - typedef nsTHashtable<EntryType> Base; - typedef MozMap<DataType> SelfType; - - MozMap() - { - } - - // Move constructor so we can do MozMap of MozMap. - MozMap(SelfType&& aOther) : - Base(Move(aOther)) - { - } - - // The return value is only safe to use until an AddEntry call. - const DataType& Get(const nsAString& aKey) const - { - const EntryType* ent = this->GetEntry(aKey); - MOZ_ASSERT(ent, "Why are you using a key we didn't claim to have?"); - return ent->mData; - } - - DataType& Get(const nsAString& aKey) - { - EntryType* ent = this->GetEntry(aKey); - MOZ_ASSERT(ent, "Why are you using a key we didn't claim to have?"); - return ent->mData; - } - - // The return value is only safe to use until an AddEntry call. - const DataType* GetIfExists(const nsAString& aKey) const - { - const EntryType* ent = this->GetEntry(aKey); - if (!ent) { - return nullptr; - } - return &ent->mData; - } - - void GetKeys(nsTArray<nsString>& aKeys) const { - for (auto iter = this->ConstIter(); !iter.Done(); iter.Next()) { - aKeys.AppendElement(iter.Get()->GetKey()); - } - } - - // XXXbz we expose this generic enumerator for tracing. Otherwise we'd end up - // with a dependency on BindingUtils.h here for the SequenceTracer bits. - typedef void (* Enumerator)(DataType* aValue, void* aClosure); - void EnumerateValues(Enumerator aEnumerator, void *aClosure) - { - for (auto iter = this->Iter(); !iter.Done(); iter.Next()) { - aEnumerator(&iter.Get()->mData, aClosure); - } - } - - MOZ_MUST_USE - DataType* AddEntry(const nsAString& aKey) - { - EntryType* ent = this->PutEntry(aKey, fallible); - if (!ent) { - return nullptr; - } - return &ent->mData; - } -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_MozMap_h diff --git a/dom/bindings/Record.h b/dom/bindings/Record.h new file mode 100644 index 000000000..d6ab31699 --- /dev/null +++ b/dom/bindings/Record.h @@ -0,0 +1,91 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Class for representing record arguments. Basically an array under the hood. + */ + +#ifndef mozilla_dom_Record_h +#define mozilla_dom_Record_h + +#include "nsTHashtable.h" +#include "nsHashKeys.h" +#include "nsStringGlue.h" +#include "nsTArray.h" +#include "mozilla/Attributes.h" +#include "mozilla/Move.h" + +namespace mozilla { +namespace dom { + +namespace binding_detail { +template<typename KeyType, typename ValueType> +class RecordEntry +{ +public: + RecordEntry() + { + } + + // Move constructor so we can do Records of Records. + RecordEntry(RecordEntry<KeyType, ValueType>&& aOther) + : mKey(Move(aOther.mKey)), + mValue(Move(aOther.mValue)) + { + } + + KeyType mKey; + ValueType mValue; +}; + +} // namespace binding_detail + +template<typename KeyType, typename ValueType> +class Record +{ +public: + typedef typename binding_detail::RecordEntry<KeyType, ValueType> EntryType; + typedef Record<KeyType, ValueType> SelfType; + + Record() + { + } + + // Move constructor so we can do Record of Record. + Record(SelfType&& aOther) : + mEntries(Move(aOther.mEntries)) + { + } + + const nsTArray<EntryType>& Entries() const + { + return mEntries; + } + + nsTArray<EntryType>& Entries() + { + return mEntries; + } + +private: + nsTArray<EntryType> mEntries; +}; + +} // namespace dom +} // namespace mozilla + +template<typename K, typename V> +class nsDefaultComparator<mozilla::dom::binding_detail::RecordEntry<K, V>, K> +{ +public: + bool Equals(const mozilla::dom::binding_detail::RecordEntry<K, V>& aEntry, + const K& aKey) const + { + return aEntry.mKey == aKey; + } +}; + +#endif // mozilla_dom_Record_h diff --git a/dom/bindings/SimpleGlobalObject.cpp b/dom/bindings/SimpleGlobalObject.cpp index 6ac397019..88710f7d9 100644 --- a/dom/bindings/SimpleGlobalObject.cpp +++ b/dom/bindings/SimpleGlobalObject.cpp @@ -29,8 +29,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(SimpleGlobalObject) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(SimpleGlobalObject) - - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS tmp->TraverseHostObjectURIs(cb); NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END diff --git a/dom/bindings/moz.build b/dom/bindings/moz.build index f1ce9e276..7e1358e9c 100644 --- a/dom/bindings/moz.build +++ b/dom/bindings/moz.build @@ -32,10 +32,10 @@ EXPORTS.mozilla.dom += [ 'FakeString.h', 'IterableIterator.h', 'JSSlots.h', - 'MozMap.h', 'NonRefcountedDOMObject.h', 'Nullable.h', 'PrimitiveConversions.h', + 'Record.h', 'RootedDictionary.h', 'SimpleGlobalObject.h', 'StructuredClone.h', diff --git a/dom/bindings/parser/WebIDL.py b/dom/bindings/parser/WebIDL.py index f668d7d62..8c32a8738 100644 --- a/dom/bindings/parser/WebIDL.py +++ b/dom/bindings/parser/WebIDL.py @@ -1867,7 +1867,7 @@ class IDLDictionary(IDLObjectWithScope): if (memberType.nullable() or memberType.isSequence() or - memberType.isMozMap()): + memberType.isRecord()): return typeContainsDictionary(memberType.inner, dictionary) if memberType.isDictionary(): @@ -1988,7 +1988,7 @@ class IDLType(IDLObject): 'callback', 'union', 'sequence', - 'mozmap' + 'record' ) def __init__(self, location, name): @@ -2038,7 +2038,7 @@ class IDLType(IDLObject): def isSequence(self): return False - def isMozMap(self): + def isRecord(self): return False def isArrayBuffer(self): @@ -2263,8 +2263,8 @@ class IDLNullableType(IDLParameterizedType): def isSequence(self): return self.inner.isSequence() - def isMozMap(self): - return self.inner.isMozMap() + def isRecord(self): + return self.inner.isRecord() def isArrayBuffer(self): return self.inner.isArrayBuffer() @@ -2321,8 +2321,10 @@ class IDLNullableType(IDLParameterizedType): return self def isDistinguishableFrom(self, other): - if (other.nullable() or (other.isUnion() and other.hasNullableType) or - other.isDictionary()): + if (other.nullable() or + other.isDictionary() or + (other.isUnion() and + (other.hasNullableType or other.hasDictionaryType()))): # Can't tell which type null should become return False return self.inner.isDistinguishableFrom(other) @@ -2397,34 +2399,38 @@ class IDLSequenceType(IDLParameterizedType): return (other.isPrimitive() or other.isString() or other.isEnum() or other.isDate() or other.isInterface() or other.isDictionary() or - other.isCallback() or other.isMozMap()) + other.isCallback() or other.isRecord()) -class IDLMozMapType(IDLParameterizedType): - def __init__(self, location, parameterType): - assert not parameterType.isVoid() +class IDLRecordType(IDLParameterizedType): + def __init__(self, location, keyType, valueType): + assert keyType.isString() + assert keyType.isComplete() + assert not valueType.isVoid() + + IDLParameterizedType.__init__(self, location, valueType.name, valueType) + self.keyType = keyType - IDLParameterizedType.__init__(self, location, parameterType.name, parameterType) # Need to set self.name up front if our inner type is already complete, # since in that case our .complete() won't be called. if self.inner.isComplete(): - self.name = self.inner.name + "MozMap" + self.name = self.keyType.name + self.inner.name + "Record" def __eq__(self, other): - return isinstance(other, IDLMozMapType) and self.inner == other.inner + return isinstance(other, IDLRecordType) and self.inner == other.inner def __str__(self): - return self.inner.__str__() + "MozMap" + return self.keyType.__str__() + self.inner.__str__() + "Record" - def isMozMap(self): + def isRecord(self): return True def tag(self): - return IDLType.Tags.mozmap + return IDLType.Tags.record def complete(self, scope): self.inner = self.inner.complete(scope) - self.name = self.inner.name + "MozMap" + self.name = self.keyType.name + self.inner.name + "Record" return self def unroll(self): @@ -2614,8 +2620,8 @@ class IDLTypedefType(IDLType): def isSequence(self): return self.inner.isSequence() - def isMozMap(self): - return self.inner.isMozMap() + def isRecord(self): + return self.inner.isRecord() def isDictionary(self): return self.inner.isDictionary() @@ -2798,7 +2804,7 @@ class IDLWrapperType(IDLType): if self.isEnum(): return (other.isPrimitive() or other.isInterface() or other.isObject() or other.isCallback() or other.isDictionary() or - other.isSequence() or other.isMozMap() or other.isDate()) + other.isSequence() or other.isRecord() or other.isDate()) if self.isDictionary() and other.nullable(): return False if (other.isPrimitive() or other.isString() or other.isEnum() or @@ -2820,7 +2826,7 @@ class IDLWrapperType(IDLType): (self.isNonCallbackInterface() or other.isNonCallbackInterface())) if (other.isDictionary() or other.isCallback() or - other.isMozMap()): + other.isRecord()): return self.isNonCallbackInterface() # Not much else |other| can be @@ -3030,17 +3036,17 @@ class IDLBuiltinType(IDLType): return (other.isNumeric() or other.isString() or other.isEnum() or other.isInterface() or other.isObject() or other.isCallback() or other.isDictionary() or - other.isSequence() or other.isMozMap() or other.isDate()) + other.isSequence() or other.isRecord() or other.isDate()) if self.isNumeric(): return (other.isBoolean() or other.isString() or other.isEnum() or other.isInterface() or other.isObject() or other.isCallback() or other.isDictionary() or - other.isSequence() or other.isMozMap() or other.isDate()) + other.isSequence() or other.isRecord() or other.isDate()) if self.isString(): return (other.isPrimitive() or other.isInterface() or other.isObject() or other.isCallback() or other.isDictionary() or - other.isSequence() or other.isMozMap() or other.isDate()) + other.isSequence() or other.isRecord() or other.isDate()) if self.isAny(): # Can't tell "any" apart from anything return False @@ -3050,7 +3056,7 @@ class IDLBuiltinType(IDLType): return (other.isPrimitive() or other.isString() or other.isEnum() or other.isInterface() or other.isCallback() or other.isDictionary() or other.isSequence() or - other.isMozMap()) + other.isRecord()) if self.isVoid(): return not other.isVoid() # Not much else we could be! @@ -3058,7 +3064,7 @@ class IDLBuiltinType(IDLType): # Like interfaces, but we know we're not a callback return (other.isPrimitive() or other.isString() or other.isEnum() or other.isCallback() or other.isDictionary() or - other.isSequence() or other.isMozMap() or other.isDate() or + other.isSequence() or other.isRecord() or other.isDate() or (other.isInterface() and ( # ArrayBuffer is distinguishable from everything # that's not an ArrayBuffer or a callback interface @@ -3843,6 +3849,9 @@ class IDLConst(IDLInterfaceMember): if type.isDictionary(): raise WebIDLError("A constant cannot be of a dictionary type", [self.location]) + if type.isRecord(): + raise WebIDLError("A constant cannot be of a record type", + [self.location]) self.type = type self.value = value @@ -3954,8 +3963,8 @@ class IDLAttribute(IDLInterfaceMember): if self.type.isSequence() and not self.getExtendedAttribute("Cached"): raise WebIDLError("A non-cached attribute cannot be of a sequence " "type", [self.location]) - if self.type.isMozMap() and not self.getExtendedAttribute("Cached"): - raise WebIDLError("A non-cached attribute cannot be of a MozMap " + if self.type.isRecord() and not self.getExtendedAttribute("Cached"): + raise WebIDLError("A non-cached attribute cannot be of a record " "type", [self.location]) if self.type.isUnion(): for f in self.type.unroll().flatMemberTypes: @@ -3971,11 +3980,11 @@ class IDLAttribute(IDLInterfaceMember): "one of its member types's member " "types, and so on) is a sequence " "type", [self.location, f.location]) - if f.isMozMap(): + if f.isRecord(): raise WebIDLError("An attribute cannot be of a union " "type if one of its member types (or " "one of its member types's member " - "types, and so on) is a MozMap " + "types, and so on) is a record " "type", [self.location, f.location]) if not self.type.isInterface() and self.getExtendedAttribute("PutForwards"): raise WebIDLError("An attribute with [PutForwards] must have an " @@ -3989,7 +3998,7 @@ class IDLAttribute(IDLInterfaceMember): def typeContainsChromeOnlyDictionaryMember(type): if (type.nullable() or type.isSequence() or - type.isMozMap()): + type.isRecord()): return typeContainsChromeOnlyDictionaryMember(type.inner) if type.isUnion(): @@ -4035,10 +4044,10 @@ class IDLAttribute(IDLInterfaceMember): [self.location, location]) if self.getExtendedAttribute("Frozen"): if (not self.type.isSequence() and not self.type.isDictionary() and - not self.type.isMozMap()): + not self.type.isRecord()): raise WebIDLError("[Frozen] is only allowed on " "sequence-valued, dictionary-valued, and " - "MozMap-valued attributes", + "record-valued attributes", [self.location]) if not self.type.unroll().isExposedInAllOf(self.exposureSet): raise WebIDLError("Attribute returns a type that is not exposed " @@ -5147,7 +5156,7 @@ class Tokenizer(object): "Promise": "PROMISE", "required": "REQUIRED", "sequence": "SEQUENCE", - "MozMap": "MOZMAP", + "record": "RECORD", "short": "SHORT", "unsigned": "UNSIGNED", "void": "VOID", @@ -6276,7 +6285,7 @@ class Parser(Tokenizer): | OCTET | OPTIONAL | SEQUENCE - | MOZMAP + | RECORD | SETTER | SHORT | STATIC @@ -6355,7 +6364,7 @@ class Parser(Tokenizer): def p_NonAnyType(self, p): """ - NonAnyType : PrimitiveOrStringType Null + NonAnyType : PrimitiveType Null | ARRAYBUFFER Null | SHAREDARRAYBUFFER Null | OBJECT Null @@ -6371,6 +6380,12 @@ class Parser(Tokenizer): p[0] = self.handleNullable(type, p[2]) + def p_NonAnyTypeStringType(self, p): + """ + NonAnyType : StringType Null + """ + p[0] = self.handleNullable(p[1], p[2]) + def p_NonAnyTypeSequenceType(self, p): """ NonAnyType : SEQUENCE LT Type GT Null @@ -6391,13 +6406,14 @@ class Parser(Tokenizer): type = IDLUnresolvedType(self.getLocation(p, 1), promiseIdent, p[3]) p[0] = self.handleNullable(type, p[5]) - def p_NonAnyTypeMozMapType(self, p): + def p_NonAnyTypeRecordType(self, p): """ - NonAnyType : MOZMAP LT Type GT Null + NonAnyType : RECORD LT StringType COMMA Type GT Null """ - innerType = p[3] - type = IDLMozMapType(self.getLocation(p, 1), innerType) - p[0] = self.handleNullable(type, p[5]) + keyType = p[3] + valueType = p[5] + type = IDLRecordType(self.getLocation(p, 1), keyType, valueType) + p[0] = self.handleNullable(type, p[7]) def p_NonAnyTypeScopedName(self, p): """ @@ -6440,7 +6456,7 @@ class Parser(Tokenizer): def p_ConstType(self, p): """ - ConstType : PrimitiveOrStringType Null + ConstType : PrimitiveType Null """ type = BuiltinTypes[p[1]] p[0] = self.handleNullable(type, p[2]) @@ -6454,69 +6470,75 @@ class Parser(Tokenizer): type = IDLUnresolvedType(self.getLocation(p, 1), identifier) p[0] = self.handleNullable(type, p[2]) - def p_PrimitiveOrStringTypeUint(self, p): + def p_PrimitiveTypeUint(self, p): """ - PrimitiveOrStringType : UnsignedIntegerType + PrimitiveType : UnsignedIntegerType """ p[0] = p[1] - def p_PrimitiveOrStringTypeBoolean(self, p): + def p_PrimitiveTypeBoolean(self, p): """ - PrimitiveOrStringType : BOOLEAN + PrimitiveType : BOOLEAN """ p[0] = IDLBuiltinType.Types.boolean - def p_PrimitiveOrStringTypeByte(self, p): + def p_PrimitiveTypeByte(self, p): """ - PrimitiveOrStringType : BYTE + PrimitiveType : BYTE """ p[0] = IDLBuiltinType.Types.byte - def p_PrimitiveOrStringTypeOctet(self, p): + def p_PrimitiveTypeOctet(self, p): """ - PrimitiveOrStringType : OCTET + PrimitiveType : OCTET """ p[0] = IDLBuiltinType.Types.octet - def p_PrimitiveOrStringTypeFloat(self, p): + def p_PrimitiveTypeFloat(self, p): """ - PrimitiveOrStringType : FLOAT + PrimitiveType : FLOAT """ p[0] = IDLBuiltinType.Types.float - def p_PrimitiveOrStringTypeUnrestictedFloat(self, p): + def p_PrimitiveTypeUnrestictedFloat(self, p): """ - PrimitiveOrStringType : UNRESTRICTED FLOAT + PrimitiveType : UNRESTRICTED FLOAT """ p[0] = IDLBuiltinType.Types.unrestricted_float - def p_PrimitiveOrStringTypeDouble(self, p): + def p_PrimitiveTypeDouble(self, p): """ - PrimitiveOrStringType : DOUBLE + PrimitiveType : DOUBLE """ p[0] = IDLBuiltinType.Types.double - def p_PrimitiveOrStringTypeUnrestictedDouble(self, p): + def p_PrimitiveTypeUnrestictedDouble(self, p): """ - PrimitiveOrStringType : UNRESTRICTED DOUBLE + PrimitiveType : UNRESTRICTED DOUBLE """ p[0] = IDLBuiltinType.Types.unrestricted_double - def p_PrimitiveOrStringTypeDOMString(self, p): + def p_StringType(self, p): + """ + StringType : BuiltinStringType + """ + p[0] = BuiltinTypes[p[1]] + + def p_BuiltinStringTypeDOMString(self, p): """ - PrimitiveOrStringType : DOMSTRING + BuiltinStringType : DOMSTRING """ p[0] = IDLBuiltinType.Types.domstring - def p_PrimitiveOrStringTypeBytestring(self, p): + def p_BuiltinStringTypeBytestring(self, p): """ - PrimitiveOrStringType : BYTESTRING + BuiltinStringType : BYTESTRING """ p[0] = IDLBuiltinType.Types.bytestring - def p_PrimitiveOrStringTypeUSVString(self, p): + def p_BuiltinStringTypeUSVString(self, p): """ - PrimitiveOrStringType : USVSTRING + BuiltinStringType : USVSTRING """ p[0] = IDLBuiltinType.Types.usvstring diff --git a/dom/browser-element/BrowserElementParent.js b/dom/browser-element/BrowserElementParent.js index 67d05f0ab..8e4475bfa 100644 --- a/dom/browser-element/BrowserElementParent.js +++ b/dom/browser-element/BrowserElementParent.js @@ -23,15 +23,6 @@ function debug(msg) { //dump("BrowserElementParent - " + msg + "\n"); } -function getIntPref(prefName, def) { - try { - return Services.prefs.getIntPref(prefName); - } - catch(err) { - return def; - } -} - function handleWindowEvent(e) { if (this._browserElementParents) { let beps = ThreadSafeChromeUtils.nondeterministicGetWeakMapKeys(this._browserElementParents); @@ -856,8 +847,8 @@ BrowserElementParent.prototype = { */ zoom: defineNoReturnMethod(function(zoom) { zoom *= 100; - zoom = Math.min(getIntPref("zoom.maxPercent", 300), zoom); - zoom = Math.max(getIntPref("zoom.minPercent", 50), zoom); + zoom = Math.min(Services.prefs.getIntPref("zoom.maxPercent", 300), zoom); + zoom = Math.max(Services.prefs.getIntPref("zoom.minPercent", 50), zoom); this._sendAsyncMsg('zoom', {zoom: zoom / 100.0}); }), diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp index e3406fc02..4849fda57 100644 --- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -1047,7 +1047,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CanvasRenderingContext2D) ImplCycleCollectionTraverse(cb, info.mElement, "Hit region fallback element"); } } - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(CanvasRenderingContext2D) @@ -1106,6 +1105,7 @@ CanvasRenderingContext2D::CanvasRenderingContext2D(layers::LayersBackend aCompos , mIsCapturedFrameInvalid(false) , mPathTransformWillUpdate(false) , mInvalidateCount(0) + , mWriteOnly(false) // == !origin-clean { sNumLivingContexts++; @@ -2563,7 +2563,8 @@ CanvasRenderingContext2D::CreatePattern(const CanvasImageSource& aSource, // nullptr and set CORSUsed to true for passing the security check in // CanvasUtils::DoDrawImageSecurityCheck(). RefPtr<CanvasPattern> pat = - new CanvasPattern(this, srcSurf, repeatMode, nullptr, false, true); + new CanvasPattern(this, srcSurf, repeatMode, nullptr, + imgBitmap.IsWriteOnly(), true); return pat.forget(); } @@ -4953,6 +4954,10 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage, aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); return; } + + if (canvas->IsWriteOnly()) { + SetWriteOnly(); + } } else if (aImage.IsImageBitmap()) { ImageBitmap& imageBitmap = aImage.GetAsImageBitmap(); srcSurf = imageBitmap.PrepareForDrawTarget(mTarget); @@ -4961,6 +4966,10 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage, return; } + if (imageBitmap.IsWriteOnly()) { + SetWriteOnly(); + } + imgSize = gfx::IntSize(imageBitmap.Width(), imageBitmap.Height()); } else { @@ -5675,9 +5684,8 @@ CanvasRenderingContext2D::GetImageData(JSContext* aCx, double aSx, // Check only if we have a canvas element; if we were created with a docshell, // then it's special internal use. - if (mCanvasElement && mCanvasElement->IsWriteOnly() && - !nsContentUtils::IsCallerChrome()) - { + if (IsWriteOnly() || + (mCanvasElement && mCanvasElement->IsWriteOnly() && !nsContentUtils::IsCallerChrome())) { // XXX ERRMSG we need to report an error to developers here! (bug 329026) aError.Throw(NS_ERROR_DOM_SECURITY_ERR); return nullptr; @@ -6321,6 +6329,13 @@ CanvasRenderingContext2D::ShouldForceInactiveLayer(LayerManager* aManager) return !aManager->CanUseCanvasLayerForSize(GetSize()); } +void CanvasRenderingContext2D::SetWriteOnly() { + mWriteOnly = true; + if (mCanvasElement) { + mCanvasElement->SetWriteOnly(); + } +} + NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(CanvasPath, AddRef) NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(CanvasPath, Release) diff --git a/dom/canvas/CanvasRenderingContext2D.h b/dom/canvas/CanvasRenderingContext2D.h index 848b3ee08..d4f295a03 100644 --- a/dom/canvas/CanvasRenderingContext2D.h +++ b/dom/canvas/CanvasRenderingContext2D.h @@ -40,6 +40,7 @@ class SourceSurface; namespace dom { class HTMLImageElementOrSVGImageElementOrHTMLCanvasElementOrHTMLVideoElementOrImageBitmap; typedef HTMLImageElementOrSVGImageElementOrHTMLCanvasElementOrHTMLVideoElementOrImageBitmap CanvasImageSource; +class ImageBitmap; class ImageData; class StringOrCanvasGradientOrCanvasPattern; class OwningStringOrCanvasGradientOrCanvasPattern; @@ -1151,6 +1152,17 @@ protected: friend struct CanvasBidiProcessor; friend class CanvasDrawObserver; + friend class ImageBitmap; + + // For the origin-clean algorithm (mWriteOnly == !origin-clean) + // See https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html + void SetWriteOnly(); + + bool IsWriteOnly() const { + return mWriteOnly; + } + + bool mWriteOnly; }; } // namespace dom diff --git a/dom/canvas/ImageBitmap.cpp b/dom/canvas/ImageBitmap.cpp index e45cdfc6f..6efe1b318 100644 --- a/dom/canvas/ImageBitmap.cpp +++ b/dom/canvas/ImageBitmap.cpp @@ -351,29 +351,27 @@ CheckSecurityForHTMLElements(const nsLayoutUtils::SurfaceFromElementResult& aRes */ template<class HTMLElementType> static already_AddRefed<SourceSurface> -GetSurfaceFromElement(nsIGlobalObject* aGlobal, HTMLElementType& aElement, ErrorResult& aRv) +GetSurfaceFromElement(nsIGlobalObject* aGlobal, HTMLElementType& aElement, + bool* aWriteOnly, ErrorResult& aRv) { nsLayoutUtils::SurfaceFromElementResult res = nsLayoutUtils::SurfaceFromElement(&aElement, nsLayoutUtils::SFE_WANT_FIRST_FRAME); - // check origin-clean - if (!CheckSecurityForHTMLElements(res)) { - aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); - return nullptr; - } - RefPtr<SourceSurface> surface = res.GetSourceSurface(); if (NS_WARN_IF(!surface)) { - aRv.Throw(NS_ERROR_NOT_AVAILABLE); + aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); return nullptr; } + + // Check origin-clean and pass back + *aWriteOnly = !CheckSecurityForHTMLElements(res); return surface.forget(); } /* - * The specification doesn't allow to create an ImegeBitmap from a vector image. + * The specification doesn't allow to create an ImageBitmap from a vector image. * This function is used to check if the given HTMLImageElement contains a * raster image. */ @@ -398,7 +396,7 @@ HasRasterImage(HTMLImageElement& aImageEl) } ImageBitmap::ImageBitmap(nsIGlobalObject* aGlobal, layers::Image* aData, - bool aIsPremultipliedAlpha /* = true */) + bool aWriteOnly, bool aIsPremultipliedAlpha /* = true */) : mParent(aGlobal) , mData(aData) , mSurface(nullptr) @@ -406,6 +404,7 @@ ImageBitmap::ImageBitmap(nsIGlobalObject* aGlobal, layers::Image* aData, , mPictureRect(0, 0, aData->GetSize().width, aData->GetSize().height) , mIsPremultipliedAlpha(aIsPremultipliedAlpha) , mIsCroppingAreaOutSideOfSourceImage(false) + , mWriteOnly(aWriteOnly) { MOZ_ASSERT(aData, "aData is null in ImageBitmap constructor."); } @@ -698,6 +697,7 @@ ImageBitmap::ToCloneData() const RefPtr<SourceSurface> surface = mData->GetAsSourceSurface(); result->mSurface = surface->GetDataSurface(); MOZ_ASSERT(result->mSurface); + result->mWriteOnly = mWriteOnly; return Move(result); } @@ -708,7 +708,7 @@ ImageBitmap::CreateFromCloneData(nsIGlobalObject* aGlobal, { RefPtr<layers::Image> data = CreateImageFromSurface(aData->mSurface); - RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, + RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, aData->mWriteOnly, aData->mIsPremultipliedAlpha); ret->mIsCroppingAreaOutSideOfSourceImage = @@ -724,11 +724,8 @@ ImageBitmap::CreateFromOffscreenCanvas(nsIGlobalObject* aGlobal, OffscreenCanvas& aOffscreenCanvas, ErrorResult& aRv) { - // Check origin-clean. - if (aOffscreenCanvas.IsWriteOnly()) { - aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); - return nullptr; - } + // Check origin-clean + bool writeOnly = aOffscreenCanvas.IsWriteOnly(); nsLayoutUtils::SurfaceFromElementResult res = nsLayoutUtils::SurfaceFromOffscreenCanvas(&aOffscreenCanvas, @@ -744,7 +741,7 @@ ImageBitmap::CreateFromOffscreenCanvas(nsIGlobalObject* aGlobal, RefPtr<layers::Image> data = CreateImageFromSurface(surface); - RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data); + RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, writeOnly); return ret.forget(); } @@ -757,16 +754,19 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, HTMLImageElement& aImageEl aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); return nullptr; } - + // Check if the image element is a bitmap (e.g. it's a vector graphic) or not. if (!HasRasterImage(aImageEl)) { aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); return nullptr; } + bool writeOnly = true; + // Get the SourceSurface out from the image element and then do security // checking. - RefPtr<SourceSurface> surface = GetSurfaceFromElement(aGlobal, aImageEl, aRv); + RefPtr<SourceSurface> surface = GetSurfaceFromElement(aGlobal, aImageEl, + &writeOnly, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; @@ -780,7 +780,7 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, HTMLImageElement& aImageEl return nullptr; } - RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data); + RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, writeOnly); // Set the picture rectangle. if (ret && aCropRect.isSome()) { @@ -812,13 +812,13 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, HTMLVideoElement& aVideoEl return nullptr; } + bool writeOnly = true; + // Check security. nsCOMPtr<nsIPrincipal> principal = aVideoEl.GetCurrentVideoPrincipal(); bool CORSUsed = aVideoEl.GetCORSMode() != CORS_NONE; - if (!CheckSecurityForHTMLElements(false, CORSUsed, principal)) { - aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); - return nullptr; - } + + writeOnly = !CheckSecurityForHTMLElements(false, CORSUsed, principal); // Create ImageBitmap. ImageContainer *container = aVideoEl.GetImageContainer(); @@ -834,7 +834,7 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, HTMLVideoElement& aVideoEl aRv.Throw(NS_ERROR_NOT_AVAILABLE); return nullptr; } - RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data); + RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, writeOnly); // Set the picture rectangle. if (ret && aCropRect.isSome()) { @@ -856,12 +856,18 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, HTMLCanvasElement& aCanvas return nullptr; } - RefPtr<SourceSurface> surface = GetSurfaceFromElement(aGlobal, aCanvasEl, aRv); + bool writeOnly = true; + + RefPtr<SourceSurface> surface = GetSurfaceFromElement(aGlobal, aCanvasEl, &writeOnly, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } + if (!writeOnly) { + writeOnly = aCanvasEl.IsWriteOnly(); + } + // Crop the source surface if needed. RefPtr<SourceSurface> croppedSurface; IntRect cropRect = aCropRect.valueOr(IntRect()); @@ -874,8 +880,7 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, HTMLCanvasElement& aCanvas aCropRect.isSome()) { // The _surface_ must be a DataSourceSurface. MOZ_ASSERT(surface->GetType() == SurfaceType::DATA, - "The snapshot SourceSurface from WebGL rendering contest is not \ - DataSourceSurface."); + "The snapshot SourceSurface from WebGL rendering contest is not DataSourceSurface."); RefPtr<DataSourceSurface> dataSurface = surface->GetDataSurface(); croppedSurface = CropAndCopyDataSourceSurface(dataSurface, cropRect); cropRect.MoveTo(0, 0); @@ -897,7 +902,7 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, HTMLCanvasElement& aCanvas return nullptr; } - RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data); + RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, writeOnly); // Set the picture rectangle. if (ret && aCropRect.isSome()) { @@ -958,9 +963,12 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, ImageData& aImageData, return nullptr; } - // Create an ImageBimtap. + // Create an ImageBitmap. // ImageData's underlying data is not alpha-premultiplied. - RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, false); + RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, + data, + false /* write-only */, + false /* alpha-premult */); // The cropping information has been handled in the CreateImageFromRawData() // function. @@ -975,11 +983,8 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, ImageData& aImageData, ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, CanvasRenderingContext2D& aCanvasCtx, const Maybe<IntRect>& aCropRect, ErrorResult& aRv) { - // Check origin-clean. - if (aCanvasCtx.GetCanvas()->IsWriteOnly()) { - aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); - return nullptr; - } + // Check origin-clean + bool writeOnly = aCanvasCtx.GetCanvas()->IsWriteOnly() || aCanvasCtx.IsWriteOnly(); RefPtr<SourceSurface> surface = aCanvasCtx.GetSurfaceSnapshot(); @@ -1001,7 +1006,7 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, CanvasRenderingContext2D& return nullptr; } - RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data); + RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, writeOnly); // Set the picture rectangle. if (ret && aCropRect.isSome()) { @@ -1024,7 +1029,10 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, ImageBitmap& aImageBitmap, } RefPtr<layers::Image> data = aImageBitmap.mData; - RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, aImageBitmap.mIsPremultipliedAlpha); + RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, + data, + aImageBitmap.mWriteOnly, + aImageBitmap.mIsPremultipliedAlpha); // Set the picture rectangle. if (ret && aCropRect.isSome()) { @@ -1295,7 +1303,7 @@ private: } // Create ImageBitmap object. - RefPtr<ImageBitmap> imageBitmap = new ImageBitmap(mGlobalObject, data); + RefPtr<ImageBitmap> imageBitmap = new ImageBitmap(mGlobalObject, data, false /* write-only */); // Set mIsCroppingAreaOutSideOfSourceImage. imageBitmap->SetIsCroppingAreaOutSideOfSourceImage(sourceSize, originalCropRect); @@ -1391,7 +1399,7 @@ private: } // Create ImageBitmap object. - RefPtr<ImageBitmap> imageBitmap = new ImageBitmap(mGlobalObject, data); + RefPtr<ImageBitmap> imageBitmap = new ImageBitmap(mGlobalObject, data, false /* write-only */); // Set mIsCroppingAreaOutSideOfSourceImage. imageBitmap->SetIsCroppingAreaOutSideOfSourceImage(sourceSize, originalCropRect); @@ -1486,14 +1494,19 @@ ImageBitmap::ReadStructuredClone(JSContext* aCx, uint32_t picRectHeight_; uint32_t isPremultipliedAlpha_; uint32_t isCroppingAreaOutSideOfSourceImage_; + uint32_t writeOnly; + uint32_t dummy; if (!JS_ReadUint32Pair(aReader, &picRectX_, &picRectY_) || !JS_ReadUint32Pair(aReader, &picRectWidth_, &picRectHeight_) || !JS_ReadUint32Pair(aReader, &isPremultipliedAlpha_, - &isCroppingAreaOutSideOfSourceImage_)) { + &isCroppingAreaOutSideOfSourceImage_) || + !JS_ReadUint32Pair(aReader, &writeOnly, &dummy)) { return nullptr; } + MOZ_ASSERT(dummy == 0); + int32_t picRectX = BitwiseCast<int32_t>(picRectX_); int32_t picRectY = BitwiseCast<int32_t>(picRectY_); int32_t picRectWidth = BitwiseCast<int32_t>(picRectWidth_); @@ -1512,7 +1525,7 @@ ImageBitmap::ReadStructuredClone(JSContext* aCx, { RefPtr<layers::Image> img = CreateImageFromSurface(aClonedSurfaces[aIndex]); RefPtr<ImageBitmap> imageBitmap = - new ImageBitmap(aParent, img, isPremultipliedAlpha_); + new ImageBitmap(aParent, img, !!writeOnly, isPremultipliedAlpha_); imageBitmap->mIsCroppingAreaOutSideOfSourceImage = isCroppingAreaOutSideOfSourceImage_; @@ -1547,6 +1560,7 @@ ImageBitmap::WriteStructuredClone(JSStructuredCloneWriter* aWriter, const uint32_t picRectHeight = BitwiseCast<uint32_t>(aImageBitmap->mPictureRect.height); const uint32_t isPremultipliedAlpha = aImageBitmap->mIsPremultipliedAlpha ? 1 : 0; const uint32_t isCroppingAreaOutSideOfSourceImage = aImageBitmap->mIsCroppingAreaOutSideOfSourceImage ? 1 : 0; + const uint32_t isWriteOnly = aImageBitmap->mWriteOnly ? 1 : 0; // Indexing the cloned surfaces and send the index to the receiver. uint32_t index = aClonedSurfaces.Length(); @@ -1555,7 +1569,8 @@ ImageBitmap::WriteStructuredClone(JSStructuredCloneWriter* aWriter, NS_WARN_IF(!JS_WriteUint32Pair(aWriter, picRectX, picRectY)) || NS_WARN_IF(!JS_WriteUint32Pair(aWriter, picRectWidth, picRectHeight)) || NS_WARN_IF(!JS_WriteUint32Pair(aWriter, isPremultipliedAlpha, - isCroppingAreaOutSideOfSourceImage))) { + isCroppingAreaOutSideOfSourceImage)) || + NS_WARN_IF(!JS_WriteUint32Pair(aWriter, isWriteOnly, 0))) { return false; } diff --git a/dom/canvas/ImageBitmap.h b/dom/canvas/ImageBitmap.h index 2119c6bda..25084b6ac 100644 --- a/dom/canvas/ImageBitmap.h +++ b/dom/canvas/ImageBitmap.h @@ -65,6 +65,7 @@ struct ImageBitmapCloneData final gfx::IntRect mPictureRect; bool mIsPremultipliedAlpha; bool mIsCroppingAreaOutSideOfSourceImage; + bool mWriteOnly; }; /* @@ -161,6 +162,10 @@ public: template<typename T> friend class MapDataIntoBufferSource; + bool IsWriteOnly() const { + return mWriteOnly; + } + // Mozilla Extensions ImageBitmapFormat FindOptimalFormat(const Optional<Sequence<ImageBitmapFormat>>& aPossibleFormats, @@ -197,6 +202,7 @@ protected: * CreateInternal(from ImageData) method. */ ImageBitmap(nsIGlobalObject* aGlobal, layers::Image* aData, + bool aWriteOnly, bool aIsPremultipliedAlpha = true); virtual ~ImageBitmap(); @@ -280,6 +286,12 @@ protected: */ bool mIsCroppingAreaOutSideOfSourceImage; + /* + * Write-Only flag is set to true if this image has been generated from a + * cross-origin source. This is the opposite of what is called 'origin-clean' + * in the spec. + */ + bool mWriteOnly; }; } // namespace dom diff --git a/dom/canvas/ImageBitmapRenderingContext.cpp b/dom/canvas/ImageBitmapRenderingContext.cpp index 8f5074554..ad313906a 100644 --- a/dom/canvas/ImageBitmapRenderingContext.cpp +++ b/dom/canvas/ImageBitmapRenderingContext.cpp @@ -63,6 +63,11 @@ ImageBitmapRenderingContext::TransferFromImageBitmap(ImageBitmap& aImageBitmap) if (!mImage) { return; } + + // Check if ImageBitmap is tainted, and if so flag the canvas tainted too. + if (aImageBitmap.IsWriteOnly() && mCanvasElement) { + mCanvasElement->SetWriteOnly(); + } Redraw(gfxRect(0, 0, mWidth, mHeight)); } diff --git a/dom/canvas/ImageData.cpp b/dom/canvas/ImageData.cpp index b201fa279..d24fbca95 100644 --- a/dom/canvas/ImageData.cpp +++ b/dom/canvas/ImageData.cpp @@ -29,7 +29,6 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ImageData) NS_IMPL_CYCLE_COLLECTION_TRACE_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ImageData) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ImageData) diff --git a/dom/canvas/WebGLContext.h b/dom/canvas/WebGLContext.h index 3ec307b00..8a20237ff 100644 --- a/dom/canvas/WebGLContext.h +++ b/dom/canvas/WebGLContext.h @@ -275,8 +275,9 @@ struct TexImageSourceAdapter final : public TexImageSource mPboOffset = pboOffset; } - TexImageSourceAdapter(const dom::ImageBitmap* imageBitmap, ErrorResult*) { + TexImageSourceAdapter(const dom::ImageBitmap* imageBitmap, ErrorResult* out_error) { mImageBitmap = imageBitmap; + mOut_error = out_error; } TexImageSourceAdapter(const dom::ImageData* imageData, ErrorResult*) { diff --git a/dom/canvas/WebGLTextureUpload.cpp b/dom/canvas/WebGLTextureUpload.cpp index 612d5889d..3839b5d5e 100644 --- a/dom/canvas/WebGLTextureUpload.cpp +++ b/dom/canvas/WebGLTextureUpload.cpp @@ -12,6 +12,7 @@ #include "GLBlitHelper.h" #include "GLContext.h" #include "mozilla/gfx/2D.h" +#include "mozilla/dom/HTMLCanvasElement.h" #include "mozilla/dom/HTMLVideoElement.h" #include "mozilla/dom/ImageBitmap.h" #include "mozilla/dom/ImageData.h" @@ -214,9 +215,18 @@ FromPboOffset(WebGLContext* webgl, const char* funcName, TexImageTarget target, static UniquePtr<webgl::TexUnpackBlob> FromImageBitmap(WebGLContext* webgl, const char* funcName, TexImageTarget target, uint32_t width, uint32_t height, uint32_t depth, - const dom::ImageBitmap& imageBitmap) + const dom::ImageBitmap& imageBitmap, ErrorResult* aRv) { + if (imageBitmap.IsWriteOnly()) { + aRv->Throw(NS_ERROR_DOM_SECURITY_ERR); + return nullptr; + } + UniquePtr<dom::ImageBitmapCloneData> cloneData = Move(imageBitmap.ToCloneData()); + if (!cloneData) { + return nullptr; + } + const RefPtr<gfx::DataSourceSurface> surf = cloneData->mSurface; //// @@ -293,6 +303,14 @@ WebGLContext::FromDomElem(const char* funcName, TexImageTarget target, uint32_t uint32_t height, uint32_t depth, const dom::Element& elem, ErrorResult* const out_error) { + if (elem.IsHTMLElement(nsGkAtoms::canvas)) {
+ const dom::HTMLCanvasElement* canvas = static_cast<const dom::HTMLCanvasElement*>(&elem);
+ if (canvas->IsWriteOnly()) {
+ out_error->Throw(NS_ERROR_DOM_SECURITY_ERR);
+ return nullptr;
+ }
+ }
+ uint32_t flags = nsLayoutUtils::SFE_WANT_IMAGE_SURFACE | nsLayoutUtils::SFE_USE_ELEMENT_SIZE_IF_VECTOR; @@ -412,7 +430,7 @@ WebGLContext::From(const char* funcName, TexImageTarget target, GLsizei rawWidth if (src.mImageBitmap) { return FromImageBitmap(this, funcName, target, width, height, depth, - *(src.mImageBitmap)); + *(src.mImageBitmap), src.mOut_error); } if (src.mImageData) { diff --git a/dom/canvas/test/test_imagebitmap.html b/dom/canvas/test/test_imagebitmap.html index b3d3c08ad..3b74970ac 100644 --- a/dom/canvas/test/test_imagebitmap.html +++ b/dom/canvas/test/test_imagebitmap.html @@ -270,13 +270,22 @@ function testSecurityErrors() { } function checkPromiseFailedWithSecurityError(p) { - return p.then( function(reason) { ok(false, "Did not get SecurityError with unclean source. ImageBitmap was created successfully."); }, - function(reason) { if (reason == "SecurityError: The operation is insecure.") { - ok(true, reason); - } - else { - ok(false, "Did not get SecurityError with unclean source. Error Message: " + reason); - }}); + return p.then(imageBitmap => { + ok(!!imageBitmap, "ImageBitmaps are always created"); + const context = document.createElement("canvas").getContext("2d"); + context.drawImage(imageBitmap, 0, 0); + try { + context.getImageData(0, 0, 1, 1); + ok(false, "Did not get SecurityError with unclean source. ImageBitmap was created successfully."); + } catch (ex) { + if (ex == "SecurityError: The operation is insecure.") { + ok(true, ex); + } + else { + ok(false, "Did not get SecurityError with unclean source. Error Message: " + ex); + } + } + }); } return Promise.all([ diff --git a/dom/console/Console.cpp b/dom/console/Console.cpp index ff5a92167..b174172e0 100755 --- a/dom/console/Console.cpp +++ b/dom/console/Console.cpp @@ -797,7 +797,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Console) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsoleEventNotifier) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Console) diff --git a/dom/events/DOMEventTargetHelper.cpp b/dom/events/DOMEventTargetHelper.cpp index f8a5227d6..dd9a01d8d 100644 --- a/dom/events/DOMEventTargetHelper.cpp +++ b/dom/events/DOMEventTargetHelper.cpp @@ -43,7 +43,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(DOMEventTargetHelper) NS_IMPL_CYCLE_COLLECTION_DESCRIBE(DOMEventTargetHelper, tmp->mRefCnt.get()) } - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mListenerManager) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END diff --git a/dom/events/DataTransfer.cpp b/dom/events/DataTransfer.cpp index 45c72e662..40a0f42e6 100644 --- a/dom/events/DataTransfer.cpp +++ b/dom/events/DataTransfer.cpp @@ -57,7 +57,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DataTransfer) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mItems) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDragTarget) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDragImage) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(DataTransfer) diff --git a/dom/events/Event.cpp b/dom/events/Event.cpp index f33bfa5a8..280e40ad5 100755 --- a/dom/events/Event.cpp +++ b/dom/events/Event.cpp @@ -231,7 +231,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Event) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPresContext) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExplicitOriginalTarget) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END diff --git a/dom/events/JSEventHandler.cpp b/dom/events/JSEventHandler.cpp index 4b1b33313..b9e7c4d84 100644 --- a/dom/events/JSEventHandler.cpp +++ b/dom/events/JSEventHandler.cpp @@ -63,7 +63,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(JSEventHandler) NS_IMPL_CYCLE_COLLECTION_DESCRIBE(JSEventHandler, tmp->mRefCnt.get()) } NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mTypedHandler.Ptr()) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(JSEventHandler) diff --git a/dom/fetch/FetchDriver.cpp b/dom/fetch/FetchDriver.cpp index 1791399b7..6294b0dc5 100644 --- a/dom/fetch/FetchDriver.cpp +++ b/dom/fetch/FetchDriver.cpp @@ -903,11 +903,7 @@ FetchDriver::SetRequestHeaders(nsIHttpChannel* aChannel) const AutoTArray<InternalHeaders::Entry, 5> headers; mRequest->Headers()->GetEntries(headers); - bool hasAccept = false; for (uint32_t i = 0; i < headers.Length(); ++i) { - if (!hasAccept && headers[i].mName.EqualsLiteral("accept")) { - hasAccept = true; - } if (headers[i].mValue.IsEmpty()) { aChannel->SetEmptyRequestHeader(headers[i].mName); } else { @@ -915,12 +911,6 @@ FetchDriver::SetRequestHeaders(nsIHttpChannel* aChannel) const } } - if (!hasAccept) { - aChannel->SetRequestHeader(NS_LITERAL_CSTRING("accept"), - NS_LITERAL_CSTRING("*/*"), - false /* merge */); - } - if (mRequest->ForceOriginHeader()) { nsAutoString origin; if (NS_SUCCEEDED(nsContentUtils::GetUTFOrigin(mPrincipal, origin))) { diff --git a/dom/fetch/Headers.cpp b/dom/fetch/Headers.cpp index 1e1a46c62..ca5aa57a6 100644 --- a/dom/fetch/Headers.cpp +++ b/dom/fetch/Headers.cpp @@ -25,7 +25,7 @@ NS_INTERFACE_MAP_END // static already_AddRefed<Headers> Headers::Constructor(const GlobalObject& aGlobal, - const Optional<HeadersOrByteStringSequenceSequenceOrByteStringMozMap>& aInit, + const Optional<HeadersOrByteStringSequenceSequenceOrByteStringByteStringRecord>& aInit, ErrorResult& aRv) { RefPtr<InternalHeaders> ih = new InternalHeaders(); @@ -39,8 +39,8 @@ Headers::Constructor(const GlobalObject& aGlobal, ih->Fill(*aInit.Value().GetAsHeaders().mInternalHeaders, aRv); } else if (aInit.Value().IsByteStringSequenceSequence()) { ih->Fill(aInit.Value().GetAsByteStringSequenceSequence(), aRv); - } else if (aInit.Value().IsByteStringMozMap()) { - ih->Fill(aInit.Value().GetAsByteStringMozMap(), aRv); + } else if (aInit.Value().IsByteStringByteStringRecord()) { + ih->Fill(aInit.Value().GetAsByteStringByteStringRecord(), aRv); } if (aRv.Failed()) { @@ -53,7 +53,7 @@ Headers::Constructor(const GlobalObject& aGlobal, // static already_AddRefed<Headers> Headers::Constructor(const GlobalObject& aGlobal, - const OwningHeadersOrByteStringSequenceSequenceOrByteStringMozMap& aInit, + const OwningHeadersOrByteStringSequenceSequenceOrByteStringByteStringRecord& aInit, ErrorResult& aRv) { nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports()); @@ -62,7 +62,7 @@ Headers::Constructor(const GlobalObject& aGlobal, /* static */ already_AddRefed<Headers> Headers::Create(nsIGlobalObject* aGlobal, - const OwningHeadersOrByteStringSequenceSequenceOrByteStringMozMap& aInit, + const OwningHeadersOrByteStringSequenceSequenceOrByteStringByteStringRecord& aInit, ErrorResult& aRv) { RefPtr<InternalHeaders> ih = new InternalHeaders(); @@ -72,8 +72,8 @@ Headers::Create(nsIGlobalObject* aGlobal, ih->Fill(*(aInit.GetAsHeaders().get()->mInternalHeaders), aRv); } else if (aInit.IsByteStringSequenceSequence()) { ih->Fill(aInit.GetAsByteStringSequenceSequence(), aRv); - } else if (aInit.IsByteStringMozMap()) { - ih->Fill(aInit.GetAsByteStringMozMap(), aRv); + } else if (aInit.IsByteStringByteStringRecord()) { + ih->Fill(aInit.GetAsByteStringByteStringRecord(), aRv); } if (NS_WARN_IF(aRv.Failed())) { diff --git a/dom/fetch/Headers.h b/dom/fetch/Headers.h index b603dc836..1dd92f779 100644 --- a/dom/fetch/Headers.h +++ b/dom/fetch/Headers.h @@ -20,9 +20,9 @@ class ErrorResult; namespace dom { -template<typename T> class MozMap; -class HeadersOrByteStringSequenceSequenceOrByteStringMozMap; -class OwningHeadersOrByteStringSequenceSequenceOrByteStringMozMap; +template<typename K, typename V> class Record; +class HeadersOrByteStringSequenceSequenceOrByteStringByteStringRecord; +class OwningHeadersOrByteStringSequenceSequenceOrByteStringByteStringRecord; /** * This Headers class is only used to represent the content facing Headers @@ -57,17 +57,17 @@ public: static already_AddRefed<Headers> Constructor(const GlobalObject& aGlobal, - const Optional<HeadersOrByteStringSequenceSequenceOrByteStringMozMap>& aInit, + const Optional<HeadersOrByteStringSequenceSequenceOrByteStringByteStringRecord>& aInit, ErrorResult& aRv); static already_AddRefed<Headers> Constructor(const GlobalObject& aGlobal, - const OwningHeadersOrByteStringSequenceSequenceOrByteStringMozMap& aInit, + const OwningHeadersOrByteStringSequenceSequenceOrByteStringByteStringRecord& aInit, ErrorResult& aRv); static already_AddRefed<Headers> Create(nsIGlobalObject* aGlobalObject, - const OwningHeadersOrByteStringSequenceSequenceOrByteStringMozMap& aInit, + const OwningHeadersOrByteStringSequenceSequenceOrByteStringByteStringRecord& aInit, ErrorResult& aRv); void Append(const nsACString& aName, const nsACString& aValue, diff --git a/dom/fetch/InternalHeaders.cpp b/dom/fetch/InternalHeaders.cpp index 11585615e..f66221d42 100644 --- a/dom/fetch/InternalHeaders.cpp +++ b/dom/fetch/InternalHeaders.cpp @@ -314,12 +314,13 @@ InternalHeaders::Fill(const Sequence<Sequence<nsCString>>& aInit, ErrorResult& a } void -InternalHeaders::Fill(const MozMap<nsCString>& aInit, ErrorResult& aRv) +InternalHeaders::Fill(const Record<nsCString, nsCString>& aInit, ErrorResult& aRv) { - nsTArray<nsString> keys; - aInit.GetKeys(keys); - for (uint32_t i = 0; i < keys.Length() && !aRv.Failed(); ++i) { - Append(NS_ConvertUTF16toUTF8(keys[i]), aInit.Get(keys[i]), aRv); + for (auto& entry : aInit.Entries()) { + Append(entry.mKey, entry.mValue, aRv); + if (aRv.Failed()) { + return; + } } } diff --git a/dom/fetch/InternalHeaders.h b/dom/fetch/InternalHeaders.h index 9a6d6dae7..98046f0ef 100644 --- a/dom/fetch/InternalHeaders.h +++ b/dom/fetch/InternalHeaders.h @@ -20,7 +20,7 @@ class ErrorResult; namespace dom { -template<typename T> class MozMap; +template<typename K, typename V> class Record; class HeadersEntry; class InternalHeaders final @@ -113,7 +113,7 @@ public: void Fill(const InternalHeaders& aInit, ErrorResult& aRv); void Fill(const Sequence<Sequence<nsCString>>& aInit, ErrorResult& aRv); - void Fill(const MozMap<nsCString>& aInit, ErrorResult& aRv); + void Fill(const Record<nsCString, nsCString>& aInit, ErrorResult& aRv); bool HasOnlySimpleHeaders() const; diff --git a/dom/filesystem/Directory.cpp b/dom/filesystem/Directory.cpp index 59c78fb2c..5e8a4a745 100644 --- a/dom/filesystem/Directory.cpp +++ b/dom/filesystem/Directory.cpp @@ -36,7 +36,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Directory) tmp->mFileSystem->Traverse(cb); } NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(Directory) diff --git a/dom/gamepad/GamepadServiceTest.cpp b/dom/gamepad/GamepadServiceTest.cpp index a6fde58f0..89429b52a 100644 --- a/dom/gamepad/GamepadServiceTest.cpp +++ b/dom/gamepad/GamepadServiceTest.cpp @@ -35,7 +35,6 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(GamepadServiceTest) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(GamepadServiceTest, DOMEventTargetHelper) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END diff --git a/dom/html/HTMLCanvasElement.cpp b/dom/html/HTMLCanvasElement.cpp index 527135a80..a01795d9e 100644 --- a/dom/html/HTMLCanvasElement.cpp +++ b/dom/html/HTMLCanvasElement.cpp @@ -1000,7 +1000,7 @@ HTMLCanvasElement::GetSize() } bool -HTMLCanvasElement::IsWriteOnly() +HTMLCanvasElement::IsWriteOnly() const { return mWriteOnly; } diff --git a/dom/html/HTMLCanvasElement.h b/dom/html/HTMLCanvasElement.h index 746fab198..e77db6ff1 100644 --- a/dom/html/HTMLCanvasElement.h +++ b/dom/html/HTMLCanvasElement.h @@ -224,9 +224,9 @@ public: nsIntSize GetSize(); /** - * Determine whether the canvas is write-only. + * Determine whether the canvas is write-only (tainted). */ - bool IsWriteOnly(); + bool IsWriteOnly() const; /** * Force the canvas to be write-only. diff --git a/dom/html/HTMLFormControlsCollection.cpp b/dom/html/HTMLFormControlsCollection.cpp index d91a6b5de..77fafae99 100644 --- a/dom/html/HTMLFormControlsCollection.cpp +++ b/dom/html/HTMLFormControlsCollection.cpp @@ -134,7 +134,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(HTMLFormControlsCollection) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(HTMLFormControlsCollection) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNameLookupTable) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(HTMLFormControlsCollection) NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER diff --git a/dom/html/HTMLTableElement.cpp b/dom/html/HTMLTableElement.cpp index ec1b7cecb..c5b7696cf 100644 --- a/dom/html/HTMLTableElement.cpp +++ b/dom/html/HTMLTableElement.cpp @@ -421,11 +421,10 @@ HTMLTableElement::CreateTHead() void HTMLTableElement::DeleteTHead() { - HTMLTableSectionElement* tHead = GetTHead(); + RefPtr<HTMLTableSectionElement> tHead = GetTHead(); if (tHead) { - mozilla::ErrorResult rv; + mozilla::IgnoredErrorResult rv; nsINode::RemoveChild(*tHead, rv); - MOZ_ASSERT(!rv.Failed()); } } @@ -452,11 +451,10 @@ HTMLTableElement::CreateTFoot() void HTMLTableElement::DeleteTFoot() { - HTMLTableSectionElement* tFoot = GetTFoot(); + RefPtr<HTMLTableSectionElement> tFoot = GetTFoot(); if (tFoot) { - mozilla::ErrorResult rv; + mozilla::IgnoredErrorResult rv; nsINode::RemoveChild(*tFoot, rv); - MOZ_ASSERT(!rv.Failed()); } } @@ -483,11 +481,10 @@ HTMLTableElement::CreateCaption() void HTMLTableElement::DeleteCaption() { - HTMLTableCaptionElement* caption = GetCaption(); + RefPtr<HTMLTableCaptionElement> caption = GetCaption(); if (caption) { - mozilla::ErrorResult rv; + mozilla::IgnoredErrorResult rv; nsINode::RemoveChild(*caption, rv); - MOZ_ASSERT(!rv.Failed()); } } diff --git a/dom/html/HTMLTableSectionElement.cpp b/dom/html/HTMLTableSectionElement.cpp index c7b0665dd..e99597636 100644 --- a/dom/html/HTMLTableSectionElement.cpp +++ b/dom/html/HTMLTableSectionElement.cpp @@ -122,7 +122,7 @@ HTMLTableSectionElement::DeleteRow(int32_t aValue, ErrorResult& aError) refIndex = (uint32_t)aValue; } - nsINode* row = rows->Item(refIndex); + nsCOMPtr<nsINode> row = rows->Item(refIndex); if (!row) { aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); return; diff --git a/dom/html/nsDOMStringMap.cpp b/dom/html/nsDOMStringMap.cpp index 42725bc6f..6d2bc424d 100644 --- a/dom/html/nsDOMStringMap.cpp +++ b/dom/html/nsDOMStringMap.cpp @@ -19,7 +19,6 @@ using namespace mozilla::dom; NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMStringMap) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMStringMap) -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mElement) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END diff --git a/dom/html/nsTextEditorState.cpp b/dom/html/nsTextEditorState.cpp index 0b4cb1920..25be6016c 100644 --- a/dom/html/nsTextEditorState.cpp +++ b/dom/html/nsTextEditorState.cpp @@ -2255,7 +2255,11 @@ nsTextEditorState::UpdatePlaceholderText(bool aNotify) nsCOMPtr<nsIContent> content = do_QueryInterface(mTextCtrlElement); content->GetAttr(kNameSpaceID_None, nsGkAtoms::placeholder, placeholderValue); - nsContentUtils::RemoveNewlines(placeholderValue); + if (mTextCtrlElement->IsTextArea()) { // <textarea>s preserve newlines... + nsContentUtils::PlatformToDOMLineBreaks(placeholderValue); + } else { // ...<input>s don't + nsContentUtils::RemoveNewlines(placeholderValue); + } NS_ASSERTION(mPlaceholderDiv->GetFirstChild(), "placeholder div has no child"); mPlaceholderDiv->GetFirstChild()->SetText(placeholderValue, aNotify); } diff --git a/dom/indexedDB/ActorsChild.cpp b/dom/indexedDB/ActorsChild.cpp index 3e8f97348..c4fcceb90 100644 --- a/dom/indexedDB/ActorsChild.cpp +++ b/dom/indexedDB/ActorsChild.cpp @@ -3456,6 +3456,8 @@ BackgroundCursorChild::RecvResponse(const CursorResponse& aResponse) RefPtr<IDBCursor> cursor; mStrongCursor.swap(cursor); + + RefPtr<IDBTransaction> transaction = mTransaction; switch (aResponse.type()) { case CursorResponse::Tnsresult: @@ -3486,7 +3488,7 @@ BackgroundCursorChild::RecvResponse(const CursorResponse& aResponse) MOZ_CRASH("Should never get here!"); } - mTransaction->OnRequestFinished(/* aActorDestroyedNormally */ true); + transaction->OnRequestFinished(/* aActorDestroyedNormally */ true); return true; } diff --git a/dom/indexedDB/IDBCursor.cpp b/dom/indexedDB/IDBCursor.cpp index 7ae35e981..af88742f0 100644 --- a/dom/indexedDB/IDBCursor.cpp +++ b/dom/indexedDB/IDBCursor.cpp @@ -948,7 +948,6 @@ NS_INTERFACE_MAP_END NS_IMPL_CYCLE_COLLECTION_CLASS(IDBCursor) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBCursor) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRequest) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourceObjectStore) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourceIndex) diff --git a/dom/indexedDB/IDBFactory.cpp b/dom/indexedDB/IDBFactory.cpp index 825d2ac36..c1ef6353d 100644 --- a/dom/indexedDB/IDBFactory.cpp +++ b/dom/indexedDB/IDBFactory.cpp @@ -865,7 +865,6 @@ NS_INTERFACE_MAP_END NS_IMPL_CYCLE_COLLECTION_CLASS(IDBFactory) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBFactory) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END diff --git a/dom/indexedDB/IDBIndex.cpp b/dom/indexedDB/IDBIndex.cpp index 657e744c9..af50926e6 100644 --- a/dom/indexedDB/IDBIndex.cpp +++ b/dom/indexedDB/IDBIndex.cpp @@ -652,7 +652,6 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBIndex) NS_IMPL_CYCLE_COLLECTION_TRACE_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBIndex) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mObjectStore) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END diff --git a/dom/indexedDB/IDBKeyRange.cpp b/dom/indexedDB/IDBKeyRange.cpp index 2de48a70c..e61c80617 100644 --- a/dom/indexedDB/IDBKeyRange.cpp +++ b/dom/indexedDB/IDBKeyRange.cpp @@ -239,7 +239,6 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(IDBKeyRange) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBKeyRange) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBKeyRange) diff --git a/dom/indexedDB/IDBObjectStore.cpp b/dom/indexedDB/IDBObjectStore.cpp index 8a0b292ad..756792741 100644 --- a/dom/indexedDB/IDBObjectStore.cpp +++ b/dom/indexedDB/IDBObjectStore.cpp @@ -1758,7 +1758,6 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBObjectStore) NS_IMPL_CYCLE_COLLECTION_TRACE_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBObjectStore) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTransaction) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIndexes) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDeletedIndexes) diff --git a/dom/indexedDB/IDBRequest.cpp b/dom/indexedDB/IDBRequest.cpp index 919d3adc7..e0e318059 100644 --- a/dom/indexedDB/IDBRequest.cpp +++ b/dom/indexedDB/IDBRequest.cpp @@ -417,8 +417,6 @@ IDBRequest::GetError(ErrorResult& aRv) NS_IMPL_CYCLE_COLLECTION_CLASS(IDBRequest) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBRequest, IDBWrapperCache) - // Don't need NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS because - // DOMEventTargetHelper does it for us. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourceAsObjectStore) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourceAsIndex) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourceAsCursor) diff --git a/dom/indexedDB/IDBWrapperCache.cpp b/dom/indexedDB/IDBWrapperCache.cpp index df62514c8..ccc2bb43e 100644 --- a/dom/indexedDB/IDBWrapperCache.cpp +++ b/dom/indexedDB/IDBWrapperCache.cpp @@ -18,8 +18,6 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(IDBWrapperCache) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBWrapperCache, DOMEventTargetHelper) - // Don't need NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS because - // DOMEventTargetHelper does it for us. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBWrapperCache, diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index f29d17e7f..4c8f15cc0 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -152,13 +152,13 @@ public: RecvInitRendering( Endpoint<PCompositorBridgeChild>&& aCompositor, Endpoint<PImageBridgeChild>&& aImageBridge, - Endpoint<PVideoDecoderManagerChild>&& aVideoManager); + Endpoint<PVideoDecoderManagerChild>&& aVideoManager) override; bool RecvReinitRendering( Endpoint<PCompositorBridgeChild>&& aCompositor, Endpoint<PImageBridgeChild>&& aImageBridge, - Endpoint<PVideoDecoderManagerChild>&& aVideoManager); + Endpoint<PVideoDecoderManagerChild>&& aVideoManager) override; PProcessHangMonitorChild* AllocPProcessHangMonitorChild(Transport* aTransport, diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 3fe94001e..e1355adee 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -176,7 +176,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(TabChildBase) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTabChildGlobal) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWebBrowserChrome) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END diff --git a/dom/locales/en-US/chrome/security/security.properties b/dom/locales/en-US/chrome/security/security.properties index 8efdb0a6d..2be56fb9d 100644 --- a/dom/locales/en-US/chrome/security/security.properties +++ b/dom/locales/en-US/chrome/security/security.properties @@ -85,3 +85,5 @@ BlockScriptWithWrongMimeType=Script from “%1$S” was blocked because of a dis # LOCALIZATION NOTE: Do not translate "data: URI". BlockTopLevelDataURINavigation=Navigation to toplevel data: URI not allowed (Blocked loading of: “%1$S”) + +BlockSubresourceFTP=Loading FTP subresource within http(s) page not allowed (Blocked loading of: “%1$S”) diff --git a/dom/media/MediaManager.cpp b/dom/media/MediaManager.cpp index 288f2e74d..979cb64c7 100644 --- a/dom/media/MediaManager.cpp +++ b/dom/media/MediaManager.cpp @@ -2049,6 +2049,16 @@ MediaManager::GetUserMedia(nsPIDOMWindowInner* aWindow, return rv; } + // Disallow access to null principal pages + nsCOMPtr<nsIPrincipal> principal = aWindow->GetExtantDoc()->NodePrincipal(); + if (principal->GetIsNullPrincipal()) { + RefPtr<MediaStreamError> error = + new MediaStreamError(aWindow, + NS_LITERAL_STRING("NotAllowedError")); + onFailure->OnError(error); + return NS_OK; + } + if (!Preferences::GetBool("media.navigator.video.enabled", true)) { c.mVideo.SetAsBoolean() = false; } @@ -2188,7 +2198,6 @@ MediaManager::GetUserMedia(nsPIDOMWindowInner* aWindow, StreamListeners* listeners = AddWindowID(windowID); // Create a disabled listener to act as a placeholder - nsIPrincipal* principal = aWindow->GetExtantDoc()->NodePrincipal(); RefPtr<GetUserMediaCallbackMediaStreamListener> listener = new GetUserMediaCallbackMediaStreamListener(mMediaThread, windowID, MakePrincipalHandle(principal)); diff --git a/dom/media/VideoFrameContainer.cpp b/dom/media/VideoFrameContainer.cpp index 2b1965766..56aea9d27 100644 --- a/dom/media/VideoFrameContainer.cpp +++ b/dom/media/VideoFrameContainer.cpp @@ -61,7 +61,7 @@ void VideoFrameContainer::UpdatePrincipalHandleForFrameIDLocked(const PrincipalH mFrameIDForPendingPrincipalHandle = aFrameID; } -static void +static bool SetImageToBlackPixel(PlanarYCbCrImage* aImage) { uint8_t blackPixel[] = { 0x10, 0x80, 0x80 }; @@ -72,7 +72,7 @@ SetImageToBlackPixel(PlanarYCbCrImage* aImage) data.mCrChannel = blackPixel + 2; data.mYStride = data.mCbCrStride = 1; data.mPicSize = data.mYSize = data.mCbCrSize = gfx::IntSize(1, 1); - aImage->CopyData(data); + return aImage->CopyData(data); } class VideoFrameContainerInvalidateRunnable : public Runnable { @@ -122,11 +122,13 @@ void VideoFrameContainer::SetCurrentFrames(const VideoSegment& aSegment) if (frame->GetForceBlack()) { if (!mBlackImage) { - mBlackImage = GetImageContainer()->CreatePlanarYCbCrImage(); - if (mBlackImage) { + RefPtr<Image> blackImage = GetImageContainer()->CreatePlanarYCbCrImage(); + if (blackImage) { // Sets the image to a single black pixel, which will be scaled to // fill the rendered size. - SetImageToBlackPixel(mBlackImage->AsPlanarYCbCrImage()); + if (SetImageToBlackPixel(blackImage->AsPlanarYCbCrImage())) { + mBlackImage = blackImage; + } } } if (mBlackImage) { diff --git a/dom/media/gmp/widevine-adapter/WidevineAdapter.cpp b/dom/media/gmp/widevine-adapter/WidevineAdapter.cpp index 74b5c38e8..57d4ecec2 100644 --- a/dom/media/gmp/widevine-adapter/WidevineAdapter.cpp +++ b/dom/media/gmp/widevine-adapter/WidevineAdapter.cpp @@ -46,7 +46,7 @@ void* GetCdmHost(int aHostInterfaceVersion, void* aUserData) Log("GetCdmHostFunc(%d, %p)", aHostInterfaceVersion, aUserData); WidevineDecryptor* decryptor = reinterpret_cast<WidevineDecryptor*>(aUserData); MOZ_ASSERT(decryptor); - return static_cast<cdm::Host_8*>(decryptor); + return static_cast<cdm::Host_9*>(decryptor); } #define STRINGIFY(s) _STRINGIFY(s) @@ -106,8 +106,8 @@ WidevineAdapter::GMPGetAPI(const char* aAPIName, WidevineDecryptor* decryptor = new WidevineDecryptor(); - auto cdm = reinterpret_cast<cdm::ContentDecryptionModule*>( - create(cdm::ContentDecryptionModule::kVersion, + auto cdm = reinterpret_cast<cdm::ContentDecryptionModule_9*>( + create(cdm::ContentDecryptionModule_9::kVersion, kEMEKeySystemWidevine.get(), kEMEKeySystemWidevine.Length(), &GetCdmHost, @@ -161,8 +161,8 @@ WidevineAdapter::Supports(int32_t aModuleVersion, int32_t aHostVersion) { return aModuleVersion == CDM_MODULE_VERSION && - aInterfaceVersion == cdm::ContentDecryptionModule::kVersion && - aHostVersion == cdm::Host_8::kVersion; + aInterfaceVersion == cdm::ContentDecryptionModule_9::kVersion && + aHostVersion == cdm::Host_9::kVersion; } } // namespace mozilla diff --git a/dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp b/dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp index 149fa1701..4d3408804 100644 --- a/dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp +++ b/dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp @@ -102,7 +102,7 @@ WidevineDecryptor::CreateSession(uint32_t aCreateSessionToken, } else { // Invalid init data type const char* errorMsg = "Invalid init data type when creating session."; - OnRejectPromise(aPromiseId, kNotSupportedError, 0, errorMsg, sizeof(errorMsg)); + OnRejectPromise(aPromiseId, kExceptionNotSupportedError, 0, errorMsg, sizeof(errorMsg)); return; } mPromiseIdToNewSessionTokens[aPromiseId] = aCreateSessionToken; @@ -302,6 +302,12 @@ WidevineDecryptor::GetCurrentWallTime() } void +WidevineDecryptor::OnResolveKeyStatusPromise(uint32_t aPromiseId, + cdm::KeyStatus aKeyStatus) { + //TODO: The callback of GetStatusForPolicy. See Mozilla bug 1404230. +} + +void WidevineDecryptor::OnResolveNewSessionPromise(uint32_t aPromiseId, const char* aSessionId, uint32_t aSessionIdSize) @@ -333,41 +339,59 @@ WidevineDecryptor::OnResolvePromise(uint32_t aPromiseId) } static GMPDOMException -ToGMPDOMException(cdm::Error aError) -{ - switch (aError) { - case kNotSupportedError: return kGMPNotSupportedError; - case kInvalidStateError: return kGMPInvalidStateError; - case kInvalidAccessError: - // Note: Chrome converts kInvalidAccessError to TypeError, since the - // Chromium CDM API doesn't have a type error enum value. The EME spec - // requires TypeError in some places, so we do the same conversion. - // See bug 1313202. - return kGMPTypeError; - case kQuotaExceededError: return kGMPQuotaExceededError; +ConvertCDMExceptionToGMPDOMException(cdm::Exception aException) +{ + switch (aException) { + case kExceptionNotSupportedError: return kGMPNotSupportedError; + case kExceptionInvalidStateError: return kGMPInvalidStateError; + case kExceptionTypeError: return kGMPTypeError; + case kExceptionQuotaExceededError: return kGMPQuotaExceededError; case kUnknownError: return kGMPInvalidModificationError; // Note: Unique placeholder. case kClientError: return kGMPAbortError; // Note: Unique placeholder. case kOutputError: return kGMPSecurityError; // Note: Unique placeholder. }; - return kGMPTimeoutError; // Note: Unique placeholder. + return kGMPInvalidStateError; // Note: Unique placeholder. +} + +// Align with spec, the Exceptions used by CDM to reject promises . +// https://w3c.github.io/encrypted-media/#exceptions +cdm::Exception +ConvertCDMErrorToCDMException(cdm::Error error) { + switch (error) { + case cdm::kNotSupportedError: + return cdm::Exception::kExceptionNotSupportedError; + case cdm::kInvalidStateError: + return cdm::Exception::kExceptionInvalidStateError; + case cdm::kInvalidAccessError: + return cdm::Exception::kExceptionTypeError; + case cdm::kQuotaExceededError: + return cdm::Exception::kExceptionQuotaExceededError; + + case cdm::kUnknownError: + case cdm::kClientError: + case cdm::kOutputError: + break; + } + + return cdm::Exception::kExceptionInvalidStateError; } void WidevineDecryptor::OnRejectPromise(uint32_t aPromiseId, - Error aError, + cdm::Exception aException, uint32_t aSystemCode, const char* aErrorMessage, uint32_t aErrorMessageSize) { if (!mCallback) { Log("Decryptor::OnRejectPromise(aPromiseId=%d, err=%d, sysCode=%u, msg=%s) FAIL; !mCallback", - aPromiseId, (int)aError, aSystemCode, aErrorMessage); + aPromiseId, (int)aException, aSystemCode, aErrorMessage); return; } Log("Decryptor::OnRejectPromise(aPromiseId=%d, err=%d, sysCode=%u, msg=%s)", - aPromiseId, (int)aError, aSystemCode, aErrorMessage); + aPromiseId, (int)aException, aSystemCode, aErrorMessage); mCallback->RejectPromise(aPromiseId, - ToGMPDOMException(aError), + ConvertCDMExceptionToGMPDOMException(aException), !aErrorMessageSize ? "" : aErrorMessage, aErrorMessageSize); } @@ -386,11 +410,9 @@ ToGMPMessageType(MessageType message_type) void WidevineDecryptor::OnSessionMessage(const char* aSessionId, uint32_t aSessionIdSize, - MessageType aMessageType, + cdm::MessageType aMessageType, const char* aMessage, - uint32_t aMessageSize, - const char* aLegacyDestinationUrl, - uint32_t aLegacyDestinationUrlLength) + uint32_t aMessageSize) { if (!mCallback) { Log("Decryptor::OnSessionMessage() FAIL; !mCallback"); @@ -479,28 +501,6 @@ WidevineDecryptor::OnSessionClosed(const char* aSessionId, } void -WidevineDecryptor::OnLegacySessionError(const char* aSessionId, - uint32_t aSessionIdLength, - Error aError, - uint32_t aSystemCode, - const char* aErrorMessage, - uint32_t aErrorMessageLength) -{ - if (!mCallback) { - Log("Decryptor::OnLegacySessionError(sid=%s, error=%d) FAIL; !mCallback", - aSessionId, (int)aError); - return; - } - Log("Decryptor::OnLegacySessionError(sid=%s, error=%d)", aSessionId, (int)aError); - mCallback->SessionError(aSessionId, - aSessionIdLength, - ToGMPDOMException(aError), - aSystemCode, - aErrorMessage, - aErrorMessageLength); -} - -void WidevineDecryptor::SendPlatformChallenge(const char* aServiceId, uint32_t aServiceIdSize, const char* aChallenge, @@ -538,4 +538,17 @@ WidevineDecryptor::CreateFileIO(FileIOClient* aClient) return new WidevineFileIO(aClient); } +void +WidevineDecryptor::RequestStorageId(uint32_t aVersion) +{ + Log("Decryptor::RequestStorageId() aVersion = %u", aVersion); + if (aVersion >= 0x80000000) { + mCDM->OnStorageId(aVersion, nullptr, 0); + return; + } + + //TODO: Need to provide a menaingful buffer instead of a dummy one. + mCDM->OnStorageId(aVersion, new uint8_t[1024*1024], 1024 * 1024); +} + } // namespace mozilla diff --git a/dom/media/gmp/widevine-adapter/WidevineDecryptor.h b/dom/media/gmp/widevine-adapter/WidevineDecryptor.h index d5185192b..f291c321d 100644 --- a/dom/media/gmp/widevine-adapter/WidevineDecryptor.h +++ b/dom/media/gmp/widevine-adapter/WidevineDecryptor.h @@ -16,7 +16,7 @@ namespace mozilla { class WidevineDecryptor : public GMPDecryptor - , public cdm::Host_8 + , public cdm::Host_9 { public: @@ -69,16 +69,19 @@ public: void DecryptingComplete() override; - // cdm::Host_8 + // cdm::Host_9 implementation cdm::Buffer* Allocate(uint32_t aCapacity) override; void SetTimer(int64_t aDelayMs, void* aContext) override; cdm::Time GetCurrentWallTime() override; + // cdm::Host_9 interface + void OnResolveKeyStatusPromise(uint32_t aPromiseId, + cdm::KeyStatus aKeyStatus) override; void OnResolveNewSessionPromise(uint32_t aPromiseId, const char* aSessionId, uint32_t aSessionIdSize) override; void OnResolvePromise(uint32_t aPromiseId) override; void OnRejectPromise(uint32_t aPromiseId, - cdm::Error aError, + cdm::Exception aException, uint32_t aSystemCode, const char* aErrorMessage, uint32_t aErrorMessageSize) override; @@ -86,9 +89,7 @@ public: uint32_t aSessionIdSize, cdm::MessageType aMessageType, const char* aMessage, - uint32_t aMessageSize, - const char* aLegacyDestinationUrl, - uint32_t aLegacyDestinationUrlLength) override; + uint32_t aMessageSize) override; void OnSessionKeysChange(const char* aSessionId, uint32_t aSessionIdSize, bool aHasAdditionalUsableKey, @@ -99,12 +100,6 @@ public: cdm::Time aNewExpiryTime) override; void OnSessionClosed(const char* aSessionId, uint32_t aSessionIdSize) override; - void OnLegacySessionError(const char* aSessionId, - uint32_t aSessionId_length, - cdm::Error aError, - uint32_t aSystemCode, - const char* aErrorMessage, - uint32_t aErrorMessageLength) override; void SendPlatformChallenge(const char* aServiceId, uint32_t aServiceIdSize, const char* aChallenge, @@ -113,6 +108,9 @@ public: void QueryOutputProtectionStatus() override; void OnDeferredInitializationDone(cdm::StreamType aStreamType, cdm::Status aDecoderStatus) override; + // cdm::Host_9 interface + // NOTE: the interface has changed upstream. + void RequestStorageId(uint32_t aVersion) override; cdm::FileIO* CreateFileIO(cdm::FileIOClient* aClient) override; GMPDecryptorCallback* Callback() const { return mCallback; } @@ -120,7 +118,7 @@ public: private: ~WidevineDecryptor(); RefPtr<CDMWrapper> mCDM; - cdm::ContentDecryptionModule_8* CDM() { return mCDM->GetCDM(); } + cdm::ContentDecryptionModule_9* CDM() { return mCDM->GetCDM(); } GMPDecryptorCallback* mCallback; std::map<uint32_t, uint32_t> mPromiseIdToNewSessionTokens; diff --git a/dom/media/gmp/widevine-adapter/WidevineUtils.cpp b/dom/media/gmp/widevine-adapter/WidevineUtils.cpp index 925dfe1a1..10c6c2e18 100644 --- a/dom/media/gmp/widevine-adapter/WidevineUtils.cpp +++ b/dom/media/gmp/widevine-adapter/WidevineUtils.cpp @@ -43,7 +43,7 @@ ToGMPErr(cdm::Status aStatus) case cdm::kSuccess: return GMPNoErr; case cdm::kNeedMoreData: return GMPGenericErr; case cdm::kNoKey: return GMPNoKeyErr; - case cdm::kSessionError: return GMPGenericErr; + case cdm::kInitializationError: return GMPGenericErr; case cdm::kDecryptError: return GMPCryptoErr; case cdm::kDecodeError: return GMPDecodeErr; case cdm::kDeferredInitialization: return GMPGenericErr; @@ -77,7 +77,7 @@ void InitInputBuffer(const GMPEncryptedBufferMetadata* aCrypto, aInputBuffer.timestamp = aTimestamp; } -CDMWrapper::CDMWrapper(cdm::ContentDecryptionModule_8* aCDM, +CDMWrapper::CDMWrapper(cdm::ContentDecryptionModule_9* aCDM, WidevineDecryptor* aDecryptor) : mCDM(aCDM) , mDecryptor(aDecryptor) diff --git a/dom/media/gmp/widevine-adapter/WidevineUtils.h b/dom/media/gmp/widevine-adapter/WidevineUtils.h index 57c004a87..2f6137fe3 100644 --- a/dom/media/gmp/widevine-adapter/WidevineUtils.h +++ b/dom/media/gmp/widevine-adapter/WidevineUtils.h @@ -48,12 +48,16 @@ class CDMWrapper { public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CDMWrapper) - explicit CDMWrapper(cdm::ContentDecryptionModule_8* aCDM, + explicit CDMWrapper(cdm::ContentDecryptionModule_9* aCDM, WidevineDecryptor* aDecryptor); - cdm::ContentDecryptionModule_8* GetCDM() const { return mCDM; } + cdm::ContentDecryptionModule_9* GetCDM() const { return mCDM; } + void OnStorageId(uint32_t aVersion, const uint8_t* aStorageId, + uint32_t aStorageIdSize) { + mCDM->OnStorageId(aVersion, aStorageId, aStorageIdSize); + } private: ~CDMWrapper(); - cdm::ContentDecryptionModule_8* mCDM; + cdm::ContentDecryptionModule_9* mCDM; RefPtr<WidevineDecryptor> mDecryptor; }; diff --git a/dom/media/gmp/widevine-adapter/WidevineVideoDecoder.h b/dom/media/gmp/widevine-adapter/WidevineVideoDecoder.h index b143f75f7..f5e63519b 100644 --- a/dom/media/gmp/widevine-adapter/WidevineVideoDecoder.h +++ b/dom/media/gmp/widevine-adapter/WidevineVideoDecoder.h @@ -45,7 +45,7 @@ private: ~WidevineVideoDecoder(); - cdm::ContentDecryptionModule_8* CDM() const { + cdm::ContentDecryptionModule_9* CDM() const { // CDM should only be accessed before 'DecodingComplete'. MOZ_ASSERT(mCDMWrapper); // CDMWrapper ensure the CDM is non-null, no need to check again. diff --git a/dom/media/gmp/widevine-adapter/content_decryption_module.h b/dom/media/gmp/widevine-adapter/content_decryption_module.h index 512ca9768..0539135fb 100644 --- a/dom/media/gmp/widevine-adapter/content_decryption_module.h +++ b/dom/media/gmp/widevine-adapter/content_decryption_module.h @@ -5,6 +5,8 @@ #ifndef CDM_CONTENT_DECRYPTION_MODULE_H_ #define CDM_CONTENT_DECRYPTION_MODULE_H_ +#include "content_decryption_module_export.h" + #if defined(_MSC_VER) typedef unsigned char uint8_t; typedef unsigned int uint32_t; @@ -14,25 +16,21 @@ typedef __int64 int64_t; #include <stdint.h> #endif -// Define CDM_EXPORT so that functionality implemented by the CDM module -// can be exported to consumers. -#if defined(WIN32) - -#if defined(CDM_IMPLEMENTATION) -#define CDM_EXPORT __declspec(dllexport) -#else -#define CDM_EXPORT __declspec(dllimport) -#endif // defined(CDM_IMPLEMENTATION) - -#else // defined(WIN32) - -#if defined(CDM_IMPLEMENTATION) -#define CDM_EXPORT __attribute__((visibility("default"))) +// Define CDM_CLASS_API to export class types. We have to add visibility +// attributes to make sure virtual tables in CDM consumer and CDM implementation +// are the same. Generally, it was always a good idea, as there're no guarantees +// about that for the internal symbols, but it has only become a practical issue +// after introduction of LTO devirtualization. See more details on +// https://crbug.com/609564#c35 +#if defined(_WIN32) +#if defined(__clang__) +#define CDM_CLASS_API [[clang::lto_visibility_public]] #else -#define CDM_EXPORT +#define CDM_CLASS_API #endif - -#endif // defined(WIN32) +#else // defined(_WIN32) +#define CDM_CLASS_API __attribute__((visibility("default"))) +#endif // defined(_WIN32) // The version number must be rolled when the exported functions are updated! // If the CDM and the adapter use different versions of these functions, the @@ -48,9 +46,9 @@ typedef __int64 int64_t; #define BUILD_ENTRYPOINT_NO_EXPANSION(name, version) name##_##version extern "C" { -CDM_EXPORT void INITIALIZE_CDM_MODULE(); +CDM_API void INITIALIZE_CDM_MODULE(); -CDM_EXPORT void DeinitializeCdmModule(); +CDM_API void DeinitializeCdmModule(); // Returns a pointer to the requested CDM Host interface upon success. // Returns NULL if the requested CDM Host interface is not supported. @@ -65,30 +63,30 @@ typedef void* (*GetCdmHostFunc)(int host_interface_version, void* user_data); // |cdm_interface_version|. // Caller retains ownership of arguments and must call Destroy() on the returned // object. -CDM_EXPORT void* CreateCdmInstance( +CDM_API void* CreateCdmInstance( int cdm_interface_version, const char* key_system, uint32_t key_system_size, GetCdmHostFunc get_cdm_host_func, void* user_data); -CDM_EXPORT const char* GetCdmVersion(); +CDM_API const char* GetCdmVersion(); } namespace cdm { -class AudioFrames; -class DecryptedBlock; -class VideoFrame; +class CDM_CLASS_API AudioFrames; +class CDM_CLASS_API DecryptedBlock; +class CDM_CLASS_API VideoFrame; -class Host_7; -class Host_8; +class CDM_CLASS_API Host_8; +class CDM_CLASS_API Host_9; enum Status { kSuccess = 0, kNeedMoreData, // Decoder needs more data to produce a decoded frame/sample. - kNoKey, // The required decryption key is not available. - kSessionError, // Session management error. - kDecryptError, // Decryption failed. - kDecodeError, // Error decoding audio or video. + kNoKey, // The required decryption key is not available. + kInitializationError, // Initialization error. + kDecryptError, // Decryption failed. + kDecodeError, // Error decoding audio or video. kDeferredInitialization // Decoder is not ready for initialization. }; @@ -97,6 +95,7 @@ enum Status { // The following starts with the list of DOM4 exceptions from: // http://www.w3.org/TR/dom/#domexception // Some DOM4 exceptions are not included as they are not expected to be used. +// Should only be used on Host_8 and before. enum Error { kNotSupportedError = 9, kInvalidStateError = 11, @@ -113,8 +112,20 @@ enum Error { kOutputError = 101 }; -// Time is defined as the number of seconds since the -// Epoch (00:00:00 UTC, January 1, 1970). +// Exceptions used by the CDM to reject promises. +// https://w3c.github.io/encrypted-media/#exceptions +enum Exception { + kExceptionTypeError, + kExceptionNotSupportedError, + kExceptionInvalidStateError, + kExceptionQuotaExceededError +}; + +// Time is defined as the number of seconds since the Epoch +// (00:00:00 UTC, January 1, 1970), not including any added leap second. +// Also see Time definition in spec: https://w3c.github.io/encrypted-media/#time +// Note that Time is defined in millisecond accuracy in the spec but in second +// accuracy here. typedef double Time; // An input buffer can be split into several continuous subsamples. @@ -151,13 +162,13 @@ struct SubsampleEntry { // unencrypted. struct InputBuffer { InputBuffer() - : data(NULL), + : data(nullptr), data_size(0), - key_id(NULL), + key_id(nullptr), key_id_size(0), - iv(NULL), + iv(nullptr), iv_size(0), - subsamples(NULL), + subsamples(nullptr), num_subsamples(0), timestamp(0) {} @@ -188,7 +199,7 @@ struct AudioDecoderConfig { channel_count(0), bits_per_channel(0), samples_per_second(0), - extra_data(NULL), + extra_data(nullptr), extra_data_size(0) {} AudioCodec codec; @@ -214,10 +225,25 @@ enum AudioFormat { }; // Surface formats based on FOURCC labels, see: http://www.fourcc.org/yuv.php +// Values are chosen to be consistent with Chromium's VideoPixelFormat values. enum VideoFormat { kUnknownVideoFormat = 0, // Unknown format value. Used for error reporting. - kYv12, // 12bpp YVU planar 1x1 Y, 2x2 VU samples. - kI420 // 12bpp YVU planar 1x1 Y, 2x2 UV samples. + kYv12 = 1, // 12bpp YVU planar 1x1 Y, 2x2 VU samples. + kI420 = 2, // 12bpp YUV planar 1x1 Y, 2x2 UV samples. + + // In the following formats, each sample uses 16-bit in storage, while the + // sample value is stored in the least significant N bits where N is + // specified by the number after "P". For example, for YUV420P9, each Y, U, + // and V sample is stored in the least significant 9 bits in a 2-byte block. + kYUV420P9 = 16, + kYUV420P10 = 17, + kYUV422P9 = 18, + kYUV422P10 = 19, + kYUV444P9 = 20, + kYUV444P10 = 21, + kYUV420P12 = 22, + kYUV422P12 = 23, + kYUV444P12 = 24, }; struct Size { @@ -245,14 +271,19 @@ struct VideoDecoderConfig { kH264ProfileHigh, kH264ProfileHigh10, kH264ProfileHigh422, - kH264ProfileHigh444Predictive + kH264ProfileHigh444Predictive, + // VP9 Profiles are only passed in starting from CDM_9. + kVP9Profile0, + kVP9Profile1, + kVP9Profile2, + kVP9Profile3 }; VideoDecoderConfig() : codec(kUnknownVideoCodec), profile(kUnknownVideoCodecProfile), format(kUnknownVideoFormat), - extra_data(NULL), + extra_data(nullptr), extra_data_size(0) {} VideoCodec codec; @@ -294,7 +325,7 @@ struct PlatformChallengeResponse { // Used when passing arrays of binary data. Does not own the referenced data. struct BinaryData { - BinaryData() : data(NULL), length(0) {} + BinaryData() : data(nullptr), length(0) {} const uint8_t* data; uint32_t length; }; @@ -316,7 +347,10 @@ enum KeyStatus { // should be 0 when |status| == kUsable. struct KeyInformation { KeyInformation() - : key_id(NULL), key_id_size(0), status(kInternalError), system_code(0) {} + : key_id(nullptr), + key_id_size(0), + status(kInternalError), + system_code(0) {} const uint8_t* key_id; uint32_t key_id_size; KeyStatus status; @@ -372,6 +406,24 @@ enum MessageType { kLicenseRelease = 2 }; +enum HdcpVersion { + kHdcpVersionNone, + kHdcpVersion1_0, + kHdcpVersion1_1, + kHdcpVersion1_2, + kHdcpVersion1_3, + kHdcpVersion1_4, + kHdcpVersion2_0, + kHdcpVersion2_1, + kHdcpVersion2_2 +}; + +struct Policy { + Policy() : min_hdcp_version(kHdcpVersionNone) {} + + HdcpVersion min_hdcp_version; +}; + // FileIO interface provides a way for the CDM to store data in a file in // persistent storage. This interface aims only at providing basic read/write // capabilities and should not be used as a full fledged file IO API. @@ -381,7 +433,7 @@ enum MessageType { // Note to implementors of this interface: // Per-origin storage and the ability for users to clear it are important. // See http://www.w3.org/TR/encrypted-media/#privacy-storedinfo. -class FileIO { +class CDM_CLASS_API FileIO { public: // Opens the file with |file_name| for read and write. // FileIOClient::OnOpenComplete() will be called after the opening @@ -389,8 +441,9 @@ class FileIO { // - When the file is opened by a CDM instance, it will be classified as "in // use". In this case other CDM instances in the same domain may receive // kInUse status when trying to open it. - // - |file_name| must not contain forward slash ('/') or backslash ('\'), and - // must not start with an underscore ('_'). + // - |file_name| must only contain letters (A-Za-z), digits(0-9), or "._-". + // It must not start with an underscore ('_'), and must be at least 1 + // character and no more than 256 characters long. virtual void Open(const char* file_name, uint32_t file_name_size) = 0; // Reads the contents of the file. FileIOClient::OnReadComplete() will be @@ -421,7 +474,7 @@ class FileIO { // When kError is returned, the FileIO object could be in an error state. All // following calls (other than Close()) could return kError. The CDM should // still call Close() to destroy the FileIO object. -class FileIOClient { +class CDM_CLASS_API FileIOClient { public: enum Status { kSuccess = 0, @@ -462,10 +515,20 @@ class FileIOClient { // provided in CreateCdmInstance() to allocate any Buffer that needs to // be passed back to the caller. Implementations must call Buffer::Destroy() // when a Buffer is created that will never be returned to the caller. -class ContentDecryptionModule_7 { +class CDM_CLASS_API ContentDecryptionModule_8 { public: - static const int kVersion = 7; - typedef Host_7 Host; + static const int kVersion = 8; + typedef Host_8 Host; + + // Initializes the CDM instance, providing information about permitted + // functionalities. + // If |allow_distinctive_identifier| is false, messages from the CDM, + // such as message events, must not contain a Distinctive Identifier, + // even in an encrypted form. + // If |allow_persistent_state| is false, the CDM must not attempt to + // persist state. Calls to CreateFileIO() will fail. + virtual void Initialize(bool allow_distinctive_identifier, + bool allow_persistent_state) = 0; // SetServerCertificate(), CreateSessionAndGenerateRequest(), LoadSession(), // UpdateSession(), CloseSession(), and RemoveSession() all accept a @@ -484,8 +547,7 @@ class ContentDecryptionModule_7 { // or Host::OnRejectPromise(). virtual void CreateSessionAndGenerateRequest(uint32_t promise_id, SessionType session_type, - const char* init_data_type, - uint32_t init_data_type_size, + InitDataType init_data_type, const uint8_t* init_data, uint32_t init_data_size) = 0; @@ -631,8 +693,8 @@ class ContentDecryptionModule_7 { virtual void Destroy() = 0; protected: - ContentDecryptionModule_7() {} - virtual ~ContentDecryptionModule_7() {} + ContentDecryptionModule_8() {} + virtual ~ContentDecryptionModule_8() {} }; // ContentDecryptionModule interface that all CDMs need to implement. @@ -641,10 +703,10 @@ class ContentDecryptionModule_7 { // provided in CreateCdmInstance() to allocate any Buffer that needs to // be passed back to the caller. Implementations must call Buffer::Destroy() // when a Buffer is created that will never be returned to the caller. -class ContentDecryptionModule_8 { +class CDM_CLASS_API ContentDecryptionModule_9 { public: - static const int kVersion = 8; - typedef Host_8 Host; + static const int kVersion = 9; + typedef Host_9 Host; // Initializes the CDM instance, providing information about permitted // functionalities. @@ -656,6 +718,13 @@ class ContentDecryptionModule_8 { virtual void Initialize(bool allow_distinctive_identifier, bool allow_persistent_state) = 0; + // Gets the key status if the CDM has a hypothetical key with the |policy|. + // The CDM must respond by calling either Host::OnResolveKeyStatusPromise() + // with the result key status or Host::OnRejectPromise() if an unexpected + // error happened or this method is not supported. + virtual void GetStatusForPolicy(uint32_t promise_id, + const Policy& policy) = 0; + // SetServerCertificate(), CreateSessionAndGenerateRequest(), LoadSession(), // UpdateSession(), CloseSession(), and RemoveSession() all accept a // |promise_id|, which must be passed to the completion Host method @@ -731,8 +800,8 @@ class ContentDecryptionModule_8 { // // Returns kSuccess if the |audio_decoder_config| is supported and the CDM // audio decoder is successfully initialized. - // Returns kSessionError if |audio_decoder_config| is not supported. The CDM - // may still be able to do Decrypt(). + // Returns kInitializationError if |audio_decoder_config| is not supported. + // The CDM may still be able to do Decrypt(). // Returns kDeferredInitialization if the CDM is not ready to initialize the // decoder at this time. Must call Host::OnDeferredInitializationDone() once // initialization is complete. @@ -744,8 +813,8 @@ class ContentDecryptionModule_8 { // // Returns kSuccess if the |video_decoder_config| is supported and the CDM // video decoder is successfully initialized. - // Returns kSessionError if |video_decoder_config| is not supported. The CDM - // may still be able to do Decrypt(). + // Returns kInitializationError if |video_decoder_config| is not supported. + // The CDM may still be able to do Decrypt(). // Returns kDeferredInitialization if the CDM is not ready to initialize the // decoder at this time. Must call Host::OnDeferredInitializationDone() once // initialization is complete. @@ -815,18 +884,30 @@ class ContentDecryptionModule_8 { uint32_t link_mask, uint32_t output_protection_mask) = 0; + // Called by the host after a call to Host::RequestStorageId(). If the + // version of the storage ID requested is available, |storage_id| and + // |storage_id_size| are set appropriately. |version| will be the same as + // what was requested, unless 0 (latest) was requested, in which case + // |version| will be the actual version number for the |storage_id| returned. + // If the requested version is not available, null/zero will be provided as + // |storage_id| and |storage_id_size|, respectively, and |version| should be + // ignored. + virtual void OnStorageId(uint32_t version, + const uint8_t* storage_id, + uint32_t storage_id_size) = 0; + // Destroys the object in the same context as it was created. virtual void Destroy() = 0; protected: - ContentDecryptionModule_8() {} - virtual ~ContentDecryptionModule_8() {} + ContentDecryptionModule_9() {} + virtual ~ContentDecryptionModule_9() {} }; -typedef ContentDecryptionModule_8 ContentDecryptionModule; +typedef ContentDecryptionModule_9 ContentDecryptionModule; // Represents a buffer created by Allocator implementations. -class Buffer { +class CDM_CLASS_API Buffer { public: // Destroys the buffer in the same context as it was created. virtual void Destroy() = 0; @@ -845,9 +926,9 @@ class Buffer { void operator=(const Buffer&); }; -class Host_7 { +class CDM_CLASS_API Host_8 { public: - static const int kVersion = 7; + static const int kVersion = 8; // Returns a Buffer* containing non-zero members upon success, or NULL on // failure. The caller owns the Buffer* after this call. The buffer is not @@ -859,7 +940,7 @@ class Host_7 { // from now with |context|. virtual void SetTimer(int64_t delay_ms, void* context) = 0; - // Returns the current wall time in seconds. + // Returns the current wall time. virtual Time GetCurrentWallTime() = 0; // Called by the CDM when a session is created or loaded and the value for the @@ -917,8 +998,10 @@ class Host_7 { // session |session_id|. This can happen as the result of an Update() call // or some other event. If this happens as a result of a call to Update(), // it must be called before resolving the Update() promise. |new_expiry_time| - // can be 0 to represent "undefined". Size parameter should not include - // null termination. + // represents the time after which the key(s) in the session will no longer + // be usable for decryption. It can be 0 if no such time exists or if the + // license explicitly never expires. Size parameter should not include null + // termination. virtual void OnExpirationChange(const char* session_id, uint32_t session_id_size, Time new_expiry_time) = 0; @@ -978,13 +1061,13 @@ class Host_7 { virtual FileIO* CreateFileIO(FileIOClient* client) = 0; protected: - Host_7() {} - virtual ~Host_7() {} + Host_8() {} + virtual ~Host_8() {} }; -class Host_8 { +class CDM_CLASS_API Host_9 { public: - static const int kVersion = 8; + static const int kVersion = 9; // Returns a Buffer* containing non-zero members upon success, or NULL on // failure. The caller owns the Buffer* after this call. The buffer is not @@ -996,9 +1079,14 @@ class Host_8 { // from now with |context|. virtual void SetTimer(int64_t delay_ms, void* context) = 0; - // Returns the current wall time in seconds. + // Returns the current wall time. virtual Time GetCurrentWallTime() = 0; + // Called by the CDM when a key status is available in response to + // GetStatusForPolicy(). + virtual void OnResolveKeyStatusPromise(uint32_t promise_id, + KeyStatus key_status) = 0; + // Called by the CDM when a session is created or loaded and the value for the // MediaKeySession's sessionId attribute is available (|session_id|). // This must be called before OnSessionMessage() or @@ -1016,26 +1104,21 @@ class Host_8 { // Called by the CDM when an error occurs as a result of one of the // ContentDecryptionModule calls that accept a |promise_id|. - // |error| must be specified, |error_message| and |system_code| + // |exception| must be specified. |error_message| and |system_code| // are optional. |error_message_size| should not include null termination. virtual void OnRejectPromise(uint32_t promise_id, - Error error, + Exception exception, uint32_t system_code, const char* error_message, uint32_t error_message_size) = 0; // Called by the CDM when it has a message for session |session_id|. // Size parameters should not include null termination. - // |legacy_destination_url| is only for supporting the prefixed EME API and - // is ignored by unprefixed EME. It should only be non-null if |message_type| - // is kLicenseRenewal. virtual void OnSessionMessage(const char* session_id, uint32_t session_id_size, MessageType message_type, const char* message, - uint32_t message_size, - const char* legacy_destination_url, - uint32_t legacy_destination_url_length) = 0; + uint32_t message_size) = 0; // Called by the CDM when there has been a change in keys or their status for // session |session_id|. |has_additional_usable_key| should be set if a @@ -1054,8 +1137,10 @@ class Host_8 { // session |session_id|. This can happen as the result of an Update() call // or some other event. If this happens as a result of a call to Update(), // it must be called before resolving the Update() promise. |new_expiry_time| - // can be 0 to represent "undefined". Size parameter should not include - // null termination. + // represents the time after which the key(s) in the session will no longer + // be usable for decryption. It can be 0 if no such time exists or if the + // license explicitly never expires. Size parameter should not include null + // termination. virtual void OnExpirationChange(const char* session_id, uint32_t session_id_size, Time new_expiry_time) = 0; @@ -1065,21 +1150,6 @@ class Host_8 { virtual void OnSessionClosed(const char* session_id, uint32_t session_id_size) = 0; - // Called by the CDM when an error occurs in session |session_id| - // unrelated to one of the ContentDecryptionModule calls that accept a - // |promise_id|. |error| must be specified, |error_message| and - // |system_code| are optional. Length parameters should not include null - // termination. - // Note: - // - This method is only for supporting prefixed EME API. - // - This method will be ignored by unprefixed EME. All errors reported - // in this method should probably also be reported by one of other methods. - virtual void OnLegacySessionError( - const char* session_id, uint32_t session_id_length, - Error error, - uint32_t system_code, - const char* error_message, uint32_t error_message_length) = 0; - // The following are optional methods that may not be implemented on all // platforms. @@ -1114,13 +1184,22 @@ class Host_8 { // CDM can call this method multiple times to operate on different files. virtual FileIO* CreateFileIO(FileIOClient* client) = 0; + // Requests a specific version of the storage ID. A storage ID is a stable, + // device specific ID used by the CDM to securely store persistent data. The + // ID will be returned by the host via ContentDecryptionModule::OnStorageId(). + // If |version| is 0, the latest version will be returned. All |version|s + // that are greater than or equal to 0x80000000 are reserved for the CDM and + // should not be supported or returned by the host. The CDM must not expose + // the ID outside the client device, even in encrypted form. + virtual void RequestStorageId(uint32_t version) = 0; + protected: - Host_8() {} - virtual ~Host_8() {} + Host_9() {} + virtual ~Host_9() {} }; // Represents a decrypted block that has not been decoded. -class DecryptedBlock { +class CDM_CLASS_API DecryptedBlock { public: virtual void SetDecryptedBuffer(Buffer* buffer) = 0; virtual Buffer* DecryptedBuffer() = 0; @@ -1135,7 +1214,7 @@ class DecryptedBlock { virtual ~DecryptedBlock() {} }; -class VideoFrame { +class CDM_CLASS_API VideoFrame { public: enum VideoPlane { kYPlane = 0, @@ -1178,7 +1257,7 @@ class VideoFrame { // // |<----------------- AudioFrames ------------------>| // | audio buffer 0 | audio buffer 1 | audio buffer 2 | -class AudioFrames { +class CDM_CLASS_API AudioFrames { public: virtual void SetFrameBuffer(Buffer* buffer) = 0; virtual Buffer* FrameBuffer() = 0; diff --git a/dom/media/gmp/widevine-adapter/content_decryption_module_export.h b/dom/media/gmp/widevine-adapter/content_decryption_module_export.h new file mode 100644 index 000000000..51d485892 --- /dev/null +++ b/dom/media/gmp/widevine-adapter/content_decryption_module_export.h @@ -0,0 +1,22 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CDM_CONTENT_DECRYPTION_MODULE_EXPORT_H_ +#define CDM_CONTENT_DECRYPTION_MODULE_EXPORT_H_ + +// Define CDM_API so that functionality implemented by the CDM module +// can be exported to consumers. +#if defined(_WIN32) + +#if defined(CDM_IMPLEMENTATION) +#define CDM_API __declspec(dllexport) +#else +#define CDM_API __declspec(dllimport) +#endif // defined(CDM_IMPLEMENTATION) + +#else // defined(_WIN32) +#define CDM_API __attribute__((visibility("default"))) +#endif // defined(_WIN32) + +#endif // CDM_CONTENT_DECRYPTION_MODULE_EXPORT_H_ diff --git a/dom/media/gmp/widevine-adapter/content_decryption_module_ext.h b/dom/media/gmp/widevine-adapter/content_decryption_module_ext.h new file mode 100644 index 000000000..5df8344e6 --- /dev/null +++ b/dom/media/gmp/widevine-adapter/content_decryption_module_ext.h @@ -0,0 +1,64 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CDM_CONTENT_DECRYPTION_MODULE_EXT_H_ +#define CDM_CONTENT_DECRYPTION_MODULE_EXT_H_ + +#if defined(_WIN32) +#include <windows.h> +#endif + +#include "content_decryption_module_export.h" + +#if defined(_MSC_VER) +typedef unsigned int uint32_t; +#else +#include <stdint.h> +#endif + +namespace cdm { + +#if defined(_WIN32) +typedef wchar_t FilePathCharType; +typedef HANDLE PlatformFile; +const PlatformFile kInvalidPlatformFile = INVALID_HANDLE_VALUE; +#else +typedef char FilePathCharType; +typedef int PlatformFile; +const PlatformFile kInvalidPlatformFile = -1; +#endif // defined(_WIN32) + +struct HostFile { + HostFile(const FilePathCharType* file_path, + PlatformFile file, + PlatformFile sig_file) + : file_path(file_path), file(file), sig_file(sig_file) {} + + // File that is part of the host of the CDM. + const FilePathCharType* file_path = nullptr; + PlatformFile file = kInvalidPlatformFile; + + // Signature file for |file|. + PlatformFile sig_file = kInvalidPlatformFile; +}; + +} // namespace cdm + +extern "C" { + +// Functions in this file are dynamically retrieved by their versioned function +// names. Increment the version number for any backward incompatible API +// changes. + +// Verifies CDM host. All files in |host_files| are opened in read-only mode. +// +// Returns false and closes all files if there is an immediate failure. +// Otherwise returns true as soon as possible and processes the files +// asynchronously. All files MUST be closed by the CDM after this one-time +// processing is finished. +CDM_API bool VerifyCdmHost_0(const cdm::HostFile* host_files, + uint32_t num_files); +} + +#endif // CDM_CONTENT_DECRYPTION_MODULE_EXT_H_ diff --git a/dom/media/webaudio/AudioBuffer.cpp b/dom/media/webaudio/AudioBuffer.cpp index cb834f6a5..e7eba2d48 100644 --- a/dom/media/webaudio/AudioBuffer.cpp +++ b/dom/media/webaudio/AudioBuffer.cpp @@ -27,7 +27,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AudioBuffer) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AudioBuffer) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(AudioBuffer) diff --git a/dom/media/webaudio/AudioParam.cpp b/dom/media/webaudio/AudioParam.cpp index 6f5574993..c1a874264 100644 --- a/dom/media/webaudio/AudioParam.cpp +++ b/dom/media/webaudio/AudioParam.cpp @@ -22,7 +22,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AudioParam) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AudioParam) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNode) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(AudioParam) diff --git a/dom/media/webaudio/MediaBufferDecoder.cpp b/dom/media/webaudio/MediaBufferDecoder.cpp index 2ee11eacd..f3b75ca1a 100644 --- a/dom/media/webaudio/MediaBufferDecoder.cpp +++ b/dom/media/webaudio/MediaBufferDecoder.cpp @@ -44,7 +44,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(WebAudioDecodeJob) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOutput) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSuccessCallback) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFailureCallback) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(WebAudioDecodeJob) diff --git a/dom/media/webaudio/WaveShaperNode.cpp b/dom/media/webaudio/WaveShaperNode.cpp index d5c617dcd..4c50f2f1d 100644 --- a/dom/media/webaudio/WaveShaperNode.cpp +++ b/dom/media/webaudio/WaveShaperNode.cpp @@ -23,7 +23,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(WaveShaperNode, AudioNode) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(WaveShaperNode, AudioNode) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(WaveShaperNode) diff --git a/dom/network/TCPSocketChild.cpp b/dom/network/TCPSocketChild.cpp index 8eb19a1db..72581ca9d 100644 --- a/dom/network/TCPSocketChild.cpp +++ b/dom/network/TCPSocketChild.cpp @@ -50,7 +50,6 @@ namespace dom { NS_IMPL_CYCLE_COLLECTION_CLASS(TCPSocketChildBase) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(TCPSocketChildBase) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSocket) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END diff --git a/dom/performance/PerformanceMainThread.cpp b/dom/performance/PerformanceMainThread.cpp index 64c06d3ea..5a84f5fb1 100644 --- a/dom/performance/PerformanceMainThread.cpp +++ b/dom/performance/PerformanceMainThread.cpp @@ -27,7 +27,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PerformanceMainThread, NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTiming, mNavigation, mDocEntry) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(PerformanceMainThread, diff --git a/dom/performance/PerformanceObserver.cpp b/dom/performance/PerformanceObserver.cpp index d02acfb09..7bf194bb7 100644 --- a/dom/performance/PerformanceObserver.cpp +++ b/dom/performance/PerformanceObserver.cpp @@ -34,7 +34,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(PerformanceObserver) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPerformance) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(PerformanceObserver) diff --git a/dom/plugins/base/nptypes.h b/dom/plugins/base/nptypes.h index 12a5fb78e..c36532472 100644 --- a/dom/plugins/base/nptypes.h +++ b/dom/plugins/base/nptypes.h @@ -22,18 +22,6 @@ typedef unsigned int uint32_t; typedef long long int64_t; typedef unsigned long long uint64_t; -#elif defined(_AIX) || defined(__sun) || defined(__osf__) || defined(IRIX) || defined(HPUX) - /* - * AIX and SunOS ship a inttypes.h header that defines [u]int32_t, - * but not bool for C. - */ - #include <inttypes.h> - - #ifndef __cplusplus - typedef int bool; - #define true 1 - #define false 0 - #endif #elif defined(bsdi) || defined(FREEBSD) || defined(OPENBSD) /* * BSD/OS, FreeBSD, and OpenBSD ship sys/types.h that define int32_t and diff --git a/dom/plugins/base/nsPluginsDirUnix.cpp b/dom/plugins/base/nsPluginsDirUnix.cpp index 6d112b4fe..e6956c34c 100644 --- a/dom/plugins/base/nsPluginsDirUnix.cpp +++ b/dom/plugins/base/nsPluginsDirUnix.cpp @@ -19,17 +19,7 @@ #include "nsIPrefService.h" #define LOCAL_PLUGIN_DLL_SUFFIX ".so" -#if defined(__hpux) -#define DEFAULT_X11_PATH "/usr/lib/X11R6/" -#undef LOCAL_PLUGIN_DLL_SUFFIX -#define LOCAL_PLUGIN_DLL_SUFFIX ".sl" -#define LOCAL_PLUGIN_DLL_ALT_SUFFIX ".so" -#elif defined(_AIX) -#define DEFAULT_X11_PATH "/usr/lib" -#define LOCAL_PLUGIN_DLL_ALT_SUFFIX ".a" -#elif defined(SOLARIS) -#define DEFAULT_X11_PATH "/usr/openwin/lib/" -#elif defined(LINUX) +#if defined(LINUX) #define DEFAULT_X11_PATH "/usr/X11R6/lib/" #elif defined(__APPLE__) #define DEFAULT_X11_PATH "/usr/X11R6/lib" @@ -102,11 +92,7 @@ static bool LoadExtraSharedLib(const char *name, char **soname, bool tryToGetSon #define PLUGIN_MAX_NUMBER_OF_EXTRA_LIBS 32 #define PREF_PLUGINS_SONAME "plugin.soname.list" -#if defined(SOLARIS) || defined(HPUX) -#define DEFAULT_EXTRA_LIBS_LIST "libXt" LOCAL_PLUGIN_DLL_SUFFIX ":libXext" LOCAL_PLUGIN_DLL_SUFFIX ":libXm" LOCAL_PLUGIN_DLL_SUFFIX -#else #define DEFAULT_EXTRA_LIBS_LIST "libXt" LOCAL_PLUGIN_DLL_SUFFIX ":libXext" LOCAL_PLUGIN_DLL_SUFFIX -#endif /* this function looks for user_pref("plugin.soname.list", "/usr/X11R6/lib/libXt.so.6:libXext.so"); @@ -280,15 +266,9 @@ nsresult nsPluginFile::LoadPlugin(PRLibrary **outLibrary) // work fine. -#if defined(SOLARIS) || defined(HPUX) - // Acrobat/libXm: Lazy resolving might cause crash later (bug 211587) - *outLibrary = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW); - pLibrary = *outLibrary; -#else // Some dlopen() doesn't recover from a failed PR_LD_NOW (bug 223744) *outLibrary = PR_LoadLibraryWithFlags(libSpec, 0); pLibrary = *outLibrary; -#endif if (!pLibrary) { LoadExtraSharedLibs(); // try reload plugin once more diff --git a/dom/promise/Promise.cpp b/dom/promise/Promise.cpp index 557f3a1f9..f636a9101 100644 --- a/dom/promise/Promise.cpp +++ b/dom/promise/Promise.cpp @@ -413,7 +413,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Promise) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResolveCallbacks) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRejectCallbacks) #endif // SPIDERMONKEY_PROMISE - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Promise) @@ -1995,7 +1994,6 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(CountdownHolder) NS_IMPL_CYCLE_COLLECTION_TRACE_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CountdownHolder) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPromise) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END diff --git a/dom/promise/PromiseCallback.cpp b/dom/promise/PromiseCallback.cpp index 3f4a689ae..6ecf983b7 100644 --- a/dom/promise/PromiseCallback.cpp +++ b/dom/promise/PromiseCallback.cpp @@ -47,7 +47,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ResolvePromiseCallback, PromiseCallback) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPromise) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ResolvePromiseCallback) @@ -107,7 +106,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(RejectPromiseCallback, PromiseCallback) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPromise) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(RejectPromiseCallback) @@ -170,7 +168,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(InvokePromiseFuncCallback, PromiseCallback) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPromiseFunc) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(InvokePromiseFuncCallback) @@ -256,7 +253,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(WrapperPromiseCallback, NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResolveFunc) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRejectFunc) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(WrapperPromiseCallback) diff --git a/dom/push/PushSubscriptionOptions.cpp b/dom/push/PushSubscriptionOptions.cpp index bc4fead1e..39252e9e8 100644 --- a/dom/push/PushSubscriptionOptions.cpp +++ b/dom/push/PushSubscriptionOptions.cpp @@ -36,7 +36,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(PushSubscriptionOptions) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(PushSubscriptionOptions) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(PushSubscriptionOptions) NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER diff --git a/dom/security/nsContentSecurityManager.cpp b/dom/security/nsContentSecurityManager.cpp index 570730312..f2cbc8fcf 100644 --- a/dom/security/nsContentSecurityManager.cpp +++ b/dom/security/nsContentSecurityManager.cpp @@ -92,6 +92,55 @@ nsContentSecurityManager::AllowTopLevelNavigationToDataURI(nsIChannel* aChannel) return false; } +/* static */ nsresult +nsContentSecurityManager::CheckFTPSubresourceLoad(nsIChannel* aChannel) +{ + // We dissallow using FTP resources as a subresource everywhere. + // The only valid way to use FTP resources is loading it as + // a top level document. + + nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo(); + if (!loadInfo) { + return NS_OK; + } + + nsContentPolicyType type = loadInfo->GetExternalContentPolicyType(); + if (type == nsIContentPolicy::TYPE_DOCUMENT) { + return NS_OK; + } + + nsCOMPtr<nsIURI> uri; + nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri)); + NS_ENSURE_SUCCESS(rv, rv); + if (!uri) { + return NS_OK; + } + + bool isFtpURI = (NS_SUCCEEDED(uri->SchemeIs("ftp", &isFtpURI)) && isFtpURI); + if (!isFtpURI) { + return NS_OK; + } + + nsCOMPtr<nsIDocument> doc; + if (nsINode* node = loadInfo->LoadingNode()) { + doc = node->OwnerDoc(); + } + + nsAutoCString spec; + uri->GetSpec(spec); + NS_ConvertUTF8toUTF16 specUTF16(NS_UnescapeURL(spec)); + const char16_t* params[] = { specUTF16.get() }; + + nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, + NS_LITERAL_CSTRING("FTP_URI_BLOCKED"), + doc, + nsContentUtils::eSECURITY_PROPERTIES, + "BlockSubresourceFTP", + params, ArrayLength(params)); + + return NS_ERROR_CONTENT_BLOCKED; +} + static nsresult ValidateSecurityFlags(nsILoadInfo* aLoadInfo) { @@ -574,6 +623,10 @@ nsContentSecurityManager::doContentSecurityCheck(nsIChannel* aChannel, rv = DoContentSecurityChecks(aChannel, loadInfo); NS_ENSURE_SUCCESS(rv, rv); + // Apply this after CSP checks to allow CSP reporting. + rv = CheckFTPSubresourceLoad(aChannel); + NS_ENSURE_SUCCESS(rv, rv); + // now lets set the initalSecurityFlag for subsequent calls loadInfo->SetInitialSecurityCheckDone(true); @@ -591,6 +644,9 @@ nsContentSecurityManager::AsyncOnChannelRedirect(nsIChannel* aOldChannel, // Are we enforcing security using LoadInfo? if (loadInfo && loadInfo->GetEnforceSecurity()) { nsresult rv = CheckChannel(aNewChannel); + if (NS_SUCCEEDED(rv)) { + rv = CheckFTPSubresourceLoad(aNewChannel); + } if (NS_FAILED(rv)) { aOldChannel->Cancel(rv); return rv; diff --git a/dom/security/nsContentSecurityManager.h b/dom/security/nsContentSecurityManager.h index bab847743..750dd8803 100644 --- a/dom/security/nsContentSecurityManager.h +++ b/dom/security/nsContentSecurityManager.h @@ -36,6 +36,7 @@ public: private: static nsresult CheckChannel(nsIChannel* aChannel); + static nsresult CheckFTPSubresourceLoad(nsIChannel* aChannel); virtual ~nsContentSecurityManager() {} diff --git a/dom/smil/nsSMILAnimationController.cpp b/dom/smil/nsSMILAnimationController.cpp index 0dd616346..69956203e 100644 --- a/dom/smil/nsSMILAnimationController.cpp +++ b/dom/smil/nsSMILAnimationController.cpp @@ -233,7 +233,7 @@ void nsSMILAnimationController::NotifyRefreshDriverCreated( nsRefreshDriver* aRefreshDriver) { - if (!mPauseState) { + if (!mPauseState && mChildContainerTable.Count()) { MaybeStartSampling(aRefreshDriver); } } diff --git a/dom/svg/DOMSVGLength.cpp b/dom/svg/DOMSVGLength.cpp index 574617045..c72c3e383 100644 --- a/dom/svg/DOMSVGLength.cpp +++ b/dom/svg/DOMSVGLength.cpp @@ -43,7 +43,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGLength) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mList) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSVGElement) -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGLength) diff --git a/dom/svg/DOMSVGLengthList.cpp b/dom/svg/DOMSVGLengthList.cpp index 9d93546d9..88ecd6007 100644 --- a/dom/svg/DOMSVGLengthList.cpp +++ b/dom/svg/DOMSVGLengthList.cpp @@ -55,7 +55,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGLengthList) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGLengthList) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAList) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGLengthList) NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER diff --git a/dom/svg/DOMSVGNumber.cpp b/dom/svg/DOMSVGNumber.cpp index 97d80d4d0..6b9528606 100644 --- a/dom/svg/DOMSVGNumber.cpp +++ b/dom/svg/DOMSVGNumber.cpp @@ -35,7 +35,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGNumber) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mList) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGNumber) NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER diff --git a/dom/svg/DOMSVGNumberList.cpp b/dom/svg/DOMSVGNumberList.cpp index 00fb7ba4d..85322688f 100644 --- a/dom/svg/DOMSVGNumberList.cpp +++ b/dom/svg/DOMSVGNumberList.cpp @@ -55,7 +55,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGNumberList) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGNumberList) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAList) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGNumberList) NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER diff --git a/dom/svg/DOMSVGPathSeg.cpp b/dom/svg/DOMSVGPathSeg.cpp index 95be3521e..a15bf42e9 100644 --- a/dom/svg/DOMSVGPathSeg.cpp +++ b/dom/svg/DOMSVGPathSeg.cpp @@ -31,7 +31,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGPathSeg) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mList) -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGPathSeg) diff --git a/dom/svg/DOMSVGPathSegList.cpp b/dom/svg/DOMSVGPathSegList.cpp index 0b811cdb1..36768ea34 100644 --- a/dom/svg/DOMSVGPathSegList.cpp +++ b/dom/svg/DOMSVGPathSegList.cpp @@ -36,7 +36,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGPathSegList) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGPathSegList) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mElement) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGPathSegList) NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER diff --git a/dom/svg/DOMSVGPointList.cpp b/dom/svg/DOMSVGPointList.cpp index 966ef476e..ca06bd270 100644 --- a/dom/svg/DOMSVGPointList.cpp +++ b/dom/svg/DOMSVGPointList.cpp @@ -55,7 +55,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGPointList) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGPointList) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mElement) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGPointList) NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER diff --git a/dom/svg/DOMSVGTransformList.cpp b/dom/svg/DOMSVGTransformList.cpp index 30760bc6d..e4bde9aeb 100644 --- a/dom/svg/DOMSVGTransformList.cpp +++ b/dom/svg/DOMSVGTransformList.cpp @@ -54,7 +54,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGTransformList) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGTransformList) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAList) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGTransformList) NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER diff --git a/dom/svg/SVGTransform.cpp b/dom/svg/SVGTransform.cpp index b73018d1c..1cba997eb 100644 --- a/dom/svg/SVGTransform.cpp +++ b/dom/svg/SVGTransform.cpp @@ -51,7 +51,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mList) SVGMatrix* matrix = SVGMatrixTearoffTable().GetTearoff(tmp); CycleCollectionNoteChild(cb, matrix, "matrix"); -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(SVGTransform) diff --git a/dom/svg/nsISVGPoint.cpp b/dom/svg/nsISVGPoint.cpp index 1c1971004..f4fdb9dd0 100644 --- a/dom/svg/nsISVGPoint.cpp +++ b/dom/svg/nsISVGPoint.cpp @@ -32,7 +32,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsISVGPoint) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mList) -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsISVGPoint) diff --git a/dom/svg/nsSVGElement.h b/dom/svg/nsSVGElement.h index 42bc05746..257ed7a2e 100644 --- a/dom/svg/nsSVGElement.h +++ b/dom/svg/nsSVGElement.h @@ -715,7 +715,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER \ NS_IMPL_CYCLE_COLLECTION_UNLINK_END \ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_val) \ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(_element) \ - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS \ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END \ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(_val) \ NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER \ diff --git a/dom/url/URLSearchParams.cpp b/dom/url/URLSearchParams.cpp index d9492f81c..f762299f8 100644 --- a/dom/url/URLSearchParams.cpp +++ b/dom/url/URLSearchParams.cpp @@ -314,14 +314,6 @@ URLSearchParams::URLSearchParams(nsISupports* aParent, { } -URLSearchParams::URLSearchParams(nsISupports* aParent, - const URLSearchParams& aOther) - : mParams(new URLParams(*aOther.mParams.get())) - , mParent(aParent) - , mObserver(nullptr) -{ -} - URLSearchParams::~URLSearchParams() { DeleteAll(); @@ -335,34 +327,43 @@ URLSearchParams::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) /* static */ already_AddRefed<URLSearchParams> URLSearchParams::Constructor(const GlobalObject& aGlobal, - const nsAString& aInit, + const USVStringSequenceSequenceOrUSVStringUSVStringRecordOrUSVString& aInit, ErrorResult& aRv) { RefPtr<URLSearchParams> sp = new URLSearchParams(aGlobal.GetAsSupports(), nullptr); - NS_ConvertUTF16toUTF8 input(aInit); - - if (StringBeginsWith(input, NS_LITERAL_CSTRING("?"))) { - sp->ParseInput(Substring(input, 1, input.Length() - 1)); + if (aInit.IsUSVString()) { + NS_ConvertUTF16toUTF8 input(aInit.GetAsUSVString()); + if (StringBeginsWith(input, NS_LITERAL_CSTRING("?"))) { + sp->ParseInput(Substring(input, 1, input.Length() - 1)); + } else { + sp->ParseInput(input); + } + } else if (aInit.IsUSVStringSequenceSequence()) { + const Sequence<Sequence<nsString>>& list = + aInit.GetAsUSVStringSequenceSequence(); + for (uint32_t i = 0; i < list.Length(); ++i) { + const Sequence<nsString>& item = list[i]; + if (item.Length() != 2) { + aRv.Throw(NS_ERROR_DOM_TYPE_ERR); + return nullptr; + } + sp->Append(item[0], item[1]); + } + } else if (aInit.IsUSVStringUSVStringRecord()) { + const Record<nsString, nsString>& record = + aInit.GetAsUSVStringUSVStringRecord(); + for (auto& entry : record.Entries()) { + sp->Append(entry.mKey, entry.mValue); + } } else { - sp->ParseInput(input); + MOZ_CRASH("URLSearchParams: Invalid string"); } return sp.forget(); } -/* static */ already_AddRefed<URLSearchParams> -URLSearchParams::Constructor(const GlobalObject& aGlobal, - URLSearchParams& aInit, - ErrorResult& aRv) -{ - RefPtr<URLSearchParams> sp = - new URLSearchParams(aGlobal.GetAsSupports(), aInit); - - return sp.forget(); -} - void URLSearchParams::ParseInput(const nsACString& aInput) { diff --git a/dom/url/URLSearchParams.h b/dom/url/URLSearchParams.h index 4b0aaa991..9fefd78dd 100644 --- a/dom/url/URLSearchParams.h +++ b/dom/url/URLSearchParams.h @@ -20,6 +20,7 @@ namespace mozilla { namespace dom { class URLSearchParams; +class USVStringSequenceSequenceOrUSVStringUSVStringRecordOrUSVString; class URLSearchParamsObserver : public nsISupports { @@ -43,14 +44,6 @@ public: DeleteAll(); } - explicit URLParams(const URLParams& aOther) - : mParams(aOther.mParams) - {} - - URLParams(const URLParams&& aOther) - : mParams(Move(aOther.mParams)) - {} - class ForEachIterator { public: @@ -144,9 +137,6 @@ public: explicit URLSearchParams(nsISupports* aParent, URLSearchParamsObserver* aObserver=nullptr); - URLSearchParams(nsISupports* aParent, - const URLSearchParams& aOther); - // WebIDL methods nsISupports* GetParentObject() const { @@ -157,11 +147,8 @@ public: WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; static already_AddRefed<URLSearchParams> - Constructor(const GlobalObject& aGlobal, const nsAString& aInit, - ErrorResult& aRv); - - static already_AddRefed<URLSearchParams> - Constructor(const GlobalObject& aGlobal, URLSearchParams& aInit, + Constructor(const GlobalObject& aGlobal, + const USVStringSequenceSequenceOrUSVStringUSVStringRecordOrUSVString& aInit, ErrorResult& aRv); void ParseInput(const nsACString& aInput); diff --git a/dom/webidl/AddonEvent.webidl b/dom/webidl/AddonEvent.webidl deleted file mode 100644 index 235f81ec2..000000000 --- a/dom/webidl/AddonEvent.webidl +++ /dev/null @@ -1,12 +0,0 @@ -[ Func="mozilla::AddonManagerWebAPI::IsAPIEnabled", - Constructor(DOMString type, AddonEventInit eventInitDict)] -interface AddonEvent : Event { - readonly attribute DOMString id; - readonly attribute boolean needsRestart; -}; - -dictionary AddonEventInit : EventInit { - required DOMString id; - required boolean needsRestart; -}; - diff --git a/dom/webidl/AddonManager.webidl b/dom/webidl/AddonManager.webidl deleted file mode 100644 index 02c7953e6..000000000 --- a/dom/webidl/AddonManager.webidl +++ /dev/null @@ -1,91 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -/* We need a JSImplementation but cannot get one without a contract ID. - Since Addon and AddonInstall are only ever created from JS they don't need - real contract IDs. */ -[ChromeOnly, JSImplementation="dummy"] -interface Addon { - // The add-on's ID. - readonly attribute DOMString id; - // The add-on's version. - readonly attribute DOMString version; - // The add-on's type (extension, theme, etc.). - readonly attribute DOMString type; - // The add-on's name in the current locale. - readonly attribute DOMString name; - // The add-on's description in the current locale. - readonly attribute DOMString description; - // If the user has enabled this add-on, note that it still may not be running - // depending on whether enabling requires a restart or if the add-on is - // incompatible in some way. - readonly attribute boolean isEnabled; - // If the add-on is currently active in the browser. - readonly attribute boolean isActive; - // If the add-on may be uninstalled - readonly attribute boolean canUninstall; - - Promise<boolean> uninstall(); - Promise<void> setEnabled(boolean value); -}; - -[ChromeOnly, JSImplementation="dummy"] -interface AddonInstall : EventTarget { - // One of the STATE_* symbols from AddonManager.jsm - readonly attribute DOMString state; - // One of the ERROR_* symbols from AddonManager.jsm, or null - readonly attribute DOMString? error; - // How many bytes have been downloaded - readonly attribute long long progress; - // How many total bytes will need to be downloaded or -1 if unknown - readonly attribute long long maxProgress; - - Promise<void> install(); - Promise<void> cancel(); -}; - -dictionary addonInstallOptions { - required DOMString url; - // If a non-empty string is passed for "hash", it is used to verify the - // checksum of the downloaded XPI before installing. If is omitted or if - // it is null or empty string, no checksum verification is performed. - DOMString? hash = null; -}; - -[HeaderFile="mozilla/AddonManagerWebAPI.h", - Func="mozilla::AddonManagerWebAPI::IsAPIEnabled", - NavigatorProperty="mozAddonManager", - JSImplementation="@mozilla.org/addon-web-api/manager;1"] -interface AddonManager : EventTarget { - /** - * Gets information about an add-on - * - * @param id - * The ID of the add-on to test for. - * @return A promise. It will resolve to an Addon if the add-on is installed. - */ - Promise<Addon> getAddonByID(DOMString id); - - /** - * Creates an AddonInstall object for a given URL. - * - * @param options - * Only one supported option: 'url', the URL of the addon to install. - * @return A promise that resolves to an instance of AddonInstall. - */ - Promise<AddonInstall> createInstall(optional addonInstallOptions options); - - /* Hooks for managing event listeners */ - [ChromeOnly] - void eventListenerWasAdded(DOMString type); - [ChromeOnly] - void eventListenerWasRemoved(DOMString type); -}; - -[ChromeOnly,Exposed=System,HeaderFile="mozilla/AddonManagerWebAPI.h"] -interface AddonManagerPermissions { - static boolean isHostPermitted(DOMString host); -}; - diff --git a/dom/webidl/Headers.webidl b/dom/webidl/Headers.webidl index 205ab9f9e..eef552a7f 100644 --- a/dom/webidl/Headers.webidl +++ b/dom/webidl/Headers.webidl @@ -8,7 +8,7 @@ * http://fetch.spec.whatwg.org/#headers-class */ -typedef (Headers or sequence<sequence<ByteString>> or MozMap<ByteString>) HeadersInit; +typedef (Headers or sequence<sequence<ByteString>> or record<ByteString, ByteString>) HeadersInit; enum HeadersGuardEnum { "none", diff --git a/dom/webidl/InstallTrigger.webidl b/dom/webidl/InstallTrigger.webidl index 789fb2bc4..68f48ddc6 100644 --- a/dom/webidl/InstallTrigger.webidl +++ b/dom/webidl/InstallTrigger.webidl @@ -57,7 +57,7 @@ interface InstallTriggerImpl { * A callback to call as each installation succeeds or fails * @return true if the installations were successfully started */ - boolean install(MozMap<(DOMString or InstallTriggerData)> installs, + boolean install(record<DOMString, (DOMString or InstallTriggerData)> installs, optional InstallTriggerCallback callback); /** diff --git a/dom/webidl/TestInterfaceJS.webidl b/dom/webidl/TestInterfaceJS.webidl index 1ca629c39..2cf8d701a 100644 --- a/dom/webidl/TestInterfaceJS.webidl +++ b/dom/webidl/TestInterfaceJS.webidl @@ -24,7 +24,7 @@ interface TestInterfaceJS : EventTarget { any pingPongObjectOrString((object or DOMString) objOrString); TestInterfaceJSDictionary pingPongDictionary(optional TestInterfaceJSDictionary dict); long pingPongDictionaryOrLong(optional (TestInterfaceJSUnionableDictionary or long) dictOrLong); - DOMString pingPongMap(MozMap<any> map); + DOMString pingPongMap(record<DOMString, any> map); long objectSequenceLength(sequence<object> seq); long anySequenceLength(sequence<any> seq); diff --git a/dom/webidl/URLSearchParams.webidl b/dom/webidl/URLSearchParams.webidl index 93e846071..b93f4e8b1 100644 --- a/dom/webidl/URLSearchParams.webidl +++ b/dom/webidl/URLSearchParams.webidl @@ -13,8 +13,7 @@ * http://www.openwebfoundation.org/legal/the-owf-1-0-agreements/owfa-1-0. */ -[Constructor(optional USVString init = ""), - Constructor(URLSearchParams init), +[Constructor(optional (sequence<sequence<USVString>> or record<USVString, USVString> or USVString) init = ""), Exposed=(Window,Worker,WorkerDebugger,System)] interface URLSearchParams { void append(USVString name, USVString value); diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index 06fea2f20..aae7e479c 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -591,9 +591,6 @@ WEBIDL_FILES = [ 'XULElement.webidl', ] -if CONFIG['MOZ_WEBEXTENSIONS']: - WEBIDL_FILES += ['AddonManager.webidl'] - if CONFIG['MOZ_AUDIO_CHANNEL_MANAGER']: WEBIDL_FILES += [ 'AudioChannelManager.webidl', @@ -722,9 +719,6 @@ 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', diff --git a/dom/worklet/WorkletGlobalScope.cpp b/dom/worklet/WorkletGlobalScope.cpp index 4caeae81a..8c05a0abe 100644 --- a/dom/worklet/WorkletGlobalScope.cpp +++ b/dom/worklet/WorkletGlobalScope.cpp @@ -22,8 +22,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WorkletGlobalScope) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(WorkletGlobalScope) - - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsole) tmp->TraverseHostObjectURIs(cb); diff --git a/dom/xbl/nsXBLDocumentInfo.cpp b/dom/xbl/nsXBLDocumentInfo.cpp index 283775dc6..73b08d7e1 100644 --- a/dom/xbl/nsXBLDocumentInfo.cpp +++ b/dom/xbl/nsXBLDocumentInfo.cpp @@ -52,7 +52,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXBLDocumentInfo) if (tmp->mDocument && nsCCUncollectableMarker::InGeneration(cb, tmp->mDocument->GetMarkedCCGeneration())) { - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS return NS_SUCCESS_INTERRUPTED_TRAVERSE; } NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument) @@ -62,7 +61,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXBLDocumentInfo) iter.UserData()->Traverse(cb); } } - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsXBLDocumentInfo) if (tmp->mBindingTable) { diff --git a/dom/xslt/xpath/XPathResult.cpp b/dom/xslt/xpath/XPathResult.cpp index 33315c942..07121347e 100644 --- a/dom/xslt/xpath/XPathResult.cpp +++ b/dom/xslt/xpath/XPathResult.cpp @@ -63,7 +63,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(XPathResult) NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(XPathResult) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResultNodes) diff --git a/dom/xslt/xpath/txUnaryExpr.cpp b/dom/xslt/xpath/txUnaryExpr.cpp index 95682b5b2..ae20fda46 100644 --- a/dom/xslt/xpath/txUnaryExpr.cpp +++ b/dom/xslt/xpath/txUnaryExpr.cpp @@ -23,16 +23,7 @@ UnaryExpr::evaluate(txIEvalContext* aContext, txAExprResult** aResult) NS_ENSURE_SUCCESS(rv, rv); double value = exprRes->numberValue(); -#ifdef HPUX - /* - * Negation of a zero doesn't produce a negative - * zero on HPUX. Perform the operation by multiplying with - * -1. - */ - return aContext->recycler()->getNumberResult(-1 * value, aResult); -#else return aContext->recycler()->getNumberResult(-value, aResult); -#endif } TX_IMPL_EXPR_STUBS_1(UnaryExpr, NODESET_RESULT, expr) diff --git a/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp b/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp index 726441757..c9bcc31ff 100644 --- a/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp +++ b/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp @@ -462,10 +462,6 @@ txCompileObserver::startLoad(nsIURI* aUri, txStylesheetCompiler* aCompiler, nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel)); if (httpChannel) { - httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"), - NS_LITERAL_CSTRING("*/*"), - false); - nsCOMPtr<nsIURI> referrerURI; aReferrerPrincipal->GetURI(getter_AddRefs(referrerURI)); if (referrerURI) { diff --git a/dom/xul/nsXULElement.cpp b/dom/xul/nsXULElement.cpp index 14fa898ab..e351a46eb 100644 --- a/dom/xul/nsXULElement.cpp +++ b/dom/xul/nsXULElement.cpp @@ -2173,7 +2173,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULPrototypeNode) } ImplCycleCollectionTraverse(cb, elem->mChildren, "mChildren"); } - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsXULPrototypeNode) if (tmp->mType == nsXULPrototypeNode::eType_Script) { |