diff options
Diffstat (limited to 'dom/base')
48 files changed, 925 insertions, 786 deletions
diff --git a/dom/base/DOMIntersectionObserver.cpp b/dom/base/DOMIntersectionObserver.cpp index 169c3fe7a..e39abf1a6 100644 --- a/dom/base/DOMIntersectionObserver.cpp +++ b/dom/base/DOMIntersectionObserver.cpp @@ -47,6 +47,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMIntersectionObserver) NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback) NS_IMPL_CYCLE_COLLECTION_UNLINK(mRoot) NS_IMPL_CYCLE_COLLECTION_UNLINK(mQueuedEntries) + tmp->Disconnect(); NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMIntersectionObserver) @@ -184,9 +185,10 @@ DOMIntersectionObserver::Connect() if (mConnected) { return; } + mConnected = true; + nsIDocument* document = mOwner->GetExtantDoc(); document->AddIntersectionObserver(this); - mConnected = true; } void @@ -202,7 +204,9 @@ DOMIntersectionObserver::Disconnect() mObservationTargets.Clear(); if (mOwner) { nsIDocument* document = mOwner->GetExtantDoc(); - document->RemoveIntersectionObserver(this); + if (document) { + document->RemoveIntersectionObserver(this); + } } mConnected = false; } @@ -248,6 +252,12 @@ EdgeInclusiveIntersection(const nsRect& aRect, const nsRect& aOtherRect) return Some(nsRect(left, top, right - left, bottom - top)); } +enum class BrowsingContextInfo { + SimilarOriginBrowsingContext, + DifferentOriginBrowsingContext, + UnknownBrowsingContext +}; + void DOMIntersectionObserver::Update(nsIDocument* aDocument, DOMHighResTimeStamp time) { @@ -359,11 +369,22 @@ DOMIntersectionObserver::Update(nsIDocument* aDocument, DOMHighResTimeStamp time } } - nsRect rootIntersectionRect = rootRect; - bool isInSimilarOriginBrowsingContext = rootFrame && targetFrame && - CheckSimilarOrigin(root, target); + nsRect rootIntersectionRect; + BrowsingContextInfo isInSimilarOriginBrowsingContext = + BrowsingContextInfo::UnknownBrowsingContext; + + if (rootFrame && targetFrame) { + rootIntersectionRect = rootRect; + } + + if (root && target) { + isInSimilarOriginBrowsingContext = CheckSimilarOrigin(root, target) ? + BrowsingContextInfo::SimilarOriginBrowsingContext : + BrowsingContextInfo::DifferentOriginBrowsingContext; + } - if (isInSimilarOriginBrowsingContext) { + if (isInSimilarOriginBrowsingContext == + BrowsingContextInfo::SimilarOriginBrowsingContext) { rootIntersectionRect.Inflate(rootMargin); } @@ -413,7 +434,9 @@ DOMIntersectionObserver::Update(nsIDocument* aDocument, DOMHighResTimeStamp time if (target->UpdateIntersectionObservation(this, threshold)) { QueueIntersectionObserverEntry( target, time, - isInSimilarOriginBrowsingContext ? Some(rootIntersectionRect) : Nothing(), + isInSimilarOriginBrowsingContext == + BrowsingContextInfo::DifferentOriginBrowsingContext ? + Nothing() : Some(rootIntersectionRect), targetRect, intersectionRect, intersectionRatio ); } diff --git a/dom/base/DOMIntersectionObserver.h b/dom/base/DOMIntersectionObserver.h index 3eb10ad38..8144fc5c5 100644 --- a/dom/base/DOMIntersectionObserver.h +++ b/dom/base/DOMIntersectionObserver.h @@ -101,9 +101,7 @@ protected: class DOMIntersectionObserver final : public nsISupports, public nsWrapperCache { - virtual ~DOMIntersectionObserver() { - Disconnect(); - } + virtual ~DOMIntersectionObserver() { } public: DOMIntersectionObserver(already_AddRefed<nsPIDOMWindowInner>&& aOwner, diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp index 9ced64c0d..52d06b0f8 100644 --- a/dom/base/Element.cpp +++ b/dom/base/Element.cpp @@ -183,6 +183,12 @@ Element::DoGetClasses() const NS_IMETHODIMP Element::QueryInterface(REFNSIID aIID, void** aInstancePtr) { + if (aIID.Equals(NS_GET_IID(Element))) { + NS_ADDREF_THIS(); + *aInstancePtr = this; + return NS_OK; + } + NS_ASSERTION(aInstancePtr, "QueryInterface requires a non-NULL destination!"); nsresult rv = FragmentOrElement::QueryInterface(aIID, aInstancePtr); @@ -1838,6 +1844,24 @@ Element::UnbindFromTree(bool aDeep, bool aNullParent) SetParentIsContent(false); } +#ifdef DEBUG + // If we can get access to the PresContext, then we sanity-check that + // we're not leaving behind a pointer to ourselves as the PresContext's + // cached provider of the viewport's scrollbar styles. + if (document) { + nsIPresShell* presShell = document->GetShell(); + if (presShell) { + nsPresContext* presContext = presShell->GetPresContext(); + if (presContext) { + MOZ_ASSERT(this != + presContext->GetViewportScrollbarStylesOverrideNode(), + "Leaving behind a raw pointer to this node (as having " + "propagated scrollbar styles) - that's dangerous..."); + } + } + } +#endif + // Ensure that CSS transitions don't continue on an element at a // different place in the tree (even if reinserted before next // animation refresh). @@ -3888,44 +3912,55 @@ Element::ClearDataset() slots->mDataset = nullptr; } -nsTArray<Element::nsDOMSlots::IntersectionObserverRegistration>* +nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t>* Element::RegisteredIntersectionObservers() { nsDOMSlots* slots = DOMSlots(); return &slots->mRegisteredIntersectionObservers; } +enum nsPreviousIntersectionThreshold { + eUninitialized = -2, + eNonIntersecting = -1 +}; + void Element::RegisterIntersectionObserver(DOMIntersectionObserver* aObserver) { - RegisteredIntersectionObservers()->AppendElement( - nsDOMSlots::IntersectionObserverRegistration { aObserver, -1 }); + nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t>* observers = + RegisteredIntersectionObservers(); + if (observers->Contains(aObserver)) { + return; + } + + // Value can be: + // -2: Makes sure next calculated threshold always differs, leading to a + // notification task being scheduled. + // -1: Non-intersecting. + // >= 0: Intersecting, valid index of aObserver->mThresholds. + RegisteredIntersectionObservers()->Put(aObserver, eUninitialized); } void Element::UnregisterIntersectionObserver(DOMIntersectionObserver* aObserver) { - nsTArray<nsDOMSlots::IntersectionObserverRegistration>* observers = + nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t>* observers = RegisteredIntersectionObservers(); - for (uint32_t i = 0; i < observers->Length(); ++i) { - nsDOMSlots::IntersectionObserverRegistration reg = observers->ElementAt(i); - if (reg.observer == aObserver) { - observers->RemoveElementAt(i); - break; - } - } + observers->Remove(aObserver); } bool Element::UpdateIntersectionObservation(DOMIntersectionObserver* aObserver, int32_t aThreshold) { - nsTArray<nsDOMSlots::IntersectionObserverRegistration>* observers = + nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t>* observers = RegisteredIntersectionObservers(); - for (auto& reg : *observers) { - if (reg.observer == aObserver && reg.previousThreshold != aThreshold) { - reg.previousThreshold = aThreshold; - return true; - } + if (!observers->Contains(aObserver)) { + return false; + } + int32_t previousThreshold = observers->Get(aObserver); + if (previousThreshold != aThreshold) { + observers->Put(aObserver, aThreshold); + return true; } return false; } diff --git a/dom/base/Element.h b/dom/base/Element.h index cf1d197e2..049984d1b 100644 --- a/dom/base/Element.h +++ b/dom/base/Element.h @@ -1380,7 +1380,7 @@ protected: nsDOMTokenList* GetTokenList(nsIAtom* aAtom, const DOMTokenListSupportedTokenArray aSupportedTokens = nullptr); - nsTArray<nsDOMSlots::IntersectionObserverRegistration>* RegisteredIntersectionObservers(); + nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t>* RegisteredIntersectionObservers(); private: /** diff --git a/dom/base/File.cpp b/dom/base/File.cpp index 8602a3064..7d86dfe8a 100755 --- a/dom/base/File.cpp +++ b/dom/base/File.cpp @@ -912,7 +912,7 @@ BlobImplFile::GetType(nsAString& aType) new GetTypeRunnable(workerPrivate, this); ErrorResult rv; - runnable->Dispatch(rv); + runnable->Dispatch(Terminating, rv); if (NS_WARN_IF(rv.Failed())) { rv.SuppressException(); } diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp index 79f6cff51..fde983e7c 100644 --- a/dom/base/FragmentOrElement.cpp +++ b/dom/base/FragmentOrElement.cpp @@ -608,6 +608,7 @@ FragmentOrElement::nsDOMSlots::Unlink(bool aIsXUL) mLabelsList = nullptr; mCustomElementData = nullptr; mClassList = nullptr; + mRegisteredIntersectionObservers.Clear(); } size_t @@ -1359,6 +1360,13 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(FragmentOrElement) { nsDOMSlots *slots = tmp->GetExistingDOMSlots(); if (slots) { + if (tmp->IsElement()) { + Element* elem = tmp->AsElement(); + for (auto iter = slots->mRegisteredIntersectionObservers.Iter(); !iter.Done(); iter.Next()) { + DOMIntersectionObserver* observer = iter.Key(); + observer->UnlinkTarget(*elem); + } + } slots->Unlink(tmp->IsXULElement()); } } @@ -1937,7 +1945,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_INTERFACE_MAP_BEGIN(FragmentOrElement) NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(FragmentOrElement) - NS_INTERFACE_MAP_ENTRY(Element) NS_INTERFACE_MAP_ENTRY(nsIContent) NS_INTERFACE_MAP_ENTRY(nsINode) NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget) diff --git a/dom/base/FragmentOrElement.h b/dom/base/FragmentOrElement.h index 1cd8033bb..7c74e9cd4 100644 --- a/dom/base/FragmentOrElement.h +++ b/dom/base/FragmentOrElement.h @@ -21,6 +21,7 @@ #include "nsIWeakReference.h" // base class #include "nsNodeUtils.h" // class member nsNodeUtils::CloneNodeImpl #include "nsIHTMLCollection.h" +#include "nsDataHashtable.h" class ContentUnbinder; class nsContentList; @@ -353,12 +354,7 @@ public: /** * Registered Intersection Observers on the element. */ - struct IntersectionObserverRegistration { - DOMIntersectionObserver* observer; - int32_t previousThreshold; - }; - - nsTArray<IntersectionObserverRegistration> mRegisteredIntersectionObservers; + nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t> mRegisteredIntersectionObservers; }; protected: diff --git a/dom/base/IdleRequest.cpp b/dom/base/IdleRequest.cpp index 26190f98b..fb3983d37 100644 --- a/dom/base/IdleRequest.cpp +++ b/dom/base/IdleRequest.cpp @@ -9,7 +9,6 @@ #include "mozilla/Function.h" #include "mozilla/TimeStamp.h" #include "mozilla/dom/IdleDeadline.h" -#include "mozilla/dom/Performance.h" #include "mozilla/dom/PerformanceTiming.h" #include "mozilla/dom/WindowBinding.h" #include "nsComponentManagerUtils.h" @@ -20,138 +19,56 @@ namespace mozilla { namespace dom { -IdleRequest::IdleRequest(JSContext* aCx, nsPIDOMWindowInner* aWindow, - IdleRequestCallback& aCallback, uint32_t aHandle) - : mWindow(aWindow) - , mCallback(&aCallback) +IdleRequest::IdleRequest(IdleRequestCallback* aCallback, uint32_t aHandle) + : mCallback(aCallback) , mHandle(aHandle) , mTimeoutHandle(Nothing()) { - MOZ_ASSERT(aWindow); - - // Get the calling location. - nsJSUtils::GetCallingLocation(aCx, mFileName, &mLineNo, &mColumn); + MOZ_DIAGNOSTIC_ASSERT(mCallback); } IdleRequest::~IdleRequest() { } -NS_IMPL_CYCLE_COLLECTION_CLASS(IdleRequest) +NS_IMPL_CYCLE_COLLECTION(IdleRequest, mCallback) NS_IMPL_CYCLE_COLLECTING_ADDREF(IdleRequest) NS_IMPL_CYCLE_COLLECTING_RELEASE(IdleRequest) -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IdleRequest) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback) -NS_IMPL_CYCLE_COLLECTION_UNLINK_END - -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IdleRequest) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback) -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END - NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequest) - NS_INTERFACE_MAP_ENTRY(nsIRunnable) - NS_INTERFACE_MAP_ENTRY(nsICancelableRunnable) - NS_INTERFACE_MAP_ENTRY(nsIIncrementalRunnable) - NS_INTERFACE_MAP_ENTRY(nsITimeoutHandler) - NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITimeoutHandler) NS_INTERFACE_MAP_END -nsresult -IdleRequest::SetTimeout(uint32_t aTimeout) -{ - int32_t handle; - nsresult rv = nsGlobalWindow::Cast(mWindow)->SetTimeoutOrInterval( - this, aTimeout, false, Timeout::Reason::eIdleCallbackTimeout, &handle); - mTimeoutHandle = Some(handle); - - return rv; -} - -nsresult -IdleRequest::Run() -{ - if (mCallback) { - RunIdleRequestCallback(false); - } - - return NS_OK; -} - -nsresult -IdleRequest::Cancel() +void +IdleRequest::SetTimeoutHandle(int32_t aHandle) { - mCallback = nullptr; - CancelTimeout(); - if (isInList()) { - remove(); - } - Release(); - - return NS_OK; + mTimeoutHandle = Some(aHandle); } -void -IdleRequest::SetDeadline(TimeStamp aDeadline) +uint32_t +IdleRequest::GetTimeoutHandle() const { - mozilla::dom::Performance* perf = mWindow->GetPerformance(); - mDeadline = - perf ? perf->GetDOMTiming()->TimeStampToDOMHighRes(aDeadline) : 0.0; + MOZ_DIAGNOSTIC_ASSERT(mTimeoutHandle.isSome()); + return mTimeoutHandle.value(); } nsresult -IdleRequest::RunIdleRequestCallback(bool aDidTimeout) +IdleRequest::IdleRun(nsPIDOMWindowInner* aWindow, + DOMHighResTimeStamp aDeadline, + bool aDidTimeout) { MOZ_ASSERT(NS_IsMainThread()); + MOZ_DIAGNOSTIC_ASSERT(mCallback); - if (!aDidTimeout) { - CancelTimeout(); - } - - remove(); ErrorResult error; RefPtr<IdleDeadline> deadline = - new IdleDeadline(mWindow, aDidTimeout, mDeadline); + new IdleDeadline(aWindow, aDidTimeout, aDeadline); mCallback->Call(*deadline, error, "requestIdleCallback handler"); - mCallback = nullptr; - Release(); + mCallback = nullptr; + error.SuppressException(); return error.StealNSResult(); } -void -IdleRequest::CancelTimeout() -{ - if (mTimeoutHandle.isSome()) { - nsGlobalWindow::Cast(mWindow)->ClearTimeoutOrInterval( - mTimeoutHandle.value(), Timeout::Reason::eIdleCallbackTimeout); - } -} - -nsresult -IdleRequest::Call() -{ - SetDeadline(TimeStamp::Now()); - return RunIdleRequestCallback(true); -} - -void -IdleRequest::GetLocation(const char** aFileName, uint32_t* aLineNo, - uint32_t* aColumn) -{ - *aFileName = mFileName.get(); - *aLineNo = mLineNo; - *aColumn = mColumn; -} - -void -IdleRequest::MarkForCC() -{ - mCallback->MarkForCC(); -} - } // namespace dom } // namespace mozilla diff --git a/dom/base/IdleRequest.h b/dom/base/IdleRequest.h index cb234430a..acf56f852 100644 --- a/dom/base/IdleRequest.h +++ b/dom/base/IdleRequest.h @@ -12,7 +12,6 @@ #include "nsCOMPtr.h" #include "nsCycleCollectionParticipant.h" #include "nsDOMNavigationTiming.h" -#include "nsITimeoutHandler.h" class nsPIDOMWindowInner; @@ -21,28 +20,19 @@ namespace dom { class IdleRequestCallback; -class IdleRequest final : public nsITimeoutHandler - , public nsIRunnable - , public nsICancelableRunnable - , public nsIIncrementalRunnable - , public LinkedListElement<IdleRequest> +class IdleRequest final : public nsISupports, + public LinkedListElement<IdleRequest> { public: - IdleRequest(JSContext* aCx, nsPIDOMWindowInner* aWindow, - IdleRequestCallback& aCallback, uint32_t aHandle); + IdleRequest(IdleRequestCallback* aCallback, uint32_t aHandle); - virtual nsresult Call() override; - virtual void GetLocation(const char** aFileName, uint32_t* aLineNo, - uint32_t* aColumn) override; - virtual void MarkForCC() override; + nsresult IdleRun(nsPIDOMWindowInner* aWindow, + DOMHighResTimeStamp aDeadline, + bool aDidTimeout); - nsresult SetTimeout(uint32_t aTimout); - nsresult RunIdleRequestCallback(bool aDidTimeout); - void CancelTimeout(); - - NS_DECL_NSIRUNNABLE; - virtual nsresult Cancel() override; - virtual void SetDeadline(mozilla::TimeStamp aDeadline) override; + void SetTimeoutHandle(int32_t aHandle); + bool HasTimeout() const { return mTimeoutHandle.isSome(); } + uint32_t GetTimeoutHandle() const; uint32_t Handle() const { @@ -50,22 +40,14 @@ public: } NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(IdleRequest, nsITimeoutHandler) + NS_DECL_CYCLE_COLLECTION_CLASS(IdleRequest) private: ~IdleRequest(); - // filename, line number and JS language version string of the - // caller of setTimeout() - nsCString mFileName; - uint32_t mLineNo; - uint32_t mColumn; - - nsCOMPtr<nsPIDOMWindowInner> mWindow; RefPtr<IdleRequestCallback> mCallback; - uint32_t mHandle; + const uint32_t mHandle; mozilla::Maybe<int32_t> mTimeoutHandle; - DOMHighResTimeStamp mDeadline; }; } // namespace dom diff --git a/dom/base/Location.cpp b/dom/base/Location.cpp index e3b614931..7b3722f09 100644 --- a/dom/base/Location.cpp +++ b/dom/base/Location.cpp @@ -393,6 +393,10 @@ Location::GetHost(nsAString& aHost) NS_IMETHODIMP Location::SetHost(const nsAString& aHost) { + if (aHost.IsEmpty()) { + return NS_OK; // Ignore empty string + } + nsCOMPtr<nsIURI> uri; nsresult rv = GetWritableURI(getter_AddRefs(uri)); if (NS_WARN_IF(NS_FAILED(rv) || !uri)) { @@ -424,6 +428,10 @@ Location::GetHostname(nsAString& aHostname) NS_IMETHODIMP Location::SetHostname(const nsAString& aHostname) { + if (aHostname.IsEmpty()) { + return NS_OK; // Ignore empty string + } + nsCOMPtr<nsIURI> uri; nsresult rv = GetWritableURI(getter_AddRefs(uri)); if (NS_WARN_IF(NS_FAILED(rv) || !uri)) { @@ -507,6 +515,10 @@ nsresult Location::SetHrefWithBase(const nsAString& aHref, nsIURI* aBase, bool aReplace) { + if (aHref.IsEmpty()) { + return NS_OK; // Ignore empty string + } + nsresult result; nsCOMPtr<nsIURI> newUri; @@ -577,19 +589,17 @@ Location::GetPathname(nsAString& aPathname) aPathname.Truncate(); nsCOMPtr<nsIURI> uri; - nsresult result = NS_OK; - - result = GetURI(getter_AddRefs(uri)); + nsresult result = GetURI(getter_AddRefs(uri)); + if (NS_FAILED(result) || !uri) { + return result; + } - nsCOMPtr<nsIURIWithQuery> url(do_QueryInterface(uri)); - if (url) { - nsAutoCString file; + nsAutoCString file; - result = url->GetFilePath(file); + result = uri->GetFilePath(file); - if (NS_SUCCEEDED(result)) { - AppendUTF8toUTF16(file, aPathname); - } + if (NS_SUCCEEDED(result)) { + AppendUTF8toUTF16(file, aPathname); } return result; @@ -604,8 +614,7 @@ Location::SetPathname(const nsAString& aPathname) return rv; } - nsCOMPtr<nsIURIWithQuery> url(do_QueryInterface(uri)); - if (url && NS_SUCCEEDED(url->SetFilePath(NS_ConvertUTF16toUTF8(aPathname)))) { + if (NS_SUCCEEDED(uri->SetFilePath(NS_ConvertUTF16toUTF8(aPathname)))) { return SetURI(uri); } @@ -697,6 +706,10 @@ Location::GetProtocol(nsAString& aProtocol) NS_IMETHODIMP Location::SetProtocol(const nsAString& aProtocol) { + if (aProtocol.IsEmpty()) { + return NS_OK; // Ignore empty string + } + nsCOMPtr<nsIURI> uri; nsresult rv = GetWritableURI(getter_AddRefs(uri)); if (NS_WARN_IF(NS_FAILED(rv) || !uri)) { @@ -750,6 +763,10 @@ 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 5c315517c..ed96ee23b 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -767,12 +767,6 @@ StaticRefPtr<VibrateWindowListener> gVibrateWindowListener; static bool MayVibrate(nsIDocument* doc) { -#if MOZ_WIDGET_GONK - if (XRE_IsParentProcess()) { - return true; // The system app can always vibrate - } -#endif // MOZ_WIDGET_GONK - // Hidden documents cannot start or stop a vibration. return (doc && !doc->Hidden()); } diff --git a/dom/base/ScreenOrientation.cpp b/dom/base/ScreenOrientation.cpp index bb3ccf5c3..ec9c4fa29 100644 --- a/dom/base/ScreenOrientation.cpp +++ b/dom/base/ScreenOrientation.cpp @@ -309,7 +309,7 @@ ScreenOrientation::LockInternal(ScreenOrientationInternal aOrientation, ErrorRes return nullptr; } -#if !defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_WIDGET_GONK) +#if !defined(MOZ_WIDGET_ANDROID) // User agent does not support locking the screen orientation. p->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR); return p.forget(); diff --git a/dom/base/StructuredCloneHolder.cpp b/dom/base/StructuredCloneHolder.cpp index 1c27c632e..8e7cee340 100644 --- a/dom/base/StructuredCloneHolder.cpp +++ b/dom/base/StructuredCloneHolder.cpp @@ -1075,9 +1075,9 @@ StructuredCloneHolder::CustomReadHandler(JSContext* aCx, return ReadFormData(aCx, aReader, aIndex, this); } - if (aTag == SCTAG_DOM_IMAGEBITMAP) { - MOZ_ASSERT(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread || - mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread); + if (aTag == SCTAG_DOM_IMAGEBITMAP && + (mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread || + mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread)) { // Get the current global object. // This can be null. @@ -1087,7 +1087,9 @@ StructuredCloneHolder::CustomReadHandler(JSContext* aCx, parent, GetSurfaces(), aIndex); } - if (aTag == SCTAG_DOM_WASM) { + if (aTag == SCTAG_DOM_WASM && + (mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread || + mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread)) { return ReadWasmModule(aCx, aIndex, this); } @@ -1202,9 +1204,9 @@ StructuredCloneHolder::CustomReadTransferHandler(JSContext* aCx, return true; } - if (aTag == SCTAG_DOM_CANVAS) { - MOZ_ASSERT(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread || - mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread); + if (aTag == SCTAG_DOM_CANVAS && + (mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread || + mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread)) { MOZ_ASSERT(aContent); OffscreenCanvasCloneData* data = static_cast<OffscreenCanvasCloneData*>(aContent); @@ -1222,9 +1224,9 @@ StructuredCloneHolder::CustomReadTransferHandler(JSContext* aCx, return true; } - if (aTag == SCTAG_DOM_IMAGEBITMAP) { - MOZ_ASSERT(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread || - mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread); + if (aTag == SCTAG_DOM_IMAGEBITMAP && + (mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread || + mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread)) { MOZ_ASSERT(aContent); ImageBitmapCloneData* data = static_cast<ImageBitmapCloneData*>(aContent); @@ -1328,9 +1330,9 @@ StructuredCloneHolder::CustomFreeTransferHandler(uint32_t aTag, return; } - if (aTag == SCTAG_DOM_CANVAS) { - MOZ_ASSERT(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread || - mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread); + if (aTag == SCTAG_DOM_CANVAS && + (mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread || + mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread)) { MOZ_ASSERT(aContent); OffscreenCanvasCloneData* data = static_cast<OffscreenCanvasCloneData*>(aContent); @@ -1338,9 +1340,9 @@ StructuredCloneHolder::CustomFreeTransferHandler(uint32_t aTag, return; } - if (aTag == SCTAG_DOM_IMAGEBITMAP) { - MOZ_ASSERT(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread || - mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread); + if (aTag == SCTAG_DOM_IMAGEBITMAP && + (mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread || + mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread)) { MOZ_ASSERT(aContent); ImageBitmapCloneData* data = static_cast<ImageBitmapCloneData*>(aContent); diff --git a/dom/base/Timeout.h b/dom/base/Timeout.h index e929f3dd1..42e2f57f5 100644 --- a/dom/base/Timeout.h +++ b/dom/base/Timeout.h @@ -41,7 +41,11 @@ public: // default main thread being used. nsresult InitTimer(nsIEventTarget* aTarget, uint32_t aDelay); - enum class Reason { eTimeoutOrInterval, eIdleCallbackTimeout }; + enum class Reason + { + eTimeoutOrInterval, + eIdleCallbackTimeout, + }; #ifdef DEBUG bool HasRefCntOne() const; @@ -62,6 +66,8 @@ public: // True if this is a repeating/interval timer bool mIsInterval; + // Used to allow several reasons for setting a timeout, where each + // 'Reason' value is using a possibly overlapping set of id:s. Reason mReason; // Returned as value of setTimeout() diff --git a/dom/base/TimeoutHandler.cpp b/dom/base/TimeoutHandler.cpp new file mode 100644 index 000000000..78c3f16dd --- /dev/null +++ b/dom/base/TimeoutHandler.cpp @@ -0,0 +1,43 @@ +/* -*- 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/. */ + +#include "TimeoutHandler.h" + +namespace mozilla { +namespace dom { + +TimeoutHandler::TimeoutHandler(JSContext* aCx) + : TimeoutHandler() +{ + nsJSUtils::GetCallingLocation(aCx, mFileName, &mLineNo, &mColumn); +} + +nsresult +TimeoutHandler::Call() +{ + return NS_OK; +} + +void +TimeoutHandler::GetLocation(const char** aFileName, uint32_t* aLineNo, + uint32_t* aColumn) +{ + *aFileName = mFileName.get(); + *aLineNo = mLineNo; + *aColumn = mColumn; +} + +NS_IMPL_CYCLE_COLLECTION_0(TimeoutHandler) + +NS_IMPL_CYCLE_COLLECTING_ADDREF(TimeoutHandler) +NS_IMPL_CYCLE_COLLECTING_RELEASE(TimeoutHandler) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TimeoutHandler) + NS_INTERFACE_MAP_ENTRY(nsITimeoutHandler) +NS_INTERFACE_MAP_END + +} // namespace dom +} // namespace mozilla diff --git a/dom/base/TimeoutHandler.h b/dom/base/TimeoutHandler.h new file mode 100644 index 000000000..cb0a0ce94 --- /dev/null +++ b/dom/base/TimeoutHandler.h @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* 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/. */ + +#ifndef mozilla_dom_timeout_handler_h +#define mozilla_dom_timeout_handler_h + +#include "nsCOMPtr.h" +#include "nsISupports.h" +#include "nsITimeoutHandler.h" + +namespace mozilla { +namespace dom { + +/** + * Utility class for implementing nsITimeoutHandlers, designed to be subclassed. + */ +class TimeoutHandler : public nsITimeoutHandler +{ +public: + // TimeoutHandler doesn't actually contain cycles, but subclasses + // probably will. + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_CLASS(TimeoutHandler) + + virtual nsresult Call() override; + virtual void GetLocation(const char** aFileName, uint32_t* aLineNo, + uint32_t* aColumn) override; + virtual void MarkForCC() override {} +protected: + TimeoutHandler() : mFileName(""), mLineNo(0), mColumn(0) {} + explicit TimeoutHandler(JSContext *aCx); + + virtual ~TimeoutHandler() {} +private: + TimeoutHandler(const TimeoutHandler&) = delete; + TimeoutHandler& operator=(const TimeoutHandler&) = delete; + TimeoutHandler& operator=(const TimeoutHandler&&) = delete; + + nsCString mFileName; + uint32_t mLineNo; + uint32_t mColumn; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_timeout_handler_h diff --git a/dom/base/WebSocket.cpp b/dom/base/WebSocket.cpp index d85bae82b..af4b7858b 100644 --- a/dom/base/WebSocket.cpp +++ b/dom/base/WebSocket.cpp @@ -340,7 +340,7 @@ WebSocketImpl::PrintErrorOnConsole(const char *aBundleURI, new PrintErrorOnConsoleRunnable(this, aBundleURI, aError, aFormatStrings, aFormatStringsLen); ErrorResult rv; - runnable->Dispatch(rv); + runnable->Dispatch(Killing, rv); // XXXbz this seems totally broken. We should be propagating this out, but // none of our callers really propagate anything usefully. Come to think of // it, why is this a syncrunnable anyway? Can't this be a fire-and-forget @@ -629,7 +629,7 @@ WebSocketImpl::Disconnect() RefPtr<DisconnectInternalRunnable> runnable = new DisconnectInternalRunnable(this); ErrorResult rv; - runnable->Dispatch(rv); + runnable->Dispatch(Killing, rv); // XXXbz this seems totally broken. We should be propagating this out, but // where to, exactly? rv.SuppressException(); @@ -1293,7 +1293,7 @@ WebSocket::ConstructorCommon(const GlobalObject& aGlobal, new InitRunnable(webSocketImpl, !!aTransportProvider, aUrl, protocolArray, nsDependentCString(file.get()), lineno, column, aRv, &connectionFailed); - runnable->Dispatch(aRv); + runnable->Dispatch(Terminating, aRv); } if (NS_WARN_IF(aRv.Failed())) { @@ -1377,7 +1377,7 @@ WebSocket::ConstructorCommon(const GlobalObject& aGlobal, "not yet implemented"); RefPtr<AsyncOpenRunnable> runnable = new AsyncOpenRunnable(webSocket->mImpl, aRv); - runnable->Dispatch(aRv); + runnable->Dispatch(Terminating, aRv); } if (NS_WARN_IF(aRv.Failed())) { diff --git a/dom/base/moz.build b/dom/base/moz.build index 0fb345d22..77eb01ba6 100755 --- a/dom/base/moz.build +++ b/dom/base/moz.build @@ -217,6 +217,7 @@ EXPORTS.mozilla.dom += [ 'TabGroup.h', 'Text.h', 'Timeout.h', + 'TimeoutHandler.h', 'TreeWalker.h', 'WebKitCSSMatrix.h', 'WebSocket.h', @@ -364,6 +365,7 @@ UNIFIED_SOURCES += [ 'TextInputProcessor.cpp', 'ThirdPartyUtil.cpp', 'Timeout.cpp', + 'TimeoutHandler.cpp', 'TimerClamping.cpp', 'TreeWalker.cpp', 'WebKitCSSMatrix.cpp', @@ -460,11 +462,6 @@ LOCAL_INCLUDES += [ '/xpcom/ds', ] -if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': - LOCAL_INCLUDES += [ - '../system/gonk', - ] - if CONFIG['MOZ_WEBRTC']: LOCAL_INCLUDES += [ '/netwerk/sctp/datachannel', diff --git a/dom/base/nsContentPermissionHelper.cpp b/dom/base/nsContentPermissionHelper.cpp index fd04b1013..c57fc6233 100644 --- a/dom/base/nsContentPermissionHelper.cpp +++ b/dom/base/nsContentPermissionHelper.cpp @@ -5,9 +5,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include <map> -#ifdef MOZ_WIDGET_GONK -#include "GonkPermission.h" -#endif // MOZ_WIDGET_GONK #include "nsCOMPtr.h" #include "nsIDOMElement.h" #include "nsIPrincipal.h" diff --git a/dom/base/nsContentPolicy.cpp b/dom/base/nsContentPolicy.cpp index 337debcea..5511b9086 100644 --- a/dom/base/nsContentPolicy.cpp +++ b/dom/base/nsContentPolicy.cpp @@ -20,6 +20,7 @@ #include "nsIDOMElement.h" #include "nsIDOMNode.h" #include "nsIDOMWindow.h" +#include "nsITabChild.h" #include "nsIContent.h" #include "nsILoadContext.h" #include "nsCOMArray.h" @@ -89,8 +90,9 @@ nsContentPolicy::CheckPolicy(CPMethod policyMethod, { nsCOMPtr<nsIDOMNode> node(do_QueryInterface(requestingContext)); nsCOMPtr<nsIDOMWindow> window(do_QueryInterface(requestingContext)); - NS_ASSERTION(!requestingContext || node || window, - "Context should be a DOM node or a DOM window!"); + nsCOMPtr<nsITabChild> tabChild(do_QueryInterface(requestingContext)); + NS_ASSERTION(!requestingContext || node || window || tabChild, + "Context should be a DOM node, DOM window or a tabChild!"); } #endif diff --git a/dom/base/nsContentPolicyUtils.h b/dom/base/nsContentPolicyUtils.h index ed0544226..600b24c56 100644 --- a/dom/base/nsContentPolicyUtils.h +++ b/dom/base/nsContentPolicyUtils.h @@ -134,6 +134,7 @@ NS_CP_ContentTypeName(uint32_t contentType) CASE_RETURN( TYPE_INTERNAL_IMAGE_FAVICON ); CASE_RETURN( TYPE_INTERNAL_STYLESHEET ); CASE_RETURN( TYPE_INTERNAL_STYLESHEET_PRELOAD ); + CASE_RETURN( TYPE_SAVEAS_DOWNLOAD ); default: return "<Unknown Type>"; } diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index ef87a250e..34c7d23b8 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -281,6 +281,7 @@ bool nsContentUtils::sIsCutCopyAllowed = true; bool nsContentUtils::sIsFrameTimingPrefEnabled = false; bool nsContentUtils::sIsPerformanceTimingEnabled = false; bool nsContentUtils::sIsResourceTimingEnabled = false; +bool nsContentUtils::sIsPerformanceNavigationTimingEnabled = false; bool nsContentUtils::sIsUserTimingLoggingEnabled = false; bool nsContentUtils::sIsExperimentalAutocompleteEnabled = false; bool nsContentUtils::sEncodeDecodeURLHash = false; @@ -571,6 +572,9 @@ nsContentUtils::Init() Preferences::AddBoolVarCache(&sIsResourceTimingEnabled, "dom.enable_resource_timing", true); + Preferences::AddBoolVarCache(&sIsPerformanceNavigationTimingEnabled, + "dom.enable_performance_navigation_timing", true); + Preferences::AddBoolVarCache(&sIsUserTimingLoggingEnabled, "dom.performance.enable_user_timing_logging", false); @@ -5100,7 +5104,7 @@ nsContentUtils::TriggerLink(nsIContent *aContent, nsPresContext *aPresContext, handler->OnLinkClick(aContent, aLinkURI, fileName.IsVoid() ? aTargetSpec.get() : EmptyString().get(), - fileName, nullptr, nullptr, aIsTrusted); + fileName, nullptr, nullptr, aIsTrusted, aContent->NodePrincipal()); } } @@ -9772,9 +9776,13 @@ nsContentUtils::AttemptLargeAllocationLoad(nsIHttpChannel* aChannel) rv = aChannel->GetReferrer(getter_AddRefs(referrer)); NS_ENSURE_SUCCESS(rv, false); + nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo(); + nsCOMPtr<nsIPrincipal> triggeringPrincipal = loadInfo->TriggeringPrincipal(); + // Actually perform the cross process load bool reloadSucceeded = false; - rv = wbc3->ReloadInFreshProcess(docShell, uri, referrer, &reloadSucceeded); + rv = wbc3->ReloadInFreshProcess(docShell, uri, referrer, + triggeringPrincipal, &reloadSucceeded); NS_ENSURE_SUCCESS(rv, false); return reloadSucceeded; diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index 0932f451e..9ae6d2155 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -2033,6 +2033,14 @@ public: } /* + * Returns true if the performance timing APIs are enabled. + */ + static bool IsPerformanceNavigationTimingEnabled() + { + return sIsPerformanceNavigationTimingEnabled; + } + + /* * Returns true if notification should be sent for peformance timing events. */ static bool SendPerformanceTimingNotifications() @@ -2825,6 +2833,7 @@ private: static uint32_t sHandlingInputTimeout; static bool sIsPerformanceTimingEnabled; static bool sIsResourceTimingEnabled; + static bool sIsPerformanceNavigationTimingEnabled; static bool sIsUserTimingLoggingEnabled; static bool sIsFrameTimingPrefEnabled; static bool sIsExperimentalAutocompleteEnabled; diff --git a/dom/base/nsDOMNavigationTiming.cpp b/dom/base/nsDOMNavigationTiming.cpp index 31b2932fb..32ce8a8cb 100644 --- a/dom/base/nsDOMNavigationTiming.cpp +++ b/dom/base/nsDOMNavigationTiming.cpp @@ -15,6 +15,9 @@ #include "nsPrintfCString.h" #include "mozilla/dom/PerformanceNavigation.h" #include "mozilla/TimeStamp.h" +#include "mozilla/Telemetry.h" + +using namespace mozilla; nsDOMNavigationTiming::nsDOMNavigationTiming() { @@ -30,47 +33,36 @@ nsDOMNavigationTiming::Clear() { mNavigationType = TYPE_RESERVED; mNavigationStartHighRes = 0; - mBeforeUnloadStart = 0; - mUnloadStart = 0; - mUnloadEnd = 0; - mLoadEventStart = 0; - mLoadEventEnd = 0; - mDOMLoading = 0; - mDOMInteractive = 0; - mDOMContentLoadedEventStart = 0; - mDOMContentLoadedEventEnd = 0; - mDOMComplete = 0; - - mLoadEventStartSet = false; - mLoadEventEndSet = false; - mDOMLoadingSet = false; - mDOMInteractiveSet = false; - mDOMContentLoadedEventStartSet = false; - mDOMContentLoadedEventEndSet = false; - mDOMCompleteSet = false; + mBeforeUnloadStart = TimeStamp(); + mUnloadStart = TimeStamp(); + mUnloadEnd = TimeStamp(); + mLoadEventStart = TimeStamp(); + mLoadEventEnd = TimeStamp(); + mDOMLoading = TimeStamp(); + mDOMInteractive = TimeStamp(); + mDOMContentLoadedEventStart = TimeStamp(); + mDOMContentLoadedEventEnd = TimeStamp(); + mDOMComplete = TimeStamp(); + mDocShellHasBeenActiveSinceNavigationStart = false; } DOMTimeMilliSec -nsDOMNavigationTiming::TimeStampToDOM(mozilla::TimeStamp aStamp) const +nsDOMNavigationTiming::TimeStampToDOM(TimeStamp aStamp) const { if (aStamp.IsNull()) { return 0; } - mozilla::TimeDuration duration = aStamp - mNavigationStartTimeStamp; - return GetNavigationStart() + static_cast<int64_t>(duration.ToMilliseconds()); -} -DOMTimeMilliSec nsDOMNavigationTiming::DurationFromStart() -{ - return TimeStampToDOM(mozilla::TimeStamp::Now()); + TimeDuration duration = aStamp - mNavigationStart; + return GetNavigationStart() + static_cast<int64_t>(duration.ToMilliseconds()); } void nsDOMNavigationTiming::NotifyNavigationStart(DocShellState aDocShellState) { mNavigationStartHighRes = (double)PR_Now() / PR_USEC_PER_MSEC; - mNavigationStartTimeStamp = mozilla::TimeStamp::Now(); + mNavigationStart = TimeStamp::Now(); mDocShellHasBeenActiveSinceNavigationStart = (aDocShellState == DocShellState::eActive); } @@ -86,7 +78,7 @@ nsDOMNavigationTiming::NotifyFetchStart(nsIURI* aURI, Type aNavigationType) void nsDOMNavigationTiming::NotifyBeforeUnload() { - mBeforeUnloadStart = DurationFromStart(); + mBeforeUnloadStart = TimeStamp::Now(); } void @@ -99,105 +91,107 @@ nsDOMNavigationTiming::NotifyUnloadAccepted(nsIURI* aOldURI) void nsDOMNavigationTiming::NotifyUnloadEventStart() { - mUnloadStart = DurationFromStart(); + mUnloadStart = TimeStamp::Now(); } void nsDOMNavigationTiming::NotifyUnloadEventEnd() { - mUnloadEnd = DurationFromStart(); + mUnloadEnd = TimeStamp::Now(); } void nsDOMNavigationTiming::NotifyLoadEventStart() { - if (!mLoadEventStartSet) { - mLoadEventStart = DurationFromStart(); - mLoadEventStartSet = true; + if (!mLoadEventStart.IsNull()) { + return; } + mLoadEventStart = TimeStamp::Now(); } void nsDOMNavigationTiming::NotifyLoadEventEnd() { - if (!mLoadEventEndSet) { - mLoadEventEnd = DurationFromStart(); - mLoadEventEndSet = true; + if (!mLoadEventEnd.IsNull()) { + return; } + mLoadEventEnd = TimeStamp::Now(); } void -nsDOMNavigationTiming::SetDOMLoadingTimeStamp(nsIURI* aURI, mozilla::TimeStamp aValue) +nsDOMNavigationTiming::SetDOMLoadingTimeStamp(nsIURI* aURI, TimeStamp aValue) { - if (!mDOMLoadingSet) { - mLoadedURI = aURI; - mDOMLoading = TimeStampToDOM(aValue); - mDOMLoadingSet = true; + if (!mDOMLoading.IsNull()) { + return; } + mLoadedURI = aURI; + mDOMLoading = aValue; } void nsDOMNavigationTiming::NotifyDOMLoading(nsIURI* aURI) { - if (!mDOMLoadingSet) { - mLoadedURI = aURI; - mDOMLoading = DurationFromStart(); - mDOMLoadingSet = true; + if (!mDOMLoading.IsNull()) { + return; } + mLoadedURI = aURI; + mDOMLoading = TimeStamp::Now(); } void nsDOMNavigationTiming::NotifyDOMInteractive(nsIURI* aURI) { - if (!mDOMInteractiveSet) { - mLoadedURI = aURI; - mDOMInteractive = DurationFromStart(); - mDOMInteractiveSet = true; + if (!mDOMInteractive.IsNull()) { + return; } + mLoadedURI = aURI; + mDOMInteractive = TimeStamp::Now(); } void nsDOMNavigationTiming::NotifyDOMComplete(nsIURI* aURI) { - if (!mDOMCompleteSet) { - mLoadedURI = aURI; - mDOMComplete = DurationFromStart(); - mDOMCompleteSet = true; + if (!mDOMComplete.IsNull()) { + return; } + mLoadedURI = aURI; + mDOMComplete = TimeStamp::Now(); } void nsDOMNavigationTiming::NotifyDOMContentLoadedStart(nsIURI* aURI) { - if (!mDOMContentLoadedEventStartSet) { - mLoadedURI = aURI; - mDOMContentLoadedEventStart = DurationFromStart(); - mDOMContentLoadedEventStartSet = true; + if (!mDOMContentLoadedEventStart.IsNull()) { + return; } + + mLoadedURI = aURI; + mDOMContentLoadedEventStart = TimeStamp::Now(); } void nsDOMNavigationTiming::NotifyDOMContentLoadedEnd(nsIURI* aURI) { - if (!mDOMContentLoadedEventEndSet) { - mLoadedURI = aURI; - mDOMContentLoadedEventEnd = DurationFromStart(); - mDOMContentLoadedEventEndSet = true; + if (!mDOMContentLoadedEventEnd.IsNull()) { + return; } + + mLoadedURI = aURI; + mDOMContentLoadedEventEnd = TimeStamp::Now(); } void nsDOMNavigationTiming::NotifyNonBlankPaintForRootContentDocument() { MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(!mNavigationStartTimeStamp.IsNull()); + MOZ_ASSERT(!mNavigationStart.IsNull()); - if (!mNonBlankPaintTimeStamp.IsNull()) { + if (!mNonBlankPaint.IsNull()) { return; } - mNonBlankPaintTimeStamp = TimeStamp::Now(); - TimeDuration elapsed = mNonBlankPaintTimeStamp - mNavigationStartTimeStamp; + mNonBlankPaint = TimeStamp::Now(); + TimeDuration elapsed = mNonBlankPaint - mNavigationStart; if (profiler_is_active()) { nsAutoCString spec; @@ -212,8 +206,8 @@ nsDOMNavigationTiming::NotifyNonBlankPaintForRootContentDocument() if (mDocShellHasBeenActiveSinceNavigationStart) { Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_NON_BLANK_PAINT_MS, - mNavigationStartTimeStamp, - mNonBlankPaintTimeStamp); + mNavigationStart, + mNonBlankPaint); } } @@ -224,24 +218,24 @@ nsDOMNavigationTiming::NotifyDocShellStateChanged(DocShellState aDocShellState) (aDocShellState == DocShellState::eActive); } -DOMTimeMilliSec -nsDOMNavigationTiming::GetUnloadEventStart() +mozilla::TimeStamp +nsDOMNavigationTiming::GetUnloadEventStartTimeStamp() const { nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); nsresult rv = ssm->CheckSameOriginURI(mLoadedURI, mUnloadedURI, false); if (NS_SUCCEEDED(rv)) { return mUnloadStart; } - return 0; + return mozilla::TimeStamp(); } -DOMTimeMilliSec -nsDOMNavigationTiming::GetUnloadEventEnd() +mozilla::TimeStamp +nsDOMNavigationTiming::GetUnloadEventEndTimeStamp() const { nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); nsresult rv = ssm->CheckSameOriginURI(mLoadedURI, mUnloadedURI, false); if (NS_SUCCEEDED(rv)) { return mUnloadEnd; } - return 0; + return mozilla::TimeStamp(); } diff --git a/dom/base/nsDOMNavigationTiming.h b/dom/base/nsDOMNavigationTiming.h index 9babece96..3be2527ca 100644 --- a/dom/base/nsDOMNavigationTiming.h +++ b/dom/base/nsDOMNavigationTiming.h @@ -47,38 +47,91 @@ public: mozilla::TimeStamp GetNavigationStartTimeStamp() const { - return mNavigationStartTimeStamp; + return mNavigationStart; + } + + DOMTimeMilliSec GetUnloadEventStart() + { + return TimeStampToDOM(GetUnloadEventStartTimeStamp()); + } + + DOMTimeMilliSec GetUnloadEventEnd() + { + return TimeStampToDOM(GetUnloadEventEndTimeStamp()); } - DOMTimeMilliSec GetUnloadEventStart(); - DOMTimeMilliSec GetUnloadEventEnd(); DOMTimeMilliSec GetDomLoading() const { - return mDOMLoading; + return TimeStampToDOM(mDOMLoading); } DOMTimeMilliSec GetDomInteractive() const { - return mDOMInteractive; + return TimeStampToDOM(mDOMInteractive); } DOMTimeMilliSec GetDomContentLoadedEventStart() const { - return mDOMContentLoadedEventStart; + return TimeStampToDOM(mDOMContentLoadedEventStart); } DOMTimeMilliSec GetDomContentLoadedEventEnd() const { - return mDOMContentLoadedEventEnd; + return TimeStampToDOM(mDOMContentLoadedEventEnd); } DOMTimeMilliSec GetDomComplete() const { - return mDOMComplete; + return TimeStampToDOM(mDOMComplete); } DOMTimeMilliSec GetLoadEventStart() const { - return mLoadEventStart; + return TimeStampToDOM(mLoadEventStart); } DOMTimeMilliSec GetLoadEventEnd() const { - return mLoadEventEnd; + return TimeStampToDOM(mLoadEventEnd); + } + DOMTimeMilliSec GetTimeToNonBlankPaint() const + { + return TimeStampToDOM(mNonBlankPaint); + } + + DOMHighResTimeStamp GetUnloadEventStartHighRes() + { + mozilla::TimeStamp stamp = GetUnloadEventStartTimeStamp(); + if (stamp.IsNull()) { + return 0; + } + return TimeStampToDOMHighRes(stamp); + } + DOMHighResTimeStamp GetUnloadEventEndHighRes() + { + mozilla::TimeStamp stamp = GetUnloadEventEndTimeStamp(); + if (stamp.IsNull()) { + return 0; + } + return TimeStampToDOMHighRes(stamp); + } + DOMHighResTimeStamp GetDomInteractiveHighRes() const + { + return TimeStampToDOMHighRes(mDOMInteractive); + } + DOMHighResTimeStamp GetDomContentLoadedEventStartHighRes() const + { + return TimeStampToDOMHighRes(mDOMContentLoadedEventStart); + } + DOMHighResTimeStamp GetDomContentLoadedEventEndHighRes() const + { + return TimeStampToDOMHighRes(mDOMContentLoadedEventEnd); + } + DOMHighResTimeStamp GetDomCompleteHighRes() const + { + return TimeStampToDOMHighRes(mDOMComplete); + } + DOMHighResTimeStamp GetLoadEventStartHighRes() const + { + return TimeStampToDOMHighRes(mLoadEventStart); + } + DOMHighResTimeStamp GetLoadEventEndHighRes() const + { + return TimeStampToDOMHighRes(mLoadEventEnd); } enum class DocShellState : uint8_t { @@ -108,9 +161,13 @@ public: DOMTimeMilliSec TimeStampToDOM(mozilla::TimeStamp aStamp) const; - inline DOMHighResTimeStamp TimeStampToDOMHighRes(mozilla::TimeStamp aStamp) + inline DOMHighResTimeStamp TimeStampToDOMHighRes(mozilla::TimeStamp aStamp) const { - mozilla::TimeDuration duration = aStamp - mNavigationStartTimeStamp; + MOZ_ASSERT(!aStamp.IsNull(), "The timestamp should not be null"); + if (aStamp.IsNull()) { + return 0; + } + mozilla::TimeDuration duration = aStamp - mNavigationStart; return duration.ToMilliseconds(); } @@ -120,37 +177,29 @@ private: void Clear(); + mozilla::TimeStamp GetUnloadEventStartTimeStamp() const; + mozilla::TimeStamp GetUnloadEventEndTimeStamp() const; + nsCOMPtr<nsIURI> mUnloadedURI; nsCOMPtr<nsIURI> mLoadedURI; Type mNavigationType; DOMHighResTimeStamp mNavigationStartHighRes; - mozilla::TimeStamp mNavigationStartTimeStamp; - mozilla::TimeStamp mNonBlankPaintTimeStamp; - DOMTimeMilliSec DurationFromStart(); - - DOMTimeMilliSec mBeforeUnloadStart; - DOMTimeMilliSec mUnloadStart; - DOMTimeMilliSec mUnloadEnd; - DOMTimeMilliSec mLoadEventStart; - DOMTimeMilliSec mLoadEventEnd; - - DOMTimeMilliSec mDOMLoading; - DOMTimeMilliSec mDOMInteractive; - DOMTimeMilliSec mDOMContentLoadedEventStart; - DOMTimeMilliSec mDOMContentLoadedEventEnd; - DOMTimeMilliSec mDOMComplete; - - // Booleans to keep track of what things we've already been notified - // about. We don't update those once we've been notified about them - // once. - bool mLoadEventStartSet : 1; - bool mLoadEventEndSet : 1; - bool mDOMLoadingSet : 1; - bool mDOMInteractiveSet : 1; - bool mDOMContentLoadedEventStartSet : 1; - bool mDOMContentLoadedEventEndSet : 1; - bool mDOMCompleteSet : 1; + mozilla::TimeStamp mNavigationStart; + mozilla::TimeStamp mNonBlankPaint; + + mozilla::TimeStamp mBeforeUnloadStart; + mozilla::TimeStamp mUnloadStart; + mozilla::TimeStamp mUnloadEnd; + mozilla::TimeStamp mLoadEventStart; + mozilla::TimeStamp mLoadEventEnd; + + mozilla::TimeStamp mDOMLoading; + mozilla::TimeStamp mDOMInteractive; + mozilla::TimeStamp mDOMContentLoadedEventStart; + mozilla::TimeStamp mDOMContentLoadedEventEnd; + mozilla::TimeStamp mDOMComplete; + bool mDocShellHasBeenActiveSinceNavigationStart : 1; }; diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index eaea49b02..8acfd901a 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -2054,10 +2054,17 @@ nsDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup, mFirstChild = content->GetNextSibling(); } mChildren.RemoveChildAt(i); + if (content == mCachedRootElement) { + // Immediately clear mCachedRootElement, now that it's been removed + // from mChildren, so that GetRootElement() will stop returning this + // now-stale value. + mCachedRootElement = nullptr; + } nsNodeUtils::ContentRemoved(this, content, i, previousSibling); content->UnbindFromTree(); } - mCachedRootElement = nullptr; + MOZ_ASSERT(!mCachedRootElement, + "After removing all children, there should be no root elem"); } mInUnlinkOrDeletion = oldVal; @@ -3913,8 +3920,18 @@ nsDocument::RemoveChildAt(uint32_t aIndex, bool aNotify) DestroyElementMaps(); } - doRemoveChildAt(aIndex, aNotify, oldKid, mChildren); + // Preemptively clear mCachedRootElement, since we may be about to remove it + // from our child list, and we don't want to return this maybe-obsolete value + // from any GetRootElement() calls that happen inside of doRemoveChildAt(). + // (NOTE: for this to be useful, doRemoveChildAt() must NOT trigger any + // GetRootElement() calls until after it's removed the child from mChildren. + // Any call before that point would restore this soon-to-be-obsolete cached + // answer, and our clearing here would be fruitless.) mCachedRootElement = nullptr; + doRemoveChildAt(aIndex, aNotify, oldKid, mChildren); + MOZ_ASSERT(mCachedRootElement != oldKid, + "Stale pointer in mCachedRootElement, after we tried to clear it " + "(maybe somebody called GetRootElement() too early?)"); } void @@ -12490,7 +12507,8 @@ nsDocument::ScheduleIntersectionObserverNotification() void nsDocument::NotifyIntersectionObservers() { - for (const auto& observer : mIntersectionObservers) { + nsTArray<RefPtr<DOMIntersectionObserver>> observers(mIntersectionObservers); + for (const auto& observer : observers) { observer->Notify(); } } @@ -12846,3 +12864,19 @@ nsDocument::CheckCustomElementName(const ElementCreationOptions& aOptions, return is; } + +Selection* +nsIDocument::GetSelection(ErrorResult& aRv) +{ + nsCOMPtr<nsPIDOMWindowInner> window = GetInnerWindow(); + if (!window) { + return nullptr; + } + + NS_ASSERTION(window->IsInnerWindow(), "Should have inner window here!"); + if (!window->IsCurrentInnerWindow()) { + return nullptr; + } + + return nsGlobalWindow::Cast(window)->GetSelection(aRv); +} diff --git a/dom/base/nsFrameMessageManager.cpp b/dom/base/nsFrameMessageManager.cpp index 049bc0a1a..6fffd376b 100644 --- a/dom/base/nsFrameMessageManager.cpp +++ b/dom/base/nsFrameMessageManager.cpp @@ -271,10 +271,10 @@ BuildClonedMessageData(typename BlobTraits<Flavor>::ConcreteContentManagerType* ClonedMessageData& aClonedData) { SerializedStructuredCloneBuffer& buffer = aClonedData.data(); - auto iter = aData.Data().Iter(); + auto iter = aData.Data().Start(); size_t size = aData.Data().Size(); bool success; - buffer.data = aData.Data().Borrow<js::SystemAllocPolicy>(iter, size, &success); + buffer.data = aData.Data().Borrow(iter, size, &success); if (NS_WARN_IF(!success)) { return false; } @@ -1286,6 +1286,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget, if (aRetVal) { ErrorResult rv; StructuredCloneData* data = aRetVal->AppendElement(); + data->InitScope(JS::StructuredCloneScope::DifferentProcess); data->Write(cx, rval, rv); if (NS_WARN_IF(rv.Failed())) { aRetVal->RemoveElementAt(aRetVal->Length() - 1); diff --git a/dom/base/nsGkAtomList.h b/dom/base/nsGkAtomList.h index e4ae7ede8..8fefa0e02 100644 --- a/dom/base/nsGkAtomList.h +++ b/dom/base/nsGkAtomList.h @@ -694,6 +694,7 @@ GK_ATOM(onadapterremoved, "onadapterremoved") GK_ATOM(onafterprint, "onafterprint") GK_ATOM(onafterscriptexecute, "onafterscriptexecute") GK_ATOM(onalerting, "onalerting") +GK_ATOM(onanimationcancel, "onanimationcancel") GK_ATOM(onanimationend, "onanimationend") GK_ATOM(onanimationiteration, "onanimationiteration") GK_ATOM(onanimationstart, "onanimationstart") @@ -704,6 +705,7 @@ GK_ATOM(onattributechanged, "onattributechanged") GK_ATOM(onattributereadreq, "onattributereadreq") GK_ATOM(onattributewritereq, "onattributewritereq") GK_ATOM(onaudioprocess, "onaudioprocess") +GK_ATOM(onauxclick, "onauxclick") GK_ATOM(onbeforecopy, "onbeforecopy") GK_ATOM(onbeforecut, "onbeforecut") GK_ATOM(onbeforepaste, "onbeforepaste") @@ -941,6 +943,7 @@ GK_ATOM(ontouchstart, "ontouchstart") GK_ATOM(ontouchend, "ontouchend") GK_ATOM(ontouchmove, "ontouchmove") GK_ATOM(ontouchcancel, "ontouchcancel") +GK_ATOM(ontransitioncancel, "ontransitioncancel") GK_ATOM(ontransitionend, "ontransitionend") GK_ATOM(ontransitionrun, "ontransitionrun") GK_ATOM(ontransitionstart, "ontransitionstart") @@ -2237,6 +2240,7 @@ GK_ATOM(windows_accent_color_applies, "windows-accent-color-applies") GK_ATOM(windows_accent_color_is_dark, "windows-accent-color-is-dark") GK_ATOM(windows_default_theme, "windows-default-theme") GK_ATOM(mac_graphite_theme, "mac-graphite-theme") +GK_ATOM(mac_lion_theme, "mac-lion-theme") GK_ATOM(mac_yosemite_theme, "mac-yosemite-theme") GK_ATOM(windows_compositor, "windows-compositor") GK_ATOM(windows_glass, "windows-glass") @@ -2268,6 +2272,7 @@ GK_ATOM(_moz_windows_accent_color_applies, "-moz-windows-accent-color-applies") GK_ATOM(_moz_windows_accent_color_is_dark, "-moz-windows-accent-color-is-dark") GK_ATOM(_moz_windows_default_theme, "-moz-windows-default-theme") GK_ATOM(_moz_mac_graphite_theme, "-moz-mac-graphite-theme") +GK_ATOM(_moz_mac_lion_theme, "-moz-mac-lion-theme") GK_ATOM(_moz_mac_yosemite_theme, "-moz-mac-yosemite-theme") GK_ATOM(_moz_windows_compositor, "-moz-windows-compositor") GK_ATOM(_moz_windows_classic, "-moz-windows-classic") diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index f784031f6..884ad69ca 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -23,8 +23,9 @@ #include "mozilla/dom/StorageEvent.h" #include "mozilla/dom/StorageEventBinding.h" #include "mozilla/dom/Timeout.h" +#include "mozilla/dom/TimeoutHandler.h" #include "mozilla/IntegerPrintfMacros.h" -#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) +#if defined(MOZ_WIDGET_ANDROID) #include "mozilla/dom/WindowOrientationObserver.h" #endif #include "nsDOMOfflineResourceList.h" @@ -248,10 +249,6 @@ #include "mozilla/dom/SpeechSynthesis.h" #endif -#ifdef MOZ_B2G -#include "nsPISocketTransportService.h" -#endif - // Apple system headers seem to have a check() macro. <sigh> #ifdef check class nsIScriptTimeoutHandler; @@ -552,29 +549,284 @@ DialogValueHolder::Get(JSContext* aCx, JS::Handle<JSObject*> aScope, } } +class IdleRequestExecutor final : public nsIRunnable + , public nsICancelableRunnable + , public nsIIncrementalRunnable +{ +public: + explicit IdleRequestExecutor(nsGlobalWindow* aWindow) + : mDispatched(false) + , mDeadline(TimeStamp::Now()) + , mWindow(aWindow) + { + MOZ_DIAGNOSTIC_ASSERT(mWindow); + MOZ_DIAGNOSTIC_ASSERT(mWindow->IsInnerWindow()); + } + + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(IdleRequestExecutor, nsIRunnable) + + NS_DECL_NSIRUNNABLE + nsresult Cancel() override; + void SetDeadline(TimeStamp aDeadline) override; + + void MaybeDispatch(); +private: + ~IdleRequestExecutor() {} + + bool mDispatched; + TimeStamp mDeadline; + RefPtr<nsGlobalWindow> mWindow; +}; + +NS_IMPL_CYCLE_COLLECTION_CLASS(IdleRequestExecutor) + +NS_IMPL_CYCLE_COLLECTING_ADDREF(IdleRequestExecutor) +NS_IMPL_CYCLE_COLLECTING_RELEASE(IdleRequestExecutor) + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IdleRequestExecutor) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow) +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IdleRequestExecutor) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequestExecutor) + NS_INTERFACE_MAP_ENTRY(nsIRunnable) + NS_INTERFACE_MAP_ENTRY(nsICancelableRunnable) + NS_INTERFACE_MAP_ENTRY(nsIIncrementalRunnable) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRunnable) +NS_INTERFACE_MAP_END + +NS_IMETHODIMP +IdleRequestExecutor::Run() +{ + MOZ_ASSERT(NS_IsMainThread()); + + mDispatched = false; + if (mWindow) { + return mWindow->ExecuteIdleRequest(mDeadline); + } + + return NS_OK; +} + +nsresult +IdleRequestExecutor::Cancel() +{ + MOZ_ASSERT(NS_IsMainThread()); + + mWindow = nullptr; + return NS_OK; +} + void -nsGlobalWindow::PostThrottledIdleCallback() +IdleRequestExecutor::SetDeadline(TimeStamp aDeadline) { - AssertIsOnMainThread(); + MOZ_ASSERT(NS_IsMainThread()); + + if (!mWindow) { + return; + } - if (mThrottledIdleRequestCallbacks.isEmpty()) + mDeadline = aDeadline; +} + +void +IdleRequestExecutor::MaybeDispatch() +{ + // If we've already dispatched the executor we don't want to do it + // again. Also, if we've called IdleRequestExecutor::Cancel mWindow + // will be null, which indicates that we shouldn't dispatch this + // executor either. + if (mDispatched || !mWindow) { return; + } - RefPtr<IdleRequest> request(mThrottledIdleRequestCallbacks.popFirst()); - // ownership transferred from mThrottledIdleRequestCallbacks to - // mIdleRequestCallbacks - mIdleRequestCallbacks.insertBack(request); + mDispatched = true; + RefPtr<IdleRequestExecutor> request = this; NS_IdleDispatchToCurrentThread(request.forget()); } -/* static */ void -nsGlobalWindow::InsertIdleCallbackIntoList(IdleRequest* aRequest, - IdleRequests& aList) +class IdleRequestExecutorTimeoutHandler final : public TimeoutHandler { - aList.insertBack(aRequest); +public: + explicit IdleRequestExecutorTimeoutHandler(IdleRequestExecutor* aExecutor) + : mExecutor(aExecutor) + { + } + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IdleRequestExecutorTimeoutHandler, + TimeoutHandler) + + nsresult Call() override + { + mExecutor->MaybeDispatch(); + return NS_OK; + } +private: + ~IdleRequestExecutorTimeoutHandler() {} + RefPtr<IdleRequestExecutor> mExecutor; +}; + +NS_IMPL_CYCLE_COLLECTION_INHERITED(IdleRequestExecutorTimeoutHandler, TimeoutHandler, mExecutor) + +NS_IMPL_ADDREF_INHERITED(IdleRequestExecutorTimeoutHandler, TimeoutHandler) +NS_IMPL_RELEASE_INHERITED(IdleRequestExecutorTimeoutHandler, TimeoutHandler) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequestExecutorTimeoutHandler) + NS_INTERFACE_MAP_ENTRY(nsITimeoutHandler) +NS_INTERFACE_MAP_END_INHERITING(TimeoutHandler) + +void +nsGlobalWindow::ScheduleIdleRequestDispatch() +{ + AssertIsOnMainThread(); + + if (mIdleRequestCallbacks.isEmpty()) { + if (mIdleRequestExecutor) { + mIdleRequestExecutor->Cancel(); + mIdleRequestExecutor = nullptr; + } + + return; + } + + if (!mIdleRequestExecutor) { + mIdleRequestExecutor = new IdleRequestExecutor(this); + } + + nsPIDOMWindowOuter* outer = GetOuterWindow(); + if (outer && outer->AsOuter()->IsBackground()) { + nsCOMPtr<nsITimeoutHandler> handler = new IdleRequestExecutorTimeoutHandler(mIdleRequestExecutor); + int32_t dummy; + // Set a timeout handler with a timeout of 0 ms to throttle idle + // callback requests coming from a backround window using + // background timeout throttling. + SetTimeoutOrInterval(handler, 0, false, + Timeout::Reason::eIdleCallbackTimeout, &dummy); + return; + } + + mIdleRequestExecutor->MaybeDispatch(); +} + +void +nsGlobalWindow::SuspendIdleRequests() +{ + if (mIdleRequestExecutor) { + mIdleRequestExecutor->Cancel(); + mIdleRequestExecutor = nullptr; + } +} + +void +nsGlobalWindow::ResumeIdleRequests() +{ + MOZ_ASSERT(!mIdleRequestExecutor); + + ScheduleIdleRequestDispatch(); +} + +void +nsGlobalWindow::InsertIdleCallback(IdleRequest* aRequest) +{ + AssertIsOnMainThread(); + mIdleRequestCallbacks.insertBack(aRequest); aRequest->AddRef(); } +void +nsGlobalWindow::RemoveIdleCallback(mozilla::dom::IdleRequest* aRequest) +{ + AssertIsOnMainThread(); + + if (aRequest->HasTimeout()) { + ClearTimeoutOrInterval(aRequest->GetTimeoutHandle(), + Timeout::Reason::eIdleCallbackTimeout); + } + + aRequest->removeFrom(mIdleRequestCallbacks); + aRequest->Release(); +} + +nsresult +nsGlobalWindow::RunIdleRequest(IdleRequest* aRequest, + DOMHighResTimeStamp aDeadline, + bool aDidTimeout) +{ + AssertIsOnMainThread(); + RefPtr<IdleRequest> request(aRequest); + RemoveIdleCallback(request); + return request->IdleRun(AsInner(), aDeadline, aDidTimeout); +} + +nsresult +nsGlobalWindow::ExecuteIdleRequest(TimeStamp aDeadline) +{ + AssertIsOnMainThread(); + RefPtr<IdleRequest> request = mIdleRequestCallbacks.getFirst(); + + if (!request) { + // There are no more idle requests, so stop scheduling idle + // request callbacks. + return NS_OK; + } + + DOMHighResTimeStamp deadline = 0.0; + + if (Performance* perf = GetPerformance()) { + deadline = perf->GetDOMTiming()->TimeStampToDOMHighRes(aDeadline); + } + + nsresult result = RunIdleRequest(request, deadline, false); + + ScheduleIdleRequestDispatch(); + return result; +} + +class IdleRequestTimeoutHandler final : public TimeoutHandler +{ +public: + IdleRequestTimeoutHandler(JSContext* aCx, + IdleRequest* aIdleRequest, + nsPIDOMWindowInner* aWindow) + : TimeoutHandler(aCx) + , mIdleRequest(aIdleRequest) + , mWindow(aWindow) + { + } + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IdleRequestTimeoutHandler, + TimeoutHandler) + + nsresult Call() override + { + return nsGlobalWindow::Cast(mWindow)->RunIdleRequest(mIdleRequest, 0.0, true); + } + +private: + ~IdleRequestTimeoutHandler() {} + + RefPtr<IdleRequest> mIdleRequest; + nsCOMPtr<nsPIDOMWindowInner> mWindow; +}; + +NS_IMPL_CYCLE_COLLECTION_INHERITED(IdleRequestTimeoutHandler, + TimeoutHandler, + mIdleRequest, + mWindow) + +NS_IMPL_ADDREF_INHERITED(IdleRequestTimeoutHandler, TimeoutHandler) +NS_IMPL_RELEASE_INHERITED(IdleRequestTimeoutHandler, TimeoutHandler) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequestTimeoutHandler) + NS_INTERFACE_MAP_ENTRY(nsITimeoutHandler) +NS_INTERFACE_MAP_END_INHERITING(TimeoutHandler) + uint32_t nsGlobalWindow::RequestIdleCallback(JSContext* aCx, IdleRequestCallback& aCallback, @@ -584,33 +836,36 @@ nsGlobalWindow::RequestIdleCallback(JSContext* aCx, MOZ_RELEASE_ASSERT(IsInnerWindow()); AssertIsOnMainThread(); - uint32_t handle = ++mIdleRequestCallbackCounter; + uint32_t handle = mIdleRequestCallbackCounter++; RefPtr<IdleRequest> request = - new IdleRequest(aCx, AsInner(), aCallback, handle); + new IdleRequest(&aCallback, handle); if (aOptions.mTimeout.WasPassed()) { - aError = request->SetTimeout(aOptions.mTimeout.Value()); - if (NS_WARN_IF(aError.Failed())) { + int32_t timeoutHandle; + nsCOMPtr<nsITimeoutHandler> handler(new IdleRequestTimeoutHandler(aCx, request, AsInner())); + + nsresult rv = SetTimeoutOrInterval( + handler, aOptions.mTimeout.Value(), false, + Timeout::Reason::eIdleCallbackTimeout, &timeoutHandle); + + if (NS_WARN_IF(NS_FAILED(rv))) { return 0; } - } - nsGlobalWindow* outer = GetOuterWindowInternal(); - if (outer && outer->AsOuter()->IsBackground()) { - // mThrottledIdleRequestCallbacks now owns request - InsertIdleCallbackIntoList(request, mThrottledIdleRequestCallbacks); - - NS_DelayedDispatchToCurrentThread( - NewRunnableMethod(this, &nsGlobalWindow::PostThrottledIdleCallback), - 10000); - } else { - MOZ_ASSERT(mThrottledIdleRequestCallbacks.isEmpty()); + request->SetTimeoutHandle(timeoutHandle); + } - // mIdleRequestCallbacks now owns request - InsertIdleCallbackIntoList(request, mIdleRequestCallbacks); + // If the list of idle callback requests is not empty it means that + // we've already dispatched the first idle request. If we're + // suspended we should only queue the idle callback and not schedule + // it to run, that will be done in ResumeIdleRequest. + bool needsScheduling = !IsSuspended() && mIdleRequestCallbacks.isEmpty(); + // mIdleRequestCallbacks now owns request + InsertIdleCallback(request); - NS_IdleDispatchToCurrentThread(request.forget()); + if (needsScheduling) { + ScheduleIdleRequestDispatch(); } return handle; @@ -623,7 +878,7 @@ nsGlobalWindow::CancelIdleCallback(uint32_t aHandle) for (IdleRequest* r : mIdleRequestCallbacks) { if (r->Handle() == aHandle) { - r->Cancel(); + RemoveIdleCallback(r); break; } } @@ -632,29 +887,17 @@ nsGlobalWindow::CancelIdleCallback(uint32_t aHandle) void nsGlobalWindow::DisableIdleCallbackRequests() { - while (!mIdleRequestCallbacks.isEmpty()) { - RefPtr<IdleRequest> request = mIdleRequestCallbacks.popFirst(); - request->Cancel(); + if (mIdleRequestExecutor) { + mIdleRequestExecutor->Cancel(); + mIdleRequestExecutor = nullptr; } - while (!mThrottledIdleRequestCallbacks.isEmpty()) { - RefPtr<IdleRequest> request = mThrottledIdleRequestCallbacks.popFirst(); - request->Cancel(); - } -} - -void nsGlobalWindow::UnthrottleIdleCallbackRequests() -{ - AssertIsOnMainThread(); - - while (!mThrottledIdleRequestCallbacks.isEmpty()) { - RefPtr<IdleRequest> request(mThrottledIdleRequestCallbacks.popFirst()); - mIdleRequestCallbacks.insertBack(request); - NS_IdleDispatchToCurrentThread(request.forget()); + while (!mIdleRequestCallbacks.isEmpty()) { + RefPtr<IdleRequest> request = mIdleRequestCallbacks.getFirst(); + RemoveIdleCallback(request); } } - namespace mozilla { namespace dom { extern uint64_t @@ -1306,13 +1549,10 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow) mSerial(0), mIdleCallbackTimeoutCounter(1), mIdleRequestCallbackCounter(1), + mIdleRequestExecutor(nullptr), #ifdef DEBUG mSetOpenerWindowCalled(false), #endif -#ifdef MOZ_B2G - mNetworkUploadObserverEnabled(false), - mNetworkDownloadObserverEnabled(false), -#endif mCleanedUp(false), mDialogAbuseCount(0), mAreDialogsEnabled(true), @@ -1665,11 +1905,6 @@ nsGlobalWindow::CleanUp() os->RemoveObserver(mObserver, "dom-storage2-changed"); } -#ifdef MOZ_B2G - DisableNetworkEvent(eNetworkUpload); - DisableNetworkEvent(eNetworkDownload); -#endif // MOZ_B2G - if (mIdleService) { mIdleService->RemoveIdleObserver(mObserver, MIN_IDLE_NOTIFICATION_TIME_S); } @@ -1713,7 +1948,7 @@ nsGlobalWindow::CleanUp() mSpeechSynthesis = nullptr; #endif -#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) +#if defined(MOZ_WIDGET_ANDROID) mOrientationChangeObserver = nullptr; #endif @@ -1738,9 +1973,6 @@ nsGlobalWindow::CleanUp() mHasGamepad = false; DisableVRUpdates(); mHasVREvents = false; -#ifdef MOZ_B2G - DisableTimeChangeNotifications(); -#endif DisableIdleCallbackRequests(); } else { MOZ_ASSERT(!mHasGamepad); @@ -1844,7 +2076,7 @@ nsGlobalWindow::FreeInnerObjects() mScreen = nullptr; } -#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) +#if defined(MOZ_WIDGET_ANDROID) mOrientationChangeObserver = nullptr; #endif @@ -2033,14 +2265,11 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindow) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWakeLock) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingStorageEvents) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleRequestExecutor) for (IdleRequest* request : tmp->mIdleRequestCallbacks) { cb.NoteNativeChild(request, NS_CYCLE_COLLECTION_PARTICIPANT(IdleRequest)); } - for (IdleRequest* request : tmp->mThrottledIdleRequestCallbacks) { - cb.NoteNativeChild(request, NS_CYCLE_COLLECTION_PARTICIPANT(IdleRequest)); - } - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleObservers) #ifdef MOZ_GAMEPAD @@ -2147,6 +2376,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow) tmp->UnlinkHostObjectURIs(); + NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleRequestExecutor) tmp->DisableIdleCallbackRequests(); NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER @@ -2275,8 +2505,13 @@ nsGlobalWindow::WouldReuseInnerWindow(nsIDocument* aNewDocument) return false; } - NS_ASSERTION(NS_IsAboutBlank(mDoc->GetDocumentURI()), - "How'd this happen?"); +#ifdef DEBUG +{ + nsCOMPtr<nsIURI> uri; + mDoc->GetDocumentURI()->CloneIgnoringRef(getter_AddRefs(uri)); + NS_ASSERTION(NS_IsAboutBlank(uri), "How'd this happen?"); +} +#endif // Great, we're the original document, check for one of the other // conditions. @@ -2878,8 +3113,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument, newInnerWindow->mPerformance = Performance::CreateForMainThread(newInnerWindow->AsInner(), currentInner->mPerformance->GetDOMTiming(), - currentInner->mPerformance->GetChannel(), - currentInner->mPerformance->GetParentPerformance()); + currentInner->mPerformance->GetChannel()); } } @@ -4093,22 +4327,7 @@ nsPIDOMWindowInner::CreatePerformanceObjectIfNeeded() timedChannel = nullptr; } if (timing) { - // If we are dealing with an iframe, we will need the parent's performance - // object (so we can add the iframe as a resource of that page). - Performance* parentPerformance = nullptr; - nsCOMPtr<nsPIDOMWindowOuter> parentWindow = GetScriptableParentOrNull(); - if (parentWindow) { - nsPIDOMWindowInner* parentInnerWindow = nullptr; - if (parentWindow) { - parentInnerWindow = parentWindow->GetCurrentInnerWindow(); - } - if (parentInnerWindow) { - parentPerformance = parentInnerWindow->GetPerformance(); - } - } - mPerformance = - Performance::CreateForMainThread(this, timing, timedChannel, - parentPerformance); + mPerformance = Performance::CreateForMainThread(this, timing, timedChannel); } } @@ -10237,12 +10456,6 @@ void nsGlobalWindow::SetIsBackground(bool aIsBackground) ResetTimersForThrottleReduction(gMinBackgroundTimeoutValue); } - if (!aIsBackground) { - nsGlobalWindow* inner = GetCurrentInnerWindowInternal(); - if (inner) { - inner->UnthrottleIdleCallbackRequests(); - } - } #ifdef MOZ_GAMEPAD if (!aIsBackground) { nsGlobalWindow* inner = GetCurrentInnerWindowInternal(); @@ -11904,27 +12117,6 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic, return NS_OK; } -#ifdef MOZ_B2G - if (!nsCRT::strcmp(aTopic, NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC) || - !nsCRT::strcmp(aTopic, NS_NETWORK_ACTIVITY_BLIP_DOWNLOAD_TOPIC)) { - MOZ_ASSERT(IsInnerWindow()); - if (!AsInner()->IsCurrentInnerWindow()) { - return NS_OK; - } - - RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr); - event->InitEvent( - !nsCRT::strcmp(aTopic, NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC) - ? NETWORK_UPLOAD_EVENT_NAME - : NETWORK_DOWNLOAD_EVENT_NAME, - false, false); - event->SetTrusted(true); - - bool dummy; - return DispatchEvent(event, &dummy); - } -#endif // MOZ_B2G - if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) { MOZ_ASSERT(!NS_strcmp(aData, u"intl.accept_languages")); MOZ_ASSERT(IsInnerWindow()); @@ -12036,6 +12228,8 @@ nsGlobalWindow::Suspend() mozilla::dom::workers::SuspendWorkersForWindow(AsInner()); + SuspendIdleRequests(); + for (Timeout* t = mTimeouts.getFirst(); t; t = t->getNext()) { // Leave the timers with the current time remaining. This will // cause the timers to potentially fire when the window is @@ -12146,6 +12340,8 @@ nsGlobalWindow::Resume() t->AddRef(); } + ResumeIdleRequests(); + // Resume all of the workers for this window. We must do this // after timeouts since workers may have queued events that can trigger // a setTimeout(). @@ -13813,7 +14009,7 @@ nsGlobalWindow::DisableDeviceSensor(uint32_t aType) } } -#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) +#if defined(MOZ_WIDGET_ANDROID) void nsGlobalWindow::EnableOrientationChangeListener() { @@ -14437,7 +14633,9 @@ nsGlobalWindow::NotifyDefaultButtonLoaded(Element& aDefaultButton, return; } LayoutDeviceIntRect buttonRect = - LayoutDeviceIntRect::FromUnknownRect(frame->GetScreenRect()); + LayoutDeviceIntRect::FromAppUnitsToNearest( + frame->GetScreenRectInAppUnits(), + frame->PresContext()->AppUnitsPerDevPixel()); // Get the widget rect in screen coordinates. nsIWidget *widget = GetNearestWidget(); @@ -14706,7 +14904,7 @@ nsGlobalWindow::IsModalContentWindow(JSContext* aCx, JSObject* aGlobal) return xpc::WindowOrNull(aGlobal)->IsModalContentWindow(); } -#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) +#if defined(MOZ_WIDGET_ANDROID) int16_t nsGlobalWindow::Orientation(CallerType aCallerType) const { @@ -14820,80 +15018,6 @@ nsGlobalWindow::GetIsPrerendered() return docShell && docShell->GetIsPrerendered(); } -#ifdef MOZ_B2G -void -nsGlobalWindow::EnableNetworkEvent(EventMessage aEventMessage) -{ - MOZ_ASSERT(IsInnerWindow()); - - nsCOMPtr<nsIPermissionManager> permMgr = - services::GetPermissionManager(); - if (!permMgr) { - NS_ERROR("No PermissionManager available!"); - return; - } - - uint32_t permission = nsIPermissionManager::DENY_ACTION; - permMgr->TestExactPermissionFromPrincipal(GetPrincipal(), "network-events", - &permission); - - if (permission != nsIPermissionManager::ALLOW_ACTION) { - return; - } - - nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService(); - if (!os) { - NS_ERROR("ObserverService should be available!"); - return; - } - - switch (aEventMessage) { - case eNetworkUpload: - if (!mNetworkUploadObserverEnabled) { - mNetworkUploadObserverEnabled = true; - os->AddObserver(mObserver, NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC, false); - } - break; - case eNetworkDownload: - if (!mNetworkDownloadObserverEnabled) { - mNetworkDownloadObserverEnabled = true; - os->AddObserver(mObserver, NS_NETWORK_ACTIVITY_BLIP_DOWNLOAD_TOPIC, false); - } - break; - default: - break; - } -} - -void -nsGlobalWindow::DisableNetworkEvent(EventMessage aEventMessage) -{ - MOZ_ASSERT(IsInnerWindow()); - - nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService(); - if (!os) { - return; - } - - switch (aEventMessage) { - case eNetworkUpload: - if (mNetworkUploadObserverEnabled) { - mNetworkUploadObserverEnabled = false; - os->RemoveObserver(mObserver, NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC); - } - break; - case eNetworkDownload: - if (mNetworkDownloadObserverEnabled) { - mNetworkDownloadObserverEnabled = false; - os->RemoveObserver(mObserver, NS_NETWORK_ACTIVITY_BLIP_DOWNLOAD_TOPIC); - } - break; - default: - break; - } -} -#endif // MOZ_B2G - void nsGlobalWindow::RedefineProperty(JSContext* aCx, const char* aPropName, JS::Handle<JS::Value> aValue, diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index dbceeab74..467bc6796 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -102,6 +102,8 @@ struct nsRect; class nsWindowSizes; +class IdleRequestExecutor; + namespace mozilla { class DOMEventTargetHelper; class ThrottledEventQueue; @@ -118,6 +120,7 @@ class Gamepad; enum class ImageBitmapFormat : uint32_t; class IdleRequest; class IdleRequestCallback; +class IncrementalRunnable; class Location; class MediaQueryList; class MozSelfSupport; @@ -135,7 +138,7 @@ class U2F; class VRDisplay; class VREventObserver; class WakeLock; -#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) +#if defined(MOZ_WIDGET_ANDROID) class WindowOrientationObserver; #endif class Worklet; @@ -628,7 +631,7 @@ public: virtual void EnableDeviceSensor(uint32_t aType) override; virtual void DisableDeviceSensor(uint32_t aType) override; -#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) +#if defined(MOZ_WIDGET_ANDROID) virtual void EnableOrientationChangeListener() override; virtual void DisableOrientationChangeListener() override; #endif @@ -636,13 +639,6 @@ public: virtual void EnableTimeChangeNotifications() override; virtual void DisableTimeChangeNotifications() override; -#ifdef MOZ_B2G - // Inner windows only. - virtual void EnableNetworkEvent(mozilla::EventMessage aEventMessage) override; - virtual void DisableNetworkEvent( - mozilla::EventMessage aEventMessage) override; -#endif // MOZ_B2G - virtual nsresult SetArguments(nsIArray* aArguments) override; void MaybeForgiveSpamCount(); @@ -909,7 +905,7 @@ public: nsIDOMOfflineResourceList* GetApplicationCache(mozilla::ErrorResult& aError); already_AddRefed<nsIDOMOfflineResourceList> GetApplicationCache() override; -#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) +#if defined(MOZ_WIDGET_ANDROID) int16_t Orientation(mozilla::dom::CallerType aCallerType) const; #endif @@ -1097,7 +1093,6 @@ public: mozilla::ErrorResult& aError); void CancelIdleCallback(uint32_t aHandle); - #ifdef MOZ_WEBSPEECH mozilla::dom::SpeechSynthesis* GetSpeechSynthesis(mozilla::ErrorResult& aError); @@ -1762,6 +1757,21 @@ private: mozilla::dom::TabGroup* TabGroupInner(); mozilla::dom::TabGroup* TabGroupOuter(); +public: + void DisableIdleCallbackRequests(); + uint32_t IdleRequestHandle() const { return mIdleRequestCallbackCounter; } + nsresult RunIdleRequest(mozilla::dom::IdleRequest* aRequest, + DOMHighResTimeStamp aDeadline, bool aDidTimeout); + nsresult ExecuteIdleRequest(TimeStamp aDeadline); + void ScheduleIdleRequestDispatch(); + void SuspendIdleRequests(); + void ResumeIdleRequests(); + + typedef mozilla::LinkedList<mozilla::dom::IdleRequest> IdleRequests; + void InsertIdleCallback(mozilla::dom::IdleRequest* aRequest); + + void RemoveIdleCallback(mozilla::dom::IdleRequest* aRequest); + protected: // These members are only used on outer window objects. Make sure // you never set any of these on an inner object! @@ -1912,32 +1922,18 @@ protected: uint32_t mSerial; - void DisableIdleCallbackRequests(); - void UnthrottleIdleCallbackRequests(); - - void PostThrottledIdleCallback(); - - typedef mozilla::LinkedList<mozilla::dom::IdleRequest> IdleRequests; - static void InsertIdleCallbackIntoList(mozilla::dom::IdleRequest* aRequest, - IdleRequests& aList); - // The current idle request callback timeout handle uint32_t mIdleCallbackTimeoutCounter; // The current idle request callback handle uint32_t mIdleRequestCallbackCounter; IdleRequests mIdleRequestCallbacks; - IdleRequests mThrottledIdleRequestCallbacks; + RefPtr<IdleRequestExecutor> mIdleRequestExecutor; #ifdef DEBUG bool mSetOpenerWindowCalled; nsCOMPtr<nsIURI> mLastOpenedURI; #endif -#ifdef MOZ_B2G - bool mNetworkUploadObserverEnabled; - bool mNetworkDownloadObserverEnabled; -#endif // MOZ_B2G - bool mCleanedUp; nsCOMPtr<nsIDOMOfflineResourceList> mApplicationCache; @@ -1975,7 +1971,7 @@ protected: nsTArray<uint32_t> mEnabledSensors; -#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) +#if defined(MOZ_WIDGET_ANDROID) nsAutoPtr<mozilla::dom::WindowOrientationObserver> mOrientationChangeObserver; #endif @@ -2002,6 +1998,7 @@ protected: friend class nsDOMWindowUtils; friend class mozilla::dom::PostMessageEvent; friend class DesktopNotification; + friend class IdleRequestExecutor; static WindowByIdTable* sWindowsById; static bool sWarnedAboutWindowInternal; diff --git a/dom/base/nsIContentPolicy.idl b/dom/base/nsIContentPolicy.idl index a73565a9a..200b97fbc 100644 --- a/dom/base/nsIContentPolicy.idl +++ b/dom/base/nsIContentPolicy.idl @@ -20,7 +20,7 @@ interface nsIPrincipal; * by launching a dialog to prompt the user for something). */ -[scriptable,uuid(caad4f1f-d047-46ac-ae9d-dc598e4fb91b)] +[scriptable,uuid(64a5ae16-6836-475c-9938-4b6cc1eee8fb)] interface nsIContentPolicy : nsIContentPolicyBase { /** diff --git a/dom/base/nsIContentPolicyBase.idl b/dom/base/nsIContentPolicyBase.idl index 884e3d96d..908e562a8 100644 --- a/dom/base/nsIContentPolicyBase.idl +++ b/dom/base/nsIContentPolicyBase.idl @@ -24,7 +24,7 @@ typedef unsigned long nsContentPolicyType; * by launching a dialog to prompt the user for something). */ -[scriptable,uuid(17418187-d86f-48dd-92d1-238838df0a4e)] +[scriptable,uuid(d6ab1d11-8e24-4db4-8582-c40a78281737)] interface nsIContentPolicyBase : nsISupports { /** @@ -329,11 +329,17 @@ interface nsIContentPolicyBase : nsISupports */ const nsContentPolicyType TYPE_INTERNAL_IMAGE_FAVICON = 41; + /** + * Indicates an save-as link download from the front-end code. + */ + const nsContentPolicyType TYPE_SAVEAS_DOWNLOAD = 42; + /* When adding new content types, please update nsContentBlocker, - * NS_CP_ContentTypeName, nsCSPContext, all nsIContentPolicy - * implementations, the static_assert in dom/cache/DBSchema.cpp, - * and other things that are not listed here that are related to - * nsIContentPolicy. */ + * NS_CP_ContentTypeName, nsCSPContext, CSP_ContentTypeToDirective, + * DoContentSecurityChecks, all nsIContentPolicy implementations, the + * static_assert in dom/cache/DBSchema.cpp, nsPermissionManager.cpp, + * and other things that are not listed here that are related + * to nsIContentPolicy. */ ////////////////////////////////////////////////////////////////////// diff --git a/dom/base/nsIDocument.h b/dom/base/nsIDocument.h index 8f35e9ba5..7a73fae71 100644 --- a/dom/base/nsIDocument.h +++ b/dom/base/nsIDocument.h @@ -18,11 +18,11 @@ #include "nsINode.h" // for base class #include "nsIScriptGlobalObject.h" // for member (in nsCOMPtr) #include "nsIServiceManager.h" +#include "nsIURI.h" // for use in inline functions #include "nsIUUIDGenerator.h" #include "nsPIDOMWindow.h" // for use in inline functions #include "nsPropertyTable.h" // for member -#include "nsDataHashtable.h" // for member -#include "nsURIHashKey.h" // for member +#include "nsTHashtable.h" // for member #include "mozilla/net/ReferrerPolicy.h" // for member #include "nsWeakReference.h" #include "mozilla/UseCounter.h" @@ -151,6 +151,7 @@ class NodeIterator; enum class OrientationType : uint32_t; class ProcessingInstruction; class Promise; +class Selection; class StyleSheetList; class SVGDocument; class SVGSVGElement; @@ -181,13 +182,6 @@ enum DocumentFlavor { DocumentFlavorPlain, // Just a Document }; -// Enum for HSTS priming states -enum class HSTSPrimingState { - eNO_HSTS_PRIMING = 0, // don't do HSTS Priming - eHSTS_PRIMING_ALLOW = 1, // if HSTS priming fails, allow the load to proceed - eHSTS_PRIMING_BLOCK = 2 // if HSTS priming fails, block the load -}; - // Document states // RTL locale: specific to the XUL localedir attribute @@ -405,34 +399,6 @@ public: } /** - * Check to see if a subresource we want to load requires HSTS priming - * to be done. - */ - HSTSPrimingState GetHSTSPrimingStateForLocation(nsIURI* aContentLocation) const - { - HSTSPrimingState state; - if (mHSTSPrimingURIList.Get(aContentLocation, &state)) { - return state; - } - return HSTSPrimingState::eNO_HSTS_PRIMING; - } - - /** - * Add a subresource to the HSTS priming list. If this URI is - * not in the HSTS cache, it will trigger an HSTS priming request - * when we try to load it. - */ - void AddHSTSPrimingLocation(nsIURI* aContentLocation, HSTSPrimingState aState) - { - mHSTSPrimingURIList.Put(aContentLocation, aState); - } - - void ClearHSTSPrimingLocation(nsIURI* aContentLocation) - { - mHSTSPrimingURIList.Remove(aContentLocation); - } - - /** * Set the principal responsible for this document. */ virtual void SetPrincipal(nsIPrincipal *aPrincipal) = 0; @@ -898,6 +864,8 @@ public: */ Element* GetRootElement() const; + mozilla::dom::Selection* GetSelection(mozilla::ErrorResult& aRv); + /** * Retrieve information about the viewport as a data structure. * This will return information in the viewport META data section @@ -2984,11 +2952,6 @@ protected: bool mUpgradeInsecureRequests; bool mUpgradeInsecurePreloads; - // if nsMixedContentBlocker requires sending an HSTS priming request, - // temporarily store that in the document so that it can be propogated to the - // LoadInfo and eventually the HTTP Channel - nsDataHashtable<nsURIHashKey, HSTSPrimingState> mHSTSPrimingURIList; - mozilla::WeakPtr<nsDocShell> mDocumentContainer; nsCString mCharacterSet; diff --git a/dom/base/nsINode.cpp b/dom/base/nsINode.cpp index 3a649a61d..09e848710 100644 --- a/dom/base/nsINode.cpp +++ b/dom/base/nsINode.cpp @@ -1777,8 +1777,8 @@ nsINode::Before(const Sequence<OwningNodeOrString>& aNodes, nsCOMPtr<nsINode> viablePreviousSibling = FindViablePreviousSibling(*this, aNodes); - nsCOMPtr<nsINode> node = - ConvertNodesOrStringsIntoNode(aNodes, OwnerDoc(), aRv); + nsCOMPtr<nsIDocument> doc = OwnerDoc(); + nsCOMPtr<nsINode> node = ConvertNodesOrStringsIntoNode(aNodes, doc, aRv); if (aRv.Failed()) { return; } @@ -1800,8 +1800,8 @@ nsINode::After(const Sequence<OwningNodeOrString>& aNodes, nsCOMPtr<nsINode> viableNextSibling = FindViableNextSibling(*this, aNodes); - nsCOMPtr<nsINode> node = - ConvertNodesOrStringsIntoNode(aNodes, OwnerDoc(), aRv); + nsCOMPtr<nsIDocument> doc = OwnerDoc(); + nsCOMPtr<nsINode> node = ConvertNodesOrStringsIntoNode(aNodes, doc, aRv); if (aRv.Failed()) { return; } @@ -1820,8 +1820,8 @@ nsINode::ReplaceWith(const Sequence<OwningNodeOrString>& aNodes, nsCOMPtr<nsINode> viableNextSibling = FindViableNextSibling(*this, aNodes); - nsCOMPtr<nsINode> node = - ConvertNodesOrStringsIntoNode(aNodes, OwnerDoc(), aRv); + nsCOMPtr<nsIDocument> doc = OwnerDoc(); + nsCOMPtr<nsINode> node = ConvertNodesOrStringsIntoNode(aNodes, doc, aRv); if (aRv.Failed()) { return; } @@ -1880,8 +1880,8 @@ void nsINode::Prepend(const Sequence<OwningNodeOrString>& aNodes, ErrorResult& aRv) { - nsCOMPtr<nsINode> node = - ConvertNodesOrStringsIntoNode(aNodes, OwnerDoc(), aRv); + nsCOMPtr<nsIDocument> doc = OwnerDoc(); + nsCOMPtr<nsINode> node = ConvertNodesOrStringsIntoNode(aNodes, doc, aRv); if (aRv.Failed()) { return; } @@ -1894,8 +1894,8 @@ void nsINode::Append(const Sequence<OwningNodeOrString>& aNodes, ErrorResult& aRv) { - nsCOMPtr<nsINode> node = - ConvertNodesOrStringsIntoNode(aNodes, OwnerDoc(), aRv); + nsCOMPtr<nsIDocument> doc = OwnerDoc(); + nsCOMPtr<nsINode> node = ConvertNodesOrStringsIntoNode(aNodes, doc, aRv); if (aRv.Failed()) { return; } @@ -1907,6 +1907,10 @@ void nsINode::doRemoveChildAt(uint32_t aIndex, bool aNotify, nsIContent* aKid, nsAttrAndChildArray& aChildArray) { + // NOTE: This function must not trigger any calls to + // nsIDocument::GetRootElement() calls until *after* it has removed aKid from + // aChildArray. Any calls before then could potentially restore a stale + // value for our cached root element, per note in nsDocument::RemoveChildAt(). NS_PRECONDITION(aKid && aKid->GetParentNode() == this && aKid == GetChildAt(aIndex) && IndexOf(aKid) == (int32_t)aIndex, "Bogus aKid"); diff --git a/dom/base/nsISelectionPrivate.idl b/dom/base/nsISelectionPrivate.idl index 68412885e..049873b28 100644 --- a/dom/base/nsISelectionPrivate.idl +++ b/dom/base/nsISelectionPrivate.idl @@ -29,7 +29,7 @@ native nsDirection(nsDirection); native ScrollAxis(nsIPresShell::ScrollAxis); [scriptable, builtinclass, uuid(0c9f4f74-ee7e-4fe9-be6b-0ba856368178)] -interface nsISelectionPrivate : nsISelection +interface nsISelectionPrivate : nsISupports { const short ENDOFPRECEDINGLINE=0; const short STARTOFNEXTLINE=1; diff --git a/dom/base/nsISimpleContentPolicy.idl b/dom/base/nsISimpleContentPolicy.idl index 493aee1a5..dc0474736 100644 --- a/dom/base/nsISimpleContentPolicy.idl +++ b/dom/base/nsISimpleContentPolicy.idl @@ -28,7 +28,7 @@ interface nsIDOMElement; * by launching a dialog to prompt the user for something). */ -[scriptable,uuid(b9df71e3-a9b3-4706-b2d5-e6c0d3d68ec7)] +[scriptable,uuid(1553a476-8a14-410b-8ecc-47f48e937392)] interface nsISimpleContentPolicy : nsIContentPolicyBase { /** diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 576f3052a..3be1a6d2f 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -1006,110 +1006,6 @@ nsJSContext::AddSupportsPrimitiveTojsvals(nsISupports *aArg, JS::Value *aArgv) return NS_OK; } -#ifdef MOZ_JPROF - -#include <signal.h> - -inline bool -IsJProfAction(struct sigaction *action) -{ - return (action->sa_sigaction && - (action->sa_flags & (SA_RESTART | SA_SIGINFO)) == (SA_RESTART | SA_SIGINFO)); -} - -void NS_JProfStartProfiling(); -void NS_JProfStopProfiling(); -void NS_JProfClearCircular(); - -static bool -JProfStartProfilingJS(JSContext *cx, unsigned argc, JS::Value *vp) -{ - NS_JProfStartProfiling(); - return true; -} - -void NS_JProfStartProfiling() -{ - // Figure out whether we're dealing with SIGPROF, SIGALRM, or - // SIGPOLL profiling (SIGALRM for JP_REALTIME, SIGPOLL for - // JP_RTC_HZ) - struct sigaction action; - - // Must check ALRM before PROF since both are enabled for real-time - sigaction(SIGALRM, nullptr, &action); - //printf("SIGALRM: %p, flags = %x\n",action.sa_sigaction,action.sa_flags); - if (IsJProfAction(&action)) { - //printf("Beginning real-time jprof profiling.\n"); - raise(SIGALRM); - return; - } - - sigaction(SIGPROF, nullptr, &action); - //printf("SIGPROF: %p, flags = %x\n",action.sa_sigaction,action.sa_flags); - if (IsJProfAction(&action)) { - //printf("Beginning process-time jprof profiling.\n"); - raise(SIGPROF); - return; - } - - sigaction(SIGPOLL, nullptr, &action); - //printf("SIGPOLL: %p, flags = %x\n",action.sa_sigaction,action.sa_flags); - if (IsJProfAction(&action)) { - //printf("Beginning rtc-based jprof profiling.\n"); - raise(SIGPOLL); - return; - } - - printf("Could not start jprof-profiling since JPROF_FLAGS was not set.\n"); -} - -static bool -JProfStopProfilingJS(JSContext *cx, unsigned argc, JS::Value *vp) -{ - NS_JProfStopProfiling(); - return true; -} - -void -NS_JProfStopProfiling() -{ - raise(SIGUSR1); - //printf("Stopped jprof profiling.\n"); -} - -static bool -JProfClearCircularJS(JSContext *cx, unsigned argc, JS::Value *vp) -{ - NS_JProfClearCircular(); - return true; -} - -void -NS_JProfClearCircular() -{ - raise(SIGUSR2); - //printf("cleared jprof buffer\n"); -} - -static bool -JProfSaveCircularJS(JSContext *cx, unsigned argc, JS::Value *vp) -{ - // Not ideal... - NS_JProfStopProfiling(); - NS_JProfStartProfiling(); - return true; -} - -static const JSFunctionSpec JProfFunctions[] = { - JS_FS("JProfStartProfiling", JProfStartProfilingJS, 0, 0), - JS_FS("JProfStopProfiling", JProfStopProfilingJS, 0, 0), - JS_FS("JProfClearCircular", JProfClearCircularJS, 0, 0), - JS_FS("JProfSaveCircular", JProfSaveCircularJS, 0, 0), - JS_FS_END -}; - -#endif /* defined(MOZ_JPROF) */ - nsresult nsJSContext::InitClasses(JS::Handle<JSObject*> aGlobalObj) { @@ -1121,11 +1017,6 @@ nsJSContext::InitClasses(JS::Handle<JSObject*> aGlobalObj) // Attempt to initialize profiling functions ::JS_DefineProfilingFunctions(cx, aGlobalObj); -#ifdef MOZ_JPROF - // Attempt to initialize JProf functions - ::JS_DefineFunctions(cx, aGlobalObj, JProfFunctions); -#endif - return NS_OK; } diff --git a/dom/base/nsNodeUtils.cpp b/dom/base/nsNodeUtils.cpp index 69a9414fe..ecea95dc1 100644 --- a/dom/base/nsNodeUtils.cpp +++ b/dom/base/nsNodeUtils.cpp @@ -297,15 +297,6 @@ nsNodeUtils::LastRelease(nsINode* aNode) NodeWillBeDestroyed, (aNode)); } - if (aNode->IsElement()) { - Element* elem = aNode->AsElement(); - FragmentOrElement::nsDOMSlots* domSlots = - static_cast<FragmentOrElement::nsDOMSlots*>(slots); - for (auto& reg : domSlots->mRegisteredIntersectionObservers) { - reg.observer->UnlinkTarget(*elem); - } - } - delete slots; aNode->mSlots = nullptr; } diff --git a/dom/base/nsPIDOMWindow.h b/dom/base/nsPIDOMWindow.h index 45823057a..47affbb06 100644 --- a/dom/base/nsPIDOMWindow.h +++ b/dom/base/nsPIDOMWindow.h @@ -444,7 +444,7 @@ public: */ virtual void DisableDeviceSensor(uint32_t aType) = 0; -#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) +#if defined(MOZ_WIDGET_ANDROID) virtual void EnableOrientationChangeListener() = 0; virtual void DisableOrientationChangeListener() = 0; #endif @@ -452,24 +452,6 @@ public: virtual void EnableTimeChangeNotifications() = 0; virtual void DisableTimeChangeNotifications() = 0; -#ifdef MOZ_B2G - /** - * Tell the window that it should start to listen to the network event of the - * given aType. - * - * Inner windows only. - */ - virtual void EnableNetworkEvent(mozilla::EventMessage aEventMessage) = 0; - - /** - * Tell the window that it should stop to listen to the network event of the - * given aType. - * - * Inner windows only. - */ - virtual void DisableNetworkEvent(mozilla::EventMessage aEventMessage) = 0; -#endif // MOZ_B2G - /** * Tell this window that there is an observer for gamepad input * diff --git a/dom/base/nsStructuredCloneContainer.cpp b/dom/base/nsStructuredCloneContainer.cpp index 8c2cdc091..ea2d38bc8 100644 --- a/dom/base/nsStructuredCloneContainer.cpp +++ b/dom/base/nsStructuredCloneContainer.cpp @@ -137,7 +137,7 @@ nsStructuredCloneContainer::GetDataAsBase64(nsAString &aOut) return NS_ERROR_FAILURE; } - auto iter = Data().Iter(); + auto iter = Data().Start(); size_t size = Data().Size(); nsAutoCString binaryData; binaryData.SetLength(size); diff --git a/dom/base/test/bug704320.sjs b/dom/base/test/bug704320.sjs index dff77f4b3..e0f549533 100644 --- a/dom/base/test/bug704320.sjs +++ b/dom/base/test/bug704320.sjs @@ -194,12 +194,6 @@ function createPolicyTest(policy, optionalEarlierPolicy) { } function handleRequest(request, response) { - if (request.method == 'HEAD') { - // respond to a HEAD request with a 418 so that we can easily distinguish - // HSTS priming responses and ignore them - response.setStatusLine('1.1', 418, "I'm a teapot"); - return; - } var sharedKey = 'bug704320.sjs'; var params = request.queryString.split('&'); var action = params[0].split('=')[1]; diff --git a/dom/base/test/file_ipc_messagemanager_blob.html b/dom/base/test/file_ipc_messagemanager_blob.html new file mode 100644 index 000000000..dbdd64a34 --- /dev/null +++ b/dom/base/test/file_ipc_messagemanager_blob.html @@ -0,0 +1 @@ +<!DOCTYPE HTML><html><body></body></html> diff --git a/dom/base/test/file_simplecontentpolicy.js b/dom/base/test/file_simplecontentpolicy.js index 1f9606c49..2727b9530 100644 --- a/dom/base/test/file_simplecontentpolicy.js +++ b/dom/base/test/file_simplecontentpolicy.js @@ -39,7 +39,6 @@ var policy = { { // Remember last content type seen for the test url if (contentLocation.spec.endsWith(urlSuffix)) { - assert.ok(frame === browserElement, "correct <browser> element"); sendAsyncMessage("shouldLoad", {contentType: contentType, isTopLevel: isTopLevel}); return Ci.nsIContentPolicy.REJECT_REQUEST; } diff --git a/dom/base/test/mochitest.ini b/dom/base/test/mochitest.ini index ddfd57443..b3b804ce4 100644 --- a/dom/base/test/mochitest.ini +++ b/dom/base/test/mochitest.ini @@ -676,6 +676,7 @@ skip-if = (toolkit == 'android') # Android: Bug 775227 [test_intersectionobservers.html] skip-if = true # Track Bug 1320704 [test_ipc_messagemanager_blob.html] +support-files = file_ipc_messagemanager_blob.html [test_link_prefetch.html] skip-if = !e10s # Track Bug 1281415 [test_link_stylesheet.html] diff --git a/dom/base/test/referrerHelper.js b/dom/base/test/referrerHelper.js index 207bf5f15..01a22829c 100644 --- a/dom/base/test/referrerHelper.js +++ b/dom/base/test/referrerHelper.js @@ -25,9 +25,6 @@ function doXHR(url, onSuccess, onFail) { xhr.onload = function () { if (xhr.status == 200) { onSuccess(xhr); - } else if (xhr.status == 418) { - // Ignore HSTS priming responses - return; } else { onFail(xhr); } diff --git a/dom/base/test/test_intersectionobservers.html b/dom/base/test/test_intersectionobservers.html index e7875e3af..10e3d7712 100644 --- a/dom/base/test/test_intersectionobservers.html +++ b/dom/base/test/test_intersectionobservers.html @@ -325,7 +325,7 @@ limitations under the License. }); - it('does not trigger if target does not intersect when observing begins', + it('does trigger if target does not intersect when observing begins', function(done) { var spy = sinon.spy(); @@ -334,7 +334,7 @@ limitations under the License. targetEl2.style.top = '-40px'; io.observe(targetEl2); callDelayed(function() { - expect(spy.callCount).to.be(0); + expect(spy.callCount).to.be(1); done(); }, ASYNC_TIMEOUT); }); @@ -528,7 +528,7 @@ limitations under the License. spy.waitForNotification(function() { expect(spy.callCount).to.be(1); var records = sortRecords(spy.lastCall.args[0]); - expect(records.length).to.be(2); + expect(records.length).to.be(3); expect(records[0].target).to.be(targetEl1); expect(records[0].intersectionRatio).to.be(0.25); expect(records[1].target).to.be(targetEl2); @@ -636,10 +636,10 @@ limitations under the License. expect(records.length).to.be(3); expect(records[0].target).to.be(targetEl1); expect(records[0].intersectionRatio).to.be(0.5); - expect(records[1].target).to.be(targetEl3); - expect(records[1].intersectionRatio).to.be(0.5); - expect(records[2].target).to.be(targetEl4); + expect(records[2].target).to.be(targetEl3); expect(records[2].intersectionRatio).to.be(0.5); + expect(records[3].target).to.be(targetEl4); + expect(records[3].intersectionRatio).to.be(0.5); io.disconnect(); done(); }, {root: rootEl, rootMargin: '-10px 10%'}); @@ -652,11 +652,11 @@ limitations under the License. function(done) { io = new IntersectionObserver(function(records) { records = sortRecords(records); - expect(records.length).to.be(2); + expect(records.length).to.be(4); expect(records[0].target).to.be(targetEl1); expect(records[0].intersectionRatio).to.be(0.5); - expect(records[1].target).to.be(targetEl4); - expect(records[1].intersectionRatio).to.be(0.5); + expect(records[3].target).to.be(targetEl4); + expect(records[3].intersectionRatio).to.be(0.5); io.disconnect(); done(); }, {root: rootEl, rootMargin: '-5% -2.5% 0px'}); @@ -669,13 +669,13 @@ limitations under the License. function(done) { io = new IntersectionObserver(function(records) { records = sortRecords(records); - expect(records.length).to.be(3); + expect(records.length).to.be(4); expect(records[0].target).to.be(targetEl1); expect(records[0].intersectionRatio).to.be(0.5); expect(records[1].target).to.be(targetEl2); expect(records[1].intersectionRatio).to.be(0.5); - expect(records[2].target).to.be(targetEl4); - expect(records[2].intersectionRatio).to.be(0.25); + expect(records[3].target).to.be(targetEl4); + expect(records[3].intersectionRatio).to.be(0.25); io.disconnect(); done(); }, {root: rootEl, rootMargin: '5% -2.5% -10px -190px'}); @@ -705,9 +705,9 @@ limitations under the License. spy.waitForNotification(function() { expect(spy.callCount).to.be(1); var records = sortRecords(spy.lastCall.args[0]); - expect(records.length).to.be(1); - expect(records[0].intersectionRatio).to.be(0); - expect(records[0].target).to.be(targetEl2); + expect(records.length).to.be(2); + expect(records[1].intersectionRatio).to.be(0); + expect(records[1].target).to.be(targetEl2); done(); }, ASYNC_TIMEOUT); }, @@ -797,14 +797,14 @@ limitations under the License. function(done) { document.getElementById('fixtures').appendChild(rootEl); callDelayed(function() { - expect(spy.callCount).to.be(0); + expect(spy.callCount).to.be(1); done(); }, ASYNC_TIMEOUT); }, function(done) { parentEl.insertBefore(targetEl1, targetEl2); spy.waitForNotification(function() { - expect(spy.callCount).to.be(1); + expect(spy.callCount).to.be(2); var records = sortRecords(spy.lastCall.args[0]); expect(records.length).to.be(1); expect(records[0].intersectionRatio).to.be(1); @@ -815,7 +815,7 @@ limitations under the License. function(done) { grandParentEl.parentNode.removeChild(grandParentEl); spy.waitForNotification(function() { - expect(spy.callCount).to.be(2); + expect(spy.callCount).to.be(3); var records = sortRecords(spy.lastCall.args[0]); expect(records.length).to.be(1); expect(records[0].intersectionRatio).to.be(0); @@ -826,7 +826,7 @@ limitations under the License. function(done) { rootEl.appendChild(targetEl1); spy.waitForNotification(function() { - expect(spy.callCount).to.be(3); + expect(spy.callCount).to.be(4); var records = sortRecords(spy.lastCall.args[0]); expect(records.length).to.be(1); expect(records[0].intersectionRatio).to.be(1); @@ -837,7 +837,7 @@ limitations under the License. function(done) { rootEl.parentNode.removeChild(rootEl); spy.waitForNotification(function() { - expect(spy.callCount).to.be(4); + expect(spy.callCount).to.be(5); var records = sortRecords(spy.lastCall.args[0]); expect(records.length).to.be(1); expect(records[0].intersectionRatio).to.be(0); @@ -867,8 +867,14 @@ limitations under the License. targetEl1.style.top = '220px'; targetEl1.style.left = '220px'; + + var callCount = 0; io = new IntersectionObserver(function(records) { + callCount++; + if (callCount <= 1) { + return; + } expect(records.length).to.be(1); expect(records[0].intersectionRatio).to.be(1); done(); @@ -891,6 +897,19 @@ limitations under the License. var win = window.open("intersectionobserver_window.html"); }); + it('triggers only once if observed multiple times (and does not crash when collected)', function(done) { + var spy = sinon.spy(); + io = new IntersectionObserver(spy, {root: rootEl}); + io.observe(targetEl1); + io.observe(targetEl1); + io.observe(targetEl1); + + callDelayed(function () { + expect(spy.callCount).to.be(1); + done(); + }, ASYNC_TIMEOUT); + }); + }); describe('observe subframe', function () { diff --git a/dom/base/test/test_ipc_messagemanager_blob.html b/dom/base/test/test_ipc_messagemanager_blob.html index 74eab2945..77d6c767f 100644 --- a/dom/base/test/test_ipc_messagemanager_blob.html +++ b/dom/base/test/test_ipc_messagemanager_blob.html @@ -14,8 +14,7 @@ SimpleTest.waitForExplicitFinish(); - const childFrameURL = - "data:text/html,<!DOCTYPE HTML><html><body></body></html>"; + const childFrameURL = "file_ipc_messagemanager_blob.html"; function childFrameScript() { "use strict"; diff --git a/dom/base/test/test_x-frame-options.html b/dom/base/test/test_x-frame-options.html index 8e24d8a78..a0c7acdc3 100644 --- a/dom/base/test/test_x-frame-options.html +++ b/dom/base/test/test_x-frame-options.html @@ -147,7 +147,11 @@ var testFrameInDataURI = function() { SimpleTest.waitForExplicitFinish(); // load the test harness -document.getElementById("harness").src = "file_x-frame-options_main.html"; +SpecialPowers.pushPrefEnv({ + "set": [["security.data_uri.block_toplevel_data_uri_navigations", false],] +}, function() { + document.getElementById("harness").src = "file_x-frame-options_main.html"; +}); </script> </pre> |