summaryrefslogtreecommitdiffstats
path: root/dom/base
diff options
context:
space:
mode:
Diffstat (limited to 'dom/base')
-rw-r--r--dom/base/Element.cpp29
-rw-r--r--dom/base/Element.h18
-rwxr-xr-x[-rw-r--r--]dom/base/File.cpp3
-rw-r--r--dom/base/FileReader.cpp4
-rw-r--r--dom/base/FragmentOrElement.cpp8
-rw-r--r--dom/base/FragmentOrElement.h6
-rw-r--r--dom/base/IdleRequest.cpp119
-rw-r--r--dom/base/IdleRequest.h40
-rw-r--r--dom/base/Location.cpp21
-rwxr-xr-x[-rw-r--r--]dom/base/MultipartBlobImpl.cpp4
-rw-r--r--dom/base/Navigator.cpp18
-rw-r--r--dom/base/Navigator.h4
-rw-r--r--dom/base/Timeout.h8
-rw-r--r--dom/base/TimeoutHandler.cpp43
-rw-r--r--dom/base/TimeoutHandler.h50
-rwxr-xr-xdom/base/TimerClamping.cpp35
-rwxr-xr-xdom/base/TimerClamping.h22
-rwxr-xr-x[-rw-r--r--]dom/base/moz.build8
-rw-r--r--dom/base/nsContentList.cpp143
-rw-r--r--dom/base/nsContentList.h40
-rw-r--r--dom/base/nsContentListDeclarations.h8
-rw-r--r--dom/base/nsContentPolicy.cpp6
-rw-r--r--dom/base/nsContentSink.cpp5
-rw-r--r--dom/base/nsContentUtils.cpp38
-rw-r--r--dom/base/nsContentUtils.h29
-rw-r--r--dom/base/nsDOMNavigationTiming.cpp138
-rw-r--r--dom/base/nsDOMNavigationTiming.h125
-rw-r--r--dom/base/nsDocument.cpp51
-rw-r--r--dom/base/nsDocument.h3
-rw-r--r--dom/base/nsDocumentEncoder.cpp2
-rw-r--r--dom/base/nsFrameMessageManager.cpp4
-rw-r--r--dom/base/nsGkAtomList.h7
-rw-r--r--dom/base/nsGlobalWindow.cpp392
-rw-r--r--dom/base/nsGlobalWindow.h45
-rw-r--r--dom/base/nsIContent.h19
-rw-r--r--dom/base/nsIDocument.h31
-rw-r--r--dom/base/nsINode.cpp4
-rw-r--r--dom/base/nsPluginArray.cpp18
-rw-r--r--dom/base/nsRange.cpp2
-rw-r--r--dom/base/nsTreeSanitizer.cpp2
-rwxr-xr-x[-rw-r--r--]dom/base/nsXHTMLContentSerializer.cpp2
-rw-r--r--dom/base/test/mochitest.ini1
-rw-r--r--dom/base/test/test_bug1375050.html33
-rw-r--r--dom/base/test/test_bug403852.html7
-rw-r--r--dom/base/test/test_file_negative_date.html6
-rw-r--r--dom/base/test/test_viewport_scroll.html4
46 files changed, 1144 insertions, 461 deletions
diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp
index 886acc670..092755590 100644
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -165,10 +165,9 @@ nsIContent::DoGetID() const
}
const nsAttrValue*
-nsIContent::DoGetClasses() const
+Element::DoGetClasses() const
{
MOZ_ASSERT(HasFlag(NODE_MAY_HAVE_CLASS), "Unexpected call");
- MOZ_ASSERT(IsElement(), "Only elements can have classes");
if (IsSVGElement()) {
const nsAttrValue* animClass =
@@ -178,12 +177,18 @@ nsIContent::DoGetClasses() const
}
}
- return AsElement()->GetParsedAttr(nsGkAtoms::_class);
+ return GetParsedAttr(nsGkAtoms::_class);
}
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);
@@ -1839,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).
diff --git a/dom/base/Element.h b/dom/base/Element.h
index 5d878df60..cf1d197e2 100644
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -544,6 +544,18 @@ public:
virtual uint32_t GetAttrCount() const override;
virtual bool IsNodeOfType(uint32_t aFlags) const override;
+ /**
+ * Get the class list of this element (this corresponds to the value of the
+ * class attribute). This may be null if there are no classes, but that's not
+ * guaranteed (e.g. we could have class="").
+ */
+ const nsAttrValue* GetClasses() const {
+ if (HasFlag(NODE_MAY_HAVE_CLASS)) {
+ return DoGetClasses();
+ }
+ return nullptr;
+ }
+
#ifdef DEBUG
virtual void List(FILE* out = stdout, int32_t aIndent = 0) const override
{
@@ -1372,6 +1384,12 @@ protected:
private:
/**
+ * Hook for implementing GetClasses. This is guaranteed to only be
+ * called if the NODE_MAY_HAVE_CLASS flag is set.
+ */
+ const nsAttrValue* DoGetClasses() const;
+
+ /**
* Get this element's client area rect in app units.
* @return the frame's client area
*/
diff --git a/dom/base/File.cpp b/dom/base/File.cpp
index 46b37b976..8602a3064 100644..100755
--- a/dom/base/File.cpp
+++ b/dom/base/File.cpp
@@ -29,6 +29,7 @@
#include "nsStringStream.h"
#include "nsJSUtils.h"
#include "nsPrintfCString.h"
+#include "mozilla/TimerClamping.h"
#include "mozilla/SHA1.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/Preferences.h"
@@ -727,7 +728,7 @@ BlobImplBase::GetLastModified(ErrorResult& aRv)
mLastModificationDate = PR_Now();
}
- return mLastModificationDate / PR_USEC_PER_MSEC;
+ return TimerClamping::ReduceUsTimeValue(mLastModificationDate) / PR_USEC_PER_MSEC;
}
void
diff --git a/dom/base/FileReader.cpp b/dom/base/FileReader.cpp
index 003edc61f..63a0ef2ee 100644
--- a/dom/base/FileReader.cpp
+++ b/dom/base/FileReader.cpp
@@ -452,8 +452,8 @@ FileReader::GetAsText(Blob *aBlob,
}
}
- nsDependentCSubstring data(aFileData, aDataLen);
- return nsContentUtils::ConvertStringFromEncoding(encoding, data, aResult);
+ return nsContentUtils::ConvertStringFromEncoding(
+ encoding, aFileData, aDataLen, aResult);
}
nsresult
diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp
index 293177ce7..b22a0d4ff 100644
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -574,6 +574,9 @@ FragmentOrElement::nsDOMSlots::Traverse(nsCycleCollectionTraversalCallback &cb,
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mChildrenList");
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMNodeList*, mChildrenList));
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mLabelsList");
+ cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMNodeList*, mLabelsList));
+
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mClassList");
cb.NoteXPCOMChild(mClassList.get());
@@ -602,6 +605,7 @@ FragmentOrElement::nsDOMSlots::Unlink(bool aIsXUL)
mShadowRoot = nullptr;
mContainingShadow = nullptr;
mChildrenList = nullptr;
+ mLabelsList = nullptr;
mCustomElementData = nullptr;
mClassList = nullptr;
}
@@ -1827,7 +1831,8 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(FragmentOrElement)
}
nsAutoString classes;
- const nsAttrValue* classAttrValue = tmp->GetClasses();
+ const nsAttrValue* classAttrValue = tmp->IsElement() ?
+ tmp->AsElement()->GetClasses() : nullptr;
if (classAttrValue) {
classes.AppendLiteral(" class='");
nsAutoString classString;
@@ -1932,7 +1937,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 3cb5575fe..1cd8033bb 100644
--- a/dom/base/FragmentOrElement.h
+++ b/dom/base/FragmentOrElement.h
@@ -24,6 +24,7 @@
class ContentUnbinder;
class nsContentList;
+class nsLabelsNodeList;
class nsDOMAttributeMap;
class nsDOMTokenList;
class nsIControllers;
@@ -313,6 +314,11 @@ public:
*/
RefPtr<nsDOMTokenList> mClassList;
+ /*
+ * An object implementing the .labels property for this element.
+ */
+ RefPtr<nsLabelsNodeList> mLabelsList;
+
/**
* ShadowRoot bound to the element.
*/
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..b6b95aaa6 100644
--- a/dom/base/Location.cpp
+++ b/dom/base/Location.cpp
@@ -577,19 +577,17 @@ Location::GetPathname(nsAString& aPathname)
aPathname.Truncate();
nsCOMPtr<nsIURI> uri;
- nsresult result = NS_OK;
+ nsresult result = GetURI(getter_AddRefs(uri));
+ if (NS_FAILED(result) || !uri) {
+ return result;
+ }
- result = GetURI(getter_AddRefs(uri));
+ nsAutoCString file;
- nsCOMPtr<nsIURIWithQuery> url(do_QueryInterface(uri));
- if (url) {
- nsAutoCString file;
+ result = uri->GetFilePath(file);
- result = url->GetFilePath(file);
-
- if (NS_SUCCEEDED(result)) {
- AppendUTF8toUTF16(file, aPathname);
- }
+ if (NS_SUCCEEDED(result)) {
+ AppendUTF8toUTF16(file, aPathname);
}
return result;
@@ -604,8 +602,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);
}
diff --git a/dom/base/MultipartBlobImpl.cpp b/dom/base/MultipartBlobImpl.cpp
index ba26d07f9..03bb62add 100644..100755
--- a/dom/base/MultipartBlobImpl.cpp
+++ b/dom/base/MultipartBlobImpl.cpp
@@ -17,6 +17,7 @@
#include "nsContentUtils.h"
#include "nsIScriptError.h"
#include "nsIXPConnect.h"
+#include "mozilla/TimerClamping.h"
#include <algorithm>
using namespace mozilla;
@@ -270,8 +271,7 @@ MultipartBlobImpl::SetLengthAndModifiedDate(ErrorResult& aRv)
// var x = new Date(); var f = new File(...);
// x.getTime() < f.dateModified.getTime()
// could fail.
- mLastModificationDate =
- lastModifiedSet ? lastModified * PR_USEC_PER_MSEC : JS_Now();
+ mLastModificationDate = TimerClamping::ReduceUsTimeValue(lastModifiedSet ? lastModified * PR_USEC_PER_MSEC : JS_Now());
}
}
diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp
index 290af152b..5c315517c 100644
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -97,8 +97,10 @@
#endif
#include "mozilla/dom/ContentChild.h"
+#ifdef MOZ_EME
#include "mozilla/EMEUtils.h"
#include "mozilla/DetailedPromise.h"
+#endif
namespace mozilla {
namespace dom {
@@ -214,7 +216,9 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServiceWorkerContainer)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
+#ifdef MOZ_EME
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeySystemAccessManager)
+#endif
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPresentation)
#ifdef MOZ_GAMEPAD
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGamepadServiceTest)
@@ -288,10 +292,12 @@ Navigator::Invalidate()
mServiceWorkerContainer = nullptr;
+#ifdef MOZ_EME
if (mMediaKeySystemAccessManager) {
mMediaKeySystemAccessManager->Shutdown();
mMediaKeySystemAccessManager = nullptr;
}
+#endif
#ifdef MOZ_GAMEPAD
if (mGamepadServiceTest) {
@@ -1854,16 +1860,6 @@ Navigator::GetUserAgent(nsPIDOMWindowInner* aWindow, nsIURI* aURI,
{
MOZ_ASSERT(NS_IsMainThread());
- if (!aIsCallerChrome) {
- const nsAdoptingString& override =
- mozilla::Preferences::GetString("general.useragent.override");
-
- if (override) {
- aUserAgent = override;
- return NS_OK;
- }
- }
-
nsresult rv;
nsCOMPtr<nsIHttpProtocolHandler>
service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv));
@@ -1894,6 +1890,7 @@ Navigator::GetUserAgent(nsPIDOMWindowInner* aWindow, nsIURI* aURI,
return siteSpecificUA->GetUserAgentForURIAndWindow(aURI, aWindow, aUserAgent);
}
+#ifdef MOZ_EME
static nsCString
ToCString(const nsString& aString)
{
@@ -2019,6 +2016,7 @@ Navigator::RequestMediaKeySystemAccess(const nsAString& aKeySystem,
mMediaKeySystemAccessManager->Request(promise, aKeySystem, aConfigs);
return promise.forget();
}
+#endif
Presentation*
Navigator::GetPresentation(ErrorResult& aRv)
diff --git a/dom/base/Navigator.h b/dom/base/Navigator.h
index 4b4ae6759..d47a80bc1 100644
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -18,7 +18,9 @@
#include "nsString.h"
#include "nsTArray.h"
#include "nsWeakPtr.h"
+#ifdef MOZ_EME
#include "mozilla/dom/MediaKeySystemAccessManager.h"
+#endif
class nsPluginArray;
class nsMimeTypeArray;
@@ -258,12 +260,14 @@ public:
// any, else null.
static already_AddRefed<nsPIDOMWindowInner> GetWindowFromGlobal(JSObject* aGlobal);
+#ifdef MOZ_EME
already_AddRefed<Promise>
RequestMediaKeySystemAccess(const nsAString& aKeySystem,
const Sequence<MediaKeySystemConfiguration>& aConfig,
ErrorResult& aRv);
private:
RefPtr<MediaKeySystemAccessManager> mMediaKeySystemAccessManager;
+#endif
public:
void NotifyVRDisplaysUpdated();
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/TimerClamping.cpp b/dom/base/TimerClamping.cpp
new file mode 100755
index 000000000..70639686b
--- /dev/null
+++ b/dom/base/TimerClamping.cpp
@@ -0,0 +1,35 @@
+/* -*- 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 "TimerClamping.h"
+
+namespace mozilla {
+
+/* static */
+double
+TimerClamping::ReduceSTimeValue(double aTime)
+{
+ static const double maxResolutionS = .002;
+ return floor(aTime / maxResolutionS) * maxResolutionS;
+}
+
+/* static */
+double
+TimerClamping::ReduceMsTimeValue(double aTime)
+{
+ static const double maxResolutionMs = 2;
+ return floor(aTime / maxResolutionMs) * maxResolutionMs;
+}
+
+/* static */
+double
+TimerClamping::ReduceUsTimeValue(double aTime)
+{
+ static const double maxResolutionUs = 2000;
+ return floor(aTime / maxResolutionUs) * maxResolutionUs;
+}
+
+} \ No newline at end of file
diff --git a/dom/base/TimerClamping.h b/dom/base/TimerClamping.h
new file mode 100755
index 000000000..2ffd6add5
--- /dev/null
+++ b/dom/base/TimerClamping.h
@@ -0,0 +1,22 @@
+/* -*- 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/. */
+
+#ifndef TimerClamping_h___
+#define TimerClamping_h___
+
+namespace mozilla {
+
+class TimerClamping
+{
+public:
+ static double ReduceSTimeValue(double aTime);
+ static double ReduceMsTimeValue(double aTime);
+ static double ReduceUsTimeValue(double aTime);
+};
+
+}
+
+#endif /* TimerClamping_h___ */ \ No newline at end of file
diff --git a/dom/base/moz.build b/dom/base/moz.build
index d237acb03..76c765b1c 100644..100755
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -143,6 +143,7 @@ EXPORTS.mozilla += [
'CORSMode.h',
'FeedWriterEnabled.h',
'TextInputProcessor.h',
+ 'TimerClamping.h',
'UseCounter.h',
]
@@ -216,6 +217,7 @@ EXPORTS.mozilla.dom += [
'TabGroup.h',
'Text.h',
'Timeout.h',
+ 'TimeoutHandler.h',
'TreeWalker.h',
'WebKitCSSMatrix.h',
'WebSocket.h',
@@ -363,6 +365,8 @@ UNIFIED_SOURCES += [
'TextInputProcessor.cpp',
'ThirdPartyUtil.cpp',
'Timeout.cpp',
+ 'TimeoutHandler.cpp',
+ 'TimerClamping.cpp',
'TreeWalker.cpp',
'WebKitCSSMatrix.cpp',
'WebSocket.cpp',
@@ -411,7 +415,7 @@ EXTRA_COMPONENTS += [
]
# Firefox for Android provides an alternate version of this component
-if CONFIG['MOZ_BUILD_APP'] != 'mobile/android':
+if not CONFIG['MOZ_FENNEC']:
EXTRA_COMPONENTS += [
'SiteSpecificUserAgent.js',
'SiteSpecificUserAgent.manifest',
@@ -472,7 +476,7 @@ include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
-if CONFIG['MOZ_BUILD_APP'] in ['browser', 'mobile/android', 'xulrunner']:
+if CONFIG['MOZ_PHOENIX'] or CONFIG['MOZ_FENNEC'] or CONFIG['MOZ_XULRUNNER']:
DEFINES['HAVE_SIDEBAR'] = True
if CONFIG['MOZ_X11']:
diff --git a/dom/base/nsContentList.cpp b/dom/base/nsContentList.cpp
index 09e949009..43e65777d 100644
--- a/dom/base/nsContentList.cpp
+++ b/dom/base/nsContentList.cpp
@@ -254,19 +254,6 @@ const nsCacheableFuncStringContentList::ContentListType
nsCacheableFuncStringHTMLCollection::sType = nsCacheableFuncStringContentList::eHTMLCollection;
#endif
-JSObject*
-nsCacheableFuncStringNodeList::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto)
-{
- return NodeListBinding::Wrap(cx, this, aGivenProto);
-}
-
-
-JSObject*
-nsCacheableFuncStringHTMLCollection::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto)
-{
- return HTMLCollectionBinding::Wrap(cx, this, aGivenProto);
-}
-
// Hashtable for storing nsCacheableFuncStringContentList
static PLDHashTable* gFuncStringContentListHashTable;
@@ -379,6 +366,7 @@ NS_GetFuncStringHTMLCollection(nsINode* aRootNode,
aString);
}
+//-----------------------------------------------------
// nsContentList implementation
nsContentList::nsContentList(nsINode* aRootNode,
@@ -660,7 +648,7 @@ nsContentList::AttributeChanged(nsIDocument *aDocument, Element* aElement,
const nsAttrValue* aOldValue)
{
NS_PRECONDITION(aElement, "Must have a content node to work with");
-
+
if (!mFunc || !mFuncMayDependOnAttr || mState == LIST_DIRTY ||
!MayContainRelevantNodes(aElement->GetParentNode()) ||
!nsContentUtils::IsInSameAnonymousTree(mRootNode, aElement)) {
@@ -806,7 +794,7 @@ nsContentList::ContentInserted(nsIDocument *aDocument,
ASSERT_IN_SYNC;
}
-
+
void
nsContentList::ContentRemoved(nsIDocument *aDocument,
nsIContent* aContainer,
@@ -1075,3 +1063,128 @@ nsContentList::AssertInSync()
NS_ASSERTION(cnt == mElements.Length(), "Too few elements");
}
#endif
+
+//-----------------------------------------------------
+// nsCacheableFuncStringNodeList
+
+JSObject*
+nsCacheableFuncStringNodeList::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto)
+{
+ return NodeListBinding::Wrap(cx, this, aGivenProto);
+}
+
+//-----------------------------------------------------
+// nsCacheableFuncStringHTMLCollection
+
+JSObject*
+nsCacheableFuncStringHTMLCollection::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto)
+{
+ return HTMLCollectionBinding::Wrap(cx, this, aGivenProto);
+}
+
+//-----------------------------------------------------
+// nsLabelsNodeList
+
+JSObject*
+nsLabelsNodeList::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto)
+{
+ return NodeListBinding::Wrap(cx, this, aGivenProto);
+}
+
+void
+nsLabelsNodeList::AttributeChanged(nsIDocument* aDocument, Element* aElement,
+ int32_t aNameSpaceID, nsIAtom* aAttribute,
+ int32_t aModType,
+ const nsAttrValue* aOldValue)
+{
+ MOZ_ASSERT(aElement, "Must have a content node to work with");
+ if (mState == LIST_DIRTY ||
+ !nsContentUtils::IsInSameAnonymousTree(mRootNode, aElement)) {
+ return;
+ }
+
+ // We need to handle input type changes to or from "hidden".
+ if (aElement->IsHTMLElement(nsGkAtoms::input) &&
+ aAttribute == nsGkAtoms::type && aNameSpaceID == kNameSpaceID_None) {
+ SetDirty();
+ return;
+ }
+}
+
+void
+nsLabelsNodeList::ContentAppended(nsIDocument* aDocument,
+ nsIContent* aContainer,
+ nsIContent* aFirstNewContent,
+ int32_t aNewIndexInContainer)
+{
+ // If a labelable element is moved to outside or inside of
+ // nested associated labels, we're gonna have to modify
+ // the content list.
+ if (mState != LIST_DIRTY ||
+ nsContentUtils::IsInSameAnonymousTree(mRootNode, aContainer)) {
+ SetDirty();
+ return;
+ }
+}
+
+void
+nsLabelsNodeList::ContentInserted(nsIDocument* aDocument,
+ nsIContent* aContainer,
+ nsIContent* aChild,
+ int32_t aIndexInContainer)
+{
+ // If a labelable element is moved to outside or inside of
+ // nested associated labels, we're gonna have to modify
+ // the content list.
+ if (mState != LIST_DIRTY ||
+ nsContentUtils::IsInSameAnonymousTree(mRootNode, aChild)) {
+ SetDirty();
+ return;
+ }
+}
+
+void
+nsLabelsNodeList::ContentRemoved(nsIDocument* aDocument,
+ nsIContent* aContainer,
+ nsIContent* aChild,
+ int32_t aIndexInContainer,
+ nsIContent* aPreviousSibling)
+{
+ // If a labelable element is removed, we're gonna have to clean
+ // the content list.
+ if (mState != LIST_DIRTY ||
+ nsContentUtils::IsInSameAnonymousTree(mRootNode, aChild)) {
+ SetDirty();
+ return;
+ }
+}
+
+void
+nsLabelsNodeList::MaybeResetRoot(nsINode* aRootNode)
+{
+ MOZ_ASSERT(aRootNode, "Must have root");
+ if (mRootNode == aRootNode) {
+ return;
+ }
+
+ if (mRootNode) {
+ mRootNode->RemoveMutationObserver(this);
+ }
+ mRootNode = aRootNode;
+ mRootNode->AddMutationObserver(this);
+ SetDirty();
+}
+
+void
+nsLabelsNodeList::PopulateSelf(uint32_t aNeededLength)
+{
+ MOZ_ASSERT(mRootNode, "Must have root");
+
+ // Start searching at the root.
+ nsINode* cur = mRootNode;
+ if (mElements.IsEmpty() && cur->IsElement() && Match(cur->AsElement())) {
+ mElements.AppendElement(cur->AsElement());
+ }
+
+ nsContentList::PopulateSelf(aNeededLength);
+}
diff --git a/dom/base/nsContentList.h b/dom/base/nsContentList.h
index 3878074b2..83d27da95 100644
--- a/dom/base/nsContentList.h
+++ b/dom/base/nsContentList.h
@@ -371,9 +371,9 @@ protected:
* traversed the whole document (or both).
*
* @param aNeededLength the length the list should have when we are
- * done (unless it exhausts the document)
+ * done (unless it exhausts the document)
*/
- void PopulateSelf(uint32_t aNeededLength);
+ virtual void PopulateSelf(uint32_t aNeededLength);
/**
* @param aContainer a content node which must be a descendant of
@@ -584,4 +584,40 @@ public:
#endif
};
+class nsLabelsNodeList final : public nsContentList
+{
+public:
+ nsLabelsNodeList(nsINode* aRootNode,
+ nsContentListMatchFunc aFunc,
+ nsContentListDestroyFunc aDestroyFunc,
+ void* aData)
+ : nsContentList(aRootNode, aFunc, aDestroyFunc, aData)
+ {
+ }
+
+ NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
+ NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
+ NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
+ NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
+
+ virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
+
+ /**
+ * Reset root, mutation observer, and clear content list
+ * if the root has been changed.
+ *
+ * @param aRootNode The node under which to limit our search.
+ */
+ void MaybeResetRoot(nsINode* aRootNode);
+
+private:
+ /**
+ * Start searching at the last one if we already have nodes, otherwise
+ * start searching at the root.
+ *
+ * @param aNeededLength The list of length should have when we are
+ * done (unless it exhausts the document).
+ */
+ void PopulateSelf(uint32_t aNeededLength) override;
+};
#endif // nsContentList_h___
diff --git a/dom/base/nsContentListDeclarations.h b/dom/base/nsContentListDeclarations.h
index db3a09036..a5e0e3691 100644
--- a/dom/base/nsContentListDeclarations.h
+++ b/dom/base/nsContentListDeclarations.h
@@ -18,6 +18,12 @@ class nsINode;
class nsString;
class nsAString;
+namespace mozilla {
+namespace dom {
+class Element;
+} // namespace dom
+} // namespace mozilla
+
// Magic namespace id that means "match all namespaces". This is
// negative so it won't collide with actual namespace constants.
#define kNameSpaceID_Wildcard INT32_MIN
@@ -26,7 +32,7 @@ class nsAString;
// arbitrary matching algorithm. aContent is the content that may
// match the list, while aNamespaceID, aAtom, and aData are whatever
// was passed to the list's constructor.
-typedef bool (*nsContentListMatchFunc)(nsIContent* aContent,
+typedef bool (*nsContentListMatchFunc)(mozilla::dom::Element* aElement,
int32_t aNamespaceID,
nsIAtom* aAtom,
void* aData);
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/nsContentSink.cpp b/dom/base/nsContentSink.cpp
index 3d6f069d2..85b3d07bf 100644
--- a/dom/base/nsContentSink.cpp
+++ b/dom/base/nsContentSink.cpp
@@ -305,6 +305,11 @@ nsContentSink::ProcessHeaderData(nsIAtom* aHeader, const nsAString& aValue,
mDocument->SetHeaderData(aHeader, aValue);
if (aHeader == nsGkAtoms::setcookie) {
+ // Don't allow setting cookies in cookie-averse documents.
+ if (mDocument->IsCookieAverse()) {
+ return NS_OK;
+ }
+
// Note: Necko already handles cookies set via the channel. We can't just
// call SetCookie on the channel because we want to do some security checks
// here.
diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp
index 29d28f8ce..bc8cea35a 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);
@@ -3717,11 +3721,15 @@ nsContentUtils::IsChildOfSameType(nsIDocument* aDoc)
}
bool
-nsContentUtils::IsScriptType(const nsACString& aContentType)
+nsContentUtils::IsPlainTextType(const nsACString& aContentType)
{
// NOTE: if you add a type here, add it to the CONTENTDLF_CATEGORIES
// define in nsContentDLF.h as well.
- return aContentType.EqualsLiteral(APPLICATION_JAVASCRIPT) ||
+ return aContentType.EqualsLiteral(TEXT_PLAIN) ||
+ aContentType.EqualsLiteral(TEXT_CSS) ||
+ aContentType.EqualsLiteral(TEXT_CACHE_MANIFEST) ||
+ aContentType.EqualsLiteral(TEXT_VTT) ||
+ aContentType.EqualsLiteral(APPLICATION_JAVASCRIPT) ||
aContentType.EqualsLiteral(APPLICATION_XJAVASCRIPT) ||
aContentType.EqualsLiteral(TEXT_ECMASCRIPT) ||
aContentType.EqualsLiteral(APPLICATION_ECMASCRIPT) ||
@@ -3731,18 +3739,6 @@ nsContentUtils::IsScriptType(const nsACString& aContentType)
}
bool
-nsContentUtils::IsPlainTextType(const nsACString& aContentType)
-{
- // NOTE: if you add a type here, add it to the CONTENTDLF_CATEGORIES
- // define in nsContentDLF.h as well.
- return aContentType.EqualsLiteral(TEXT_PLAIN) ||
- aContentType.EqualsLiteral(TEXT_CSS) ||
- aContentType.EqualsLiteral(TEXT_CACHE_MANIFEST) ||
- aContentType.EqualsLiteral(TEXT_VTT) ||
- IsScriptType(aContentType);
-}
-
-bool
nsContentUtils::GetWrapperSafeScriptFilename(nsIDocument* aDocument,
nsIURI* aURI,
nsACString& aScriptURI,
@@ -4128,9 +4124,15 @@ nsContentUtils::GetSubdocumentWithOuterWindowId(nsIDocument *aDocument,
/* static */
nsresult
nsContentUtils::ConvertStringFromEncoding(const nsACString& aEncoding,
- const nsACString& aInput,
+ const char* aInput,
+ uint32_t aInputLen,
nsAString& aOutput)
{
+ CheckedInt32 len = aInputLen;
+ if (!len.isValid()) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
nsAutoCString encoding;
if (aEncoding.IsEmpty()) {
encoding.AssignLiteral("UTF-8");
@@ -4142,7 +4144,7 @@ nsContentUtils::ConvertStringFromEncoding(const nsACString& aEncoding,
nsAutoPtr<TextDecoder> decoder(new TextDecoder());
decoder->InitWithEncoding(encoding, false);
- decoder->Decode(aInput.BeginReading(), aInput.Length(), false,
+ decoder->Decode(aInput, len.value(), false,
aOutput, rv);
return rv.StealNSResult();
}
@@ -6281,11 +6283,11 @@ struct ClassMatchingInfo {
// static
bool
-nsContentUtils::MatchClassNames(nsIContent* aContent, int32_t aNamespaceID,
+nsContentUtils::MatchClassNames(Element* aElement, int32_t aNamespaceID,
nsIAtom* aAtom, void* aData)
{
// We can't match if there are no class names
- const nsAttrValue* classAttr = aContent->GetClasses();
+ const nsAttrValue* classAttr = aElement->GetClasses();
if (!classAttr) {
return false;
}
diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h
index 278fbd008..9ae6d2155 100644
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -554,9 +554,17 @@ public:
* string (meaning UTF-8)
*/
static nsresult ConvertStringFromEncoding(const nsACString& aEncoding,
- const nsACString& aInput,
+ const char* aInput,
+ uint32_t aInputLen,
nsAString& aOutput);
+ static nsresult ConvertStringFromEncoding(const nsACString& aEncoding,
+ const nsACString& aInput,
+ nsAString& aOutput) {
+ return ConvertStringFromEncoding(
+ aEncoding, aInput.BeginReading(), aInput.Length(), aOutput);
+ }
+
/**
* Determine whether a buffer begins with a BOM for UTF-8, UTF-16LE,
* UTF-16BE
@@ -1010,12 +1018,7 @@ public:
static bool IsChildOfSameType(nsIDocument* aDoc);
/**
- '* Returns true if the content-type is any of the supported script types.
- */
- static bool IsScriptType(const nsACString& aContentType);
-
- /**
- '* Returns true if the content-type will be rendered as plain-text.
+ * Returns true if the content-type will be rendered as plain-text.
*/
static bool IsPlainTextType(const nsACString& aContentType);
@@ -2030,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()
@@ -2745,7 +2756,8 @@ private:
static void DropFragmentParsers();
- static bool MatchClassNames(nsIContent* aContent, int32_t aNamespaceID,
+ static bool MatchClassNames(mozilla::dom::Element* aElement,
+ int32_t aNamespaceID,
nsIAtom* aAtom, void* aData);
static void DestroyClassNameArray(void* aData);
static void* AllocClassMatchingInfo(nsINode* aRootNode,
@@ -2821,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 8e6920a0e..fd3b52948 100644
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -61,6 +61,7 @@
#include "nsGenericHTMLElement.h"
#include "mozilla/dom/CDATASection.h"
#include "mozilla/dom/ProcessingInstruction.h"
+#include "nsDSURIContentListener.h"
#include "nsDOMString.h"
#include "nsNodeUtils.h"
#include "nsLayoutUtils.h" // for GetFrameForPoint
@@ -2053,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;
@@ -2456,6 +2464,15 @@ nsDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
NS_ENSURE_SUCCESS(rv, rv);
}
+ // XFO needs to be checked after CSP because it is ignored if
+ // the CSP defines frame-ancestors.
+ if (!nsDSURIContentListener::CheckFrameOptions(aChannel, docShell, NodePrincipal())) {
+ MOZ_LOG(gCspPRLog, LogLevel::Debug,
+ ("XFO doesn't like frame's ancestry, not loading."));
+ // stop! ERROR page!
+ aChannel->Cancel(NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION);
+ }
+
return NS_OK;
}
@@ -3903,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
@@ -4330,6 +4357,7 @@ nsDocument::SetScopeObject(nsIGlobalObject* aGlobal)
}
}
+#ifdef MOZ_EME
static void
CheckIfContainsEMEContent(nsISupports* aSupports, void* aContainsEME)
{
@@ -4353,6 +4381,7 @@ nsDocument::ContainsEMEContent()
static_cast<void*>(&containsEME));
return containsEME;
}
+#endif // MOZ_EME
static void
CheckIfContainsMSEContent(nsISupports* aSupports, void* aContainsMSE)
@@ -8380,11 +8409,13 @@ nsDocument::CanSavePresentation(nsIRequest *aNewRequest)
}
#endif // MOZ_WEBRTC
+#ifdef MOZ_EME
// Don't save presentations for documents containing EME content, so that
// CDMs reliably shutdown upon user navigation.
if (ContainsEMEContent()) {
return false;
}
+#endif
// Don't save presentations for documents containing MSE content, to
// reduce memory usage.
@@ -12832,3 +12863,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/nsDocument.h b/dom/base/nsDocument.h
index 17d936055..3725b3c18 100644
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -1267,7 +1267,9 @@ public:
js::ExpandoAndGeneration mExpandoAndGeneration;
+#ifdef MOZ_EME
bool ContainsEMEContent();
+#endif
bool ContainsMSEContent();
@@ -1491,7 +1493,6 @@ private:
void PostUnblockOnloadEvent();
void DoUnblockOnload();
- nsresult CheckFrameOptions();
nsresult InitCSP(nsIChannel* aChannel);
/**
diff --git a/dom/base/nsDocumentEncoder.cpp b/dom/base/nsDocumentEncoder.cpp
index 0a3570962..84b128b15 100644
--- a/dom/base/nsDocumentEncoder.cpp
+++ b/dom/base/nsDocumentEncoder.cpp
@@ -481,7 +481,7 @@ nsDocumentEncoder::SerializeToStringRecursive(nsINode* aNode,
}
if (!aDontSerializeRoot) {
- rv = SerializeNodeEnd(node, aStr);
+ rv = SerializeNodeEnd(maybeFixedNode, aStr);
NS_ENSURE_SUCCESS(rv, rv);
}
diff --git a/dom/base/nsFrameMessageManager.cpp b/dom/base/nsFrameMessageManager.cpp
index a4bba4856..049bc0a1a 100644
--- a/dom/base/nsFrameMessageManager.cpp
+++ b/dom/base/nsFrameMessageManager.cpp
@@ -51,10 +51,6 @@
#include <algorithm>
#include "chrome/common/ipc_channel.h" // for IPC::Channel::kMaximumMessageSize
-#ifdef MOZ_CRASHREPORTER
-#include "nsExceptionHandler.h"
-#endif
-
#ifdef ANDROID
#include <android/log.h>
#endif
diff --git a/dom/base/nsGkAtomList.h b/dom/base/nsGkAtomList.h
index 5ece68634..aa4ef2ca3 100644
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -526,6 +526,7 @@ GK_ATOM(keytext, "keytext")
GK_ATOM(keyup, "keyup")
GK_ATOM(kind, "kind")
GK_ATOM(label, "label")
+GK_ATOM(labels, "labels")
GK_ATOM(lang, "lang")
GK_ATOM(language, "language")
GK_ATOM(last, "last")
@@ -951,6 +952,7 @@ GK_ATOM(onupdateready, "onupdateready")
GK_ATOM(onupgradeneeded, "onupgradeneeded")
GK_ATOM(onussdreceived, "onussdreceived")
GK_ATOM(onversionchange, "onversionchange")
+GK_ATOM(onvisibilitychange, "onvisibilitychange")
GK_ATOM(onvoicechange, "onvoicechange")
GK_ATOM(onvoiceschanged, "onvoiceschanged")
GK_ATOM(onvrdisplayconnect, "onvrdisplayconnect")
@@ -1450,6 +1452,7 @@ GK_ATOM(font_style, "font-style")
GK_ATOM(font_variant, "font-variant")
GK_ATOM(foreignObject, "foreignObject")
GK_ATOM(fractalNoise, "fractalNoise")
+GK_ATOM(fr, "fr")
GK_ATOM(fx, "fx")
GK_ATOM(fy, "fy")
GK_ATOM(G, "G")
@@ -2231,6 +2234,8 @@ GK_ATOM(scrollbar_end_backward, "scrollbar-end-backward")
GK_ATOM(scrollbar_end_forward, "scrollbar-end-forward")
GK_ATOM(scrollbar_thumb_proportional, "scrollbar-thumb-proportional")
GK_ATOM(overlay_scrollbars, "overlay-scrollbars")
+GK_ATOM(windows_accent_color_applies, "windows-accent-color-applies")
+GK_ATOM(windows_accent_color_is_dark, "windows-accent-color-is-dark")
GK_ATOM(windows_default_theme, "windows-default-theme")
GK_ATOM(mac_graphite_theme, "mac-graphite-theme")
GK_ATOM(mac_yosemite_theme, "mac-yosemite-theme")
@@ -2260,6 +2265,8 @@ GK_ATOM(_moz_scrollbar_end_backward, "-moz-scrollbar-end-backward")
GK_ATOM(_moz_scrollbar_end_forward, "-moz-scrollbar-end-forward")
GK_ATOM(_moz_scrollbar_thumb_proportional, "-moz-scrollbar-thumb-proportional")
GK_ATOM(_moz_overlay_scrollbars, "-moz-overlay-scrollbars")
+GK_ATOM(_moz_windows_accent_color_applies, "-moz-windows-accent-color-applies")
+GK_ATOM(_moz_windows_accent_color_is_dark, "-moz-windows-accent-color-is-dark")
GK_ATOM(_moz_windows_default_theme, "-moz-windows-default-theme")
GK_ATOM(_moz_mac_graphite_theme, "-moz-mac-graphite-theme")
GK_ATOM(_moz_mac_yosemite_theme, "-moz-mac-yosemite-theme")
diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp
index 8ff4b84ce..738703ef1 100644
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -23,6 +23,7 @@
#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)
#include "mozilla/dom/WindowOrientationObserver.h"
@@ -552,29 +553,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 (mThrottledIdleRequestCallbacks.isEmpty())
+ if (!mWindow) {
return;
+ }
+
+ mDeadline = aDeadline;
+}
- RefPtr<IdleRequest> request(mThrottledIdleRequestCallbacks.popFirst());
- // ownership transferred from mThrottledIdleRequestCallbacks to
- // mIdleRequestCallbacks
- mIdleRequestCallbacks.insertBack(request);
+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;
+ }
+
+ mDispatched = true;
+ RefPtr<IdleRequestExecutor> request = this;
NS_IdleDispatchToCurrentThread(request.forget());
}
-/* static */ void
-nsGlobalWindow::InsertIdleCallbackIntoList(IdleRequest* aRequest,
- IdleRequests& aList)
+class IdleRequestExecutorTimeoutHandler final : public TimeoutHandler
+{
+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)
{
- aList.insertBack(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 +840,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 +882,7 @@ nsGlobalWindow::CancelIdleCallback(uint32_t aHandle)
for (IdleRequest* r : mIdleRequestCallbacks) {
if (r->Handle() == aHandle) {
- r->Cancel();
+ RemoveIdleCallback(r);
break;
}
}
@@ -632,29 +891,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,6 +1553,7 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
mSerial(0),
mIdleCallbackTimeoutCounter(1),
mIdleRequestCallbackCounter(1),
+ mIdleRequestExecutor(nullptr),
#ifdef DEBUG
mSetOpenerWindowCalled(false),
#endif
@@ -2033,14 +2281,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 +2392,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
@@ -2878,8 +3124,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 +4338,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);
}
}
@@ -6187,7 +6417,7 @@ nsGlobalWindow::GetScrollMaxY(ErrorResult& aError)
FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideBottom), aError, 0);
}
-CSSIntPoint
+CSSPoint
nsGlobalWindow::GetScrollXY(bool aDoFlush)
{
MOZ_ASSERT(IsOuterWindow());
@@ -6211,30 +6441,30 @@ nsGlobalWindow::GetScrollXY(bool aDoFlush)
return GetScrollXY(true);
}
- return sf->GetScrollPositionCSSPixels();
+ return CSSPoint::FromAppUnits(scrollPos);
}
-int32_t
+double
nsGlobalWindow::GetScrollXOuter()
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
return GetScrollXY(false).x;
}
-int32_t
+double
nsGlobalWindow::GetScrollX(ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(GetScrollXOuter, (), aError, 0);
}
-int32_t
+double
nsGlobalWindow::GetScrollYOuter()
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
return GetScrollXY(false).y;
}
-int32_t
+double
nsGlobalWindow::GetScrollY(ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(GetScrollYOuter, (), aError, 0);
@@ -10237,12 +10467,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();
@@ -12036,6 +12260,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 +12372,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().
diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h
index eab91c2e4..78bee63a1 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;
@@ -1050,15 +1053,15 @@ public:
void SetInnerHeight(JSContext* aCx, JS::Handle<JS::Value> aValue,
mozilla::dom::CallerType aCallerType,
mozilla::ErrorResult& aError);
- int32_t GetScrollXOuter();
- int32_t GetScrollX(mozilla::ErrorResult& aError);
- int32_t GetPageXOffset(mozilla::ErrorResult& aError)
+ double GetScrollXOuter();
+ double GetScrollX(mozilla::ErrorResult& aError);
+ double GetPageXOffset(mozilla::ErrorResult& aError)
{
return GetScrollX(aError);
}
- int32_t GetScrollYOuter();
- int32_t GetScrollY(mozilla::ErrorResult& aError);
- int32_t GetPageYOffset(mozilla::ErrorResult& aError)
+ double GetScrollYOuter();
+ double GetScrollY(mozilla::ErrorResult& aError);
+ double GetPageYOffset(mozilla::ErrorResult& aError)
{
return GetScrollY(aError);
}
@@ -1097,7 +1100,6 @@ public:
mozilla::ErrorResult& aError);
void CancelIdleCallback(uint32_t aHandle);
-
#ifdef MOZ_WEBSPEECH
mozilla::dom::SpeechSynthesis*
GetSpeechSynthesis(mozilla::ErrorResult& aError);
@@ -1579,7 +1581,7 @@ public:
// If aDoFlush is true, we'll flush our own layout; otherwise we'll try to
// just flush our parent and only flush ourselves if we think we need to.
// Outer windows only.
- mozilla::CSSIntPoint GetScrollXY(bool aDoFlush);
+ mozilla::CSSPoint GetScrollXY(bool aDoFlush);
int32_t GetScrollBoundaryOuter(mozilla::Side aSide);
@@ -1762,6 +1764,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,21 +1929,12 @@ 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;
@@ -2002,6 +2010,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/nsIContent.h b/dom/base/nsIContent.h
index f05c47a61..405090865 100644
--- a/dom/base/nsIContent.h
+++ b/dom/base/nsIContent.h
@@ -862,18 +862,6 @@ public:
}
/**
- * Get the class list of this content node (this corresponds to the
- * value of the class attribute). This may be null if there are no
- * classes, but that's not guaranteed.
- */
- const nsAttrValue* GetClasses() const {
- if (HasFlag(NODE_MAY_HAVE_CLASS)) {
- return DoGetClasses();
- }
- return nullptr;
- }
-
- /**
* Walk aRuleWalker over the content style rules (presentational
* hint rules) for this content node.
*/
@@ -990,13 +978,6 @@ protected:
*/
nsIAtom* DoGetID() const;
-private:
- /**
- * Hook for implementing GetClasses. This is guaranteed to only be
- * called if the NODE_MAY_HAVE_CLASS flag is set.
- */
- const nsAttrValue* DoGetClasses() const;
-
public:
#ifdef DEBUG
/**
diff --git a/dom/base/nsIDocument.h b/dom/base/nsIDocument.h
index 5b10c9914..1e0c9562e 100644
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -151,6 +151,7 @@ class NodeIterator;
enum class OrientationType : uint32_t;
class ProcessingInstruction;
class Promise;
+class Selection;
class StyleSheetList;
class SVGDocument;
class SVGSVGElement;
@@ -898,6 +899,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
@@ -1923,6 +1926,34 @@ public:
return mMarkedCCGeneration;
}
+ /**
+ * Returns whether this document is cookie-averse. See
+ * https://html.spec.whatwg.org/multipage/dom.html#cookie-averse-document-object
+ */
+ bool IsCookieAverse() const
+ {
+ // If we are a document that "has no browsing context."
+ if (!GetInnerWindow()) {
+ return true;
+ }
+
+ // If we are a document "whose URL's scheme is not a network scheme."
+ // NB: Explicitly allow file: URIs to store cookies.
+ nsCOMPtr<nsIURI> codebaseURI;
+ NodePrincipal()->GetURI(getter_AddRefs(codebaseURI));
+
+ if (!codebaseURI) {
+ return true;
+ }
+
+ nsAutoCString scheme;
+ codebaseURI->GetScheme(scheme);
+ return !scheme.EqualsLiteral("http") &&
+ !scheme.EqualsLiteral("https") &&
+ !scheme.EqualsLiteral("ftp") &&
+ !scheme.EqualsLiteral("file");
+ }
+
bool IsLoadedAsData()
{
return mLoadedAsData;
diff --git a/dom/base/nsINode.cpp b/dom/base/nsINode.cpp
index 3a649a61d..715ca93ea 100644
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -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/nsPluginArray.cpp b/dom/base/nsPluginArray.cpp
index b9c946ca3..5b9378ae0 100644
--- a/dom/base/nsPluginArray.cpp
+++ b/dom/base/nsPluginArray.cpp
@@ -372,9 +372,21 @@ nsPluginArray::EnsurePlugins()
nsCString permString;
nsresult rv = pluginHost->GetPermissionStringForTag(pluginTag, 0, permString);
if (rv == NS_OK) {
- nsIPrincipal* principal = mWindow->GetExtantDoc()->NodePrincipal();
- nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
- permMgr->TestPermissionFromPrincipal(principal, permString.get(), &permission);
+ nsCOMPtr<nsIDocument> currentDoc = mWindow->GetExtantDoc();
+
+ // The top-level content document gets the final say on whether or not
+ // a plugin is going to be hidden or not, regardless of the origin
+ // that a subframe is hosted at. This is to avoid spamming the user
+ // with the hidden plugin notification bar when third-party iframes
+ // attempt to access navigator.plugins after the user has already
+ // expressed that the top-level document has this permission.
+ nsCOMPtr<nsIDocument> topDoc = currentDoc->GetTopLevelContentDocument();
+
+ if (topDoc) {
+ nsIPrincipal* principal = topDoc->NodePrincipal();
+ nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
+ permMgr->TestPermissionFromPrincipal(principal, permString.get(), &permission);
+ }
}
}
}
diff --git a/dom/base/nsRange.cpp b/dom/base/nsRange.cpp
index 37ba147af..4b4ce7885 100644
--- a/dom/base/nsRange.cpp
+++ b/dom/base/nsRange.cpp
@@ -3194,7 +3194,7 @@ nsRange::AutoInvalidateSelection::~AutoInvalidateSelection()
mIsNested = false;
::InvalidateAllFrames(mCommonAncestor);
nsINode* commonAncestor = mRange->GetRegisteredCommonAncestor();
- if (commonAncestor != mCommonAncestor) {
+ if (commonAncestor && commonAncestor != mCommonAncestor) {
::InvalidateAllFrames(commonAncestor);
}
}
diff --git a/dom/base/nsTreeSanitizer.cpp b/dom/base/nsTreeSanitizer.cpp
index dc53ea5fa..323c851c1 100644
--- a/dom/base/nsTreeSanitizer.cpp
+++ b/dom/base/nsTreeSanitizer.cpp
@@ -169,6 +169,7 @@ nsIAtom** const kAttributesHTML[] = {
&nsGkAtoms::contextmenu,
&nsGkAtoms::controls,
&nsGkAtoms::coords,
+ &nsGkAtoms::crossorigin,
&nsGkAtoms::datetime,
&nsGkAtoms::dir,
&nsGkAtoms::disabled,
@@ -185,6 +186,7 @@ nsIAtom** const kAttributesHTML[] = {
&nsGkAtoms::hreflang,
&nsGkAtoms::icon,
&nsGkAtoms::id,
+ &nsGkAtoms::integrity,
&nsGkAtoms::ismap,
&nsGkAtoms::itemid,
&nsGkAtoms::itemprop,
diff --git a/dom/base/nsXHTMLContentSerializer.cpp b/dom/base/nsXHTMLContentSerializer.cpp
index 0dc31d7ae..111ed46c7 100644..100755
--- a/dom/base/nsXHTMLContentSerializer.cpp
+++ b/dom/base/nsXHTMLContentSerializer.cpp
@@ -306,7 +306,7 @@ nsXHTMLContentSerializer::SerializeAttributes(nsIContent* aContent,
continue;
}
- BorrowedAttrInfo info = aContent->GetAttrInfoAt(index);
+ mozilla::dom::BorrowedAttrInfo info = aContent->GetAttrInfoAt(index);
const nsAttrName* name = info.mName;
int32_t namespaceID = name->NamespaceID();
diff --git a/dom/base/test/mochitest.ini b/dom/base/test/mochitest.ini
index ea86290d9..ddfd57443 100644
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -609,6 +609,7 @@ skip-if = toolkit == 'android'
[test_bug1307730.html]
[test_bug1308069.html]
[test_bug1314032.html]
+[test_bug1375050.html]
[test_caretPositionFromPoint.html]
[test_change_policy.html]
[test_classList.html]
diff --git a/dom/base/test/test_bug1375050.html b/dom/base/test/test_bug1375050.html
new file mode 100644
index 000000000..b91b859d0
--- /dev/null
+++ b/dom/base/test/test_bug1375050.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1375050
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1375050</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+ try { o1 = document.createElement('input'); } catch(e) { console.log(e); };
+ try { o2 = document.createElement('col'); } catch(e) { console.log(e); };
+ try { o4 = document.createRange(); } catch(e) { console.log(e); };
+ try { document.documentElement.appendChild(o1); } catch(e) { console.log(e); };
+ try { for (let p in o1) { let x = o1[p] }; } catch(e) { console.log(e); };
+ try { o4.selectNode(o1); } catch(e) { console.log(e); };
+ try { o6 = document.createComment(" x"); } catch(e) { console.log(e); }
+ try { o4.surroundContents(o6); } catch(e) { console.log(e); }
+ try { o7 = document.implementation.createDocument('', '', null).adoptNode(o1); } catch(e) { console.log(e);};
+ try { o2.appendChild(o1); } catch(e) { console.log(e); };
+ ok(true, "Didn't crash.");
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1375050">Mozilla Bug 1375050</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/base/test/test_bug403852.html b/dom/base/test/test_bug403852.html
index 30192cb1b..592711500 100644
--- a/dom/base/test/test_bug403852.html
+++ b/dom/base/test/test_bug403852.html
@@ -38,7 +38,8 @@ function onOpened(message) {
ok("lastModifiedDate" in domFile, "lastModifiedDate must be present");
var d = new Date(message.mtime);
- is(d.getTime(), domFile.lastModifiedDate.getTime(), "lastModifiedDate should be the same");
+ // Commented out: lastModifiedDate is rounded because it is a DOM API, message is a special-powers Chrome thing
+ // is(d.getTime(), domFile.lastModifiedDate.getTime(), "lastModifiedDate should be the same");
var x = new Date();
@@ -53,8 +54,8 @@ function onOpened(message) {
ok((x.getTime() <= y.getTime()) && (y.getTime() <= z.getTime()), "lastModifiedDate of file which does not have last modified date should be current time");
- var d = new Date(message.fileDate);
- is(d.getTime(), message.fileWithDate.lastModifiedDate.getTime(), "lastModifiedDate should be the same when lastModified is set: " + message.fileWithDate.lastModified);
+ // var d = new Date(message.fileDate);
+ // is(d.getTime(), message.fileWithDate.lastModifiedDate.getTime(), "lastModifiedDate should be the same when lastModified is set: " + message.fileWithDate.lastModified);
script.destroy();
SimpleTest.finish();
diff --git a/dom/base/test/test_file_negative_date.html b/dom/base/test/test_file_negative_date.html
index ebfa9bd0d..26cf3b82e 100644
--- a/dom/base/test/test_file_negative_date.html
+++ b/dom/base/test/test_file_negative_date.html
@@ -22,13 +22,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1158437
var blob = new Blob(['hello world']);
var f1 = new File([blob], 'f1.txt', { lastModified: 0 });
-var f2 = new File([blob], 'f2.txt', { lastModified: -1 });
+var f2 = new File([blob], 'f2.txt', { lastModified: -2 });
var f3 = new File([blob], 'f3.txt', { lastModified: -1000 });
is(f1.lastModified, 0, "lastModified == 0 is supported");
ok(f1.lastModifiedDate.toString(), (new Date(0)).toString(), "Correct f1.lastModifiedDate value");
-is(f2.lastModified, -1, "lastModified == -1 is supported");
-ok(f2.lastModifiedDate.toString(), (new Date(-1)).toString(), "Correct f2.lastModifiedDate value");
+is(f2.lastModified, -2, "lastModified == -2 is supported");
+ok(f2.lastModifiedDate.toString(), (new Date(-2)).toString(), "Correct f2.lastModifiedDate value");
is(f3.lastModified, -1000, "lastModified == -1000 is supported");
ok(f3.lastModifiedDate.toString(), (new Date(-1000)).toString(), "Correct f3.lastModifiedDate value");
diff --git a/dom/base/test/test_viewport_scroll.html b/dom/base/test/test_viewport_scroll.html
index 9b812360b..7db02b781 100644
--- a/dom/base/test/test_viewport_scroll.html
+++ b/dom/base/test/test_viewport_scroll.html
@@ -28,10 +28,10 @@ function subtest(winProp, elemProp, win, correctElement, elemToSet, otherElem1,
win.scrollTo(50, 50);
elemToSet[elemProp] = 100;
if (elemToSet == correctElement) {
- is(win[winProp], 100, "Setting " + elemToSet.name + "." + elemProp + " should scroll");
+ is(Math.round(win[winProp]), 100, "Setting " + elemToSet.name + "." + elemProp + " should scroll");
is(elemToSet[elemProp], 100, "Reading back " + elemToSet.name + "." + elemProp + " after scrolling");
} else {
- is(win[winProp], 50, "Setting " + elemToSet.name + "." + elemProp + " should not scroll");
+ is(Math.round(win[winProp]), 50, "Setting " + elemToSet.name + "." + elemProp + " should not scroll");
is(elemToSet[elemProp], 0, "Reading back " + elemToSet.name + "." + elemProp + " after not scrolling");
}
if (otherElem1 == correctElement) {