summaryrefslogtreecommitdiffstats
path: root/dom
diff options
context:
space:
mode:
Diffstat (limited to 'dom')
-rw-r--r--dom/base/Element.cpp5
-rw-r--r--dom/base/Element.h18
-rwxr-xr-x[-rw-r--r--]dom/base/File.cpp3
-rw-r--r--dom/base/FragmentOrElement.cpp7
-rw-r--r--dom/base/FragmentOrElement.h6
-rwxr-xr-x[-rw-r--r--]dom/base/MultipartBlobImpl.cpp4
-rw-r--r--dom/base/Navigator.cpp18
-rw-r--r--dom/base/Navigator.h4
-rwxr-xr-xdom/base/TimerClamping.cpp35
-rwxr-xr-xdom/base/TimerClamping.h22
-rwxr-xr-x[-rw-r--r--]dom/base/moz.build6
-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/nsContentUtils.cpp4
-rw-r--r--dom/base/nsContentUtils.h3
-rw-r--r--dom/base/nsDocument.cpp14
-rw-r--r--dom/base/nsDocument.h3
-rw-r--r--dom/base/nsDocumentEncoder.cpp2
-rw-r--r--dom/base/nsGkAtomList.h3
-rw-r--r--dom/base/nsGlobalWindow.cpp12
-rw-r--r--dom/base/nsGlobalWindow.h14
-rw-r--r--dom/base/nsIContent.h19
-rw-r--r--dom/base/nsPluginArray.cpp18
-rwxr-xr-x[-rw-r--r--]dom/base/nsXHTMLContentSerializer.cpp2
-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
-rw-r--r--dom/bindings/moz.build2
-rw-r--r--dom/bindings/test/test_promise_rejections_from_jsimplemented.html2
-rw-r--r--dom/browser-element/mochitest/browserElement_ScrollEvent.js4
-rw-r--r--dom/canvas/CanvasRenderingContext2D.cpp4
-rw-r--r--dom/canvas/DocumentRendererChild.cpp94
-rw-r--r--dom/canvas/DocumentRendererChild.h37
-rw-r--r--dom/canvas/DocumentRendererParent.cpp63
-rw-r--r--dom/canvas/DocumentRendererParent.h44
-rw-r--r--dom/canvas/WebGL2ContextState.cpp1
-rw-r--r--dom/canvas/WebGLContextDraw.cpp1
-rw-r--r--dom/canvas/WebGLContextExtensions.cpp4
-rw-r--r--dom/canvas/WebGLFramebuffer.cpp3
-rw-r--r--dom/canvas/WebGLObjectModel.h12
-rw-r--r--dom/canvas/WebGLProgram.cpp1
-rw-r--r--dom/canvas/WebGLTransformFeedback.cpp1
-rw-r--r--dom/canvas/moz.build9
-rw-r--r--dom/canvas/test/webgl-mochitest/mochitest.ini2
-rwxr-xr-x[-rw-r--r--]dom/console/Console.cpp3
-rwxr-xr-x[-rw-r--r--]dom/events/Event.cpp7
-rwxr-xr-x[-rw-r--r--]dom/events/Event.h1
-rw-r--r--dom/events/EventListenerManager.cpp5
-rw-r--r--dom/events/EventNameList.h4
-rw-r--r--dom/events/EventStateManager.cpp5
-rw-r--r--dom/events/test/test_eventTimeStamp.html26
-rw-r--r--dom/html/HTMLAllCollection.cpp7
-rw-r--r--dom/html/HTMLDataListElement.cpp6
-rw-r--r--dom/html/HTMLDataListElement.h4
-rw-r--r--dom/html/HTMLFieldSetElement.cpp4
-rw-r--r--dom/html/HTMLFieldSetElement.h4
-rw-r--r--dom/html/HTMLInputElement.cpp10
-rw-r--r--dom/html/HTMLInputElement.h2
-rw-r--r--dom/html/HTMLLabelElement.cpp23
-rw-r--r--dom/html/HTMLMediaElement.cpp43
-rw-r--r--dom/html/HTMLMediaElement.h10
-rw-r--r--dom/html/HTMLSelectElement.cpp4
-rw-r--r--dom/html/HTMLSelectElement.h2
-rw-r--r--dom/html/HTMLTableRowElement.cpp4
-rw-r--r--dom/html/nsGenericHTMLElement.cpp40
-rw-r--r--dom/html/nsGenericHTMLElement.h6
-rw-r--r--dom/html/nsHTMLDocument.cpp48
-rw-r--r--dom/html/nsHTMLDocument.h11
-rw-r--r--dom/html/test/forms/test_button_attributes_reflection.html9
-rw-r--r--dom/interfaces/security/nsIContentSecurityPolicy.idl6
-rw-r--r--dom/ipc/PBrowser.ipdl20
-rw-r--r--dom/ipc/PDocumentRenderer.ipdl25
-rw-r--r--dom/ipc/TabChild.cpp52
-rw-r--r--dom/ipc/TabChild.h21
-rw-r--r--dom/ipc/TabParent.cpp19
-rw-r--r--dom/ipc/TabParent.h11
-rw-r--r--dom/ipc/moz.build1
-rw-r--r--dom/locales/en-US/chrome/security/csp.properties11
-rwxr-xr-x[-rw-r--r--]dom/media/DOMMediaStream.cpp5
-rw-r--r--dom/media/GraphDriver.cpp1
-rw-r--r--dom/media/MediaData.cpp2
-rw-r--r--dom/media/MediaDecoderOwner.h2
-rw-r--r--dom/media/MediaFormatReader.cpp12
-rw-r--r--dom/media/MediaPrefs.h4
-rw-r--r--dom/media/gtest/moz.build4
-rw-r--r--dom/media/mediasource/TrackBuffersManager.cpp4
-rwxr-xr-x[-rw-r--r--]dom/media/test/test_background_video_suspend.html4
-rwxr-xr-x[-rw-r--r--]dom/media/test/test_streams_element_capture.html3
-rwxr-xr-x[-rw-r--r--]dom/media/test/test_streams_element_capture_createObjectURL.html3
-rwxr-xr-x[-rw-r--r--]dom/media/webaudio/AudioContext.cpp5
-rwxr-xr-x[-rw-r--r--]dom/performance/Performance.cpp5
-rw-r--r--dom/performance/PerformanceMainThread.cpp5
-rw-r--r--dom/performance/PerformanceResourceTiming.h6
-rwxr-xr-x[-rw-r--r--]dom/performance/PerformanceTiming.cpp87
-rwxr-xr-x[-rw-r--r--]dom/performance/PerformanceTiming.h30
-rw-r--r--dom/performance/tests/test_performance_user_timing.js2
-rw-r--r--dom/performance/tests/test_worker_performance_now.js48
-rw-r--r--dom/push/moz.build2
-rw-r--r--dom/security/nsCSPContext.cpp25
-rw-r--r--dom/security/nsCSPParser.cpp49
-rw-r--r--dom/security/nsCSPParser.h19
-rw-r--r--dom/security/nsCSPUtils.cpp102
-rw-r--r--dom/security/nsCSPUtils.h53
-rw-r--r--dom/security/test/csp/file_frame_src.js14
-rw-r--r--dom/security/test/csp/file_frame_src_child_governs.html10
-rw-r--r--dom/security/test/csp/file_frame_src_frame_governs.html10
-rw-r--r--dom/security/test/csp/file_frame_src_inner.html5
-rw-r--r--dom/security/test/csp/file_ignore_xfo.html10
-rw-r--r--dom/security/test/csp/file_ignore_xfo.html^headers^3
-rw-r--r--dom/security/test/csp/file_image_nonce.html39
-rw-r--r--dom/security/test/csp/file_image_nonce.html^headers^2
-rw-r--r--dom/security/test/csp/file_punycode_host_src.js2
-rw-r--r--dom/security/test/csp/file_punycode_host_src.sjs45
-rw-r--r--dom/security/test/csp/file_ro_ignore_xfo.html10
-rw-r--r--dom/security/test/csp/file_ro_ignore_xfo.html^headers^3
-rw-r--r--dom/security/test/csp/file_spawn_service_worker.js1
-rw-r--r--dom/security/test/csp/file_spawn_shared_worker.js7
-rw-r--r--dom/security/test/csp/file_spawn_worker.js1
-rw-r--r--dom/security/test/csp/file_upgrade_insecure_navigation.sjs79
-rw-r--r--dom/security/test/csp/file_websocket_explicit.html31
-rw-r--r--dom/security/test/csp/file_websocket_self.html31
-rw-r--r--dom/security/test/csp/file_websocket_self_wsh.py7
-rw-r--r--dom/security/test/csp/file_worker_src.js52
-rw-r--r--dom/security/test/csp/file_worker_src_child_governs.html9
-rw-r--r--dom/security/test/csp/file_worker_src_script_governs.html9
-rw-r--r--dom/security/test/csp/file_worker_src_worker_governs.html9
-rw-r--r--dom/security/test/csp/mochitest.ini33
-rw-r--r--dom/security/test/csp/test_child-src_worker.html6
-rw-r--r--dom/security/test/csp/test_frame_src.html84
-rw-r--r--dom/security/test/csp/test_ignore_xfo.html59
-rw-r--r--dom/security/test/csp/test_image_nonce.html60
-rw-r--r--dom/security/test/csp/test_punycode_host_src.html81
-rw-r--r--dom/security/test/csp/test_upgrade_insecure_navigation.html103
-rw-r--r--dom/security/test/csp/test_websocket_self.html61
-rw-r--r--dom/security/test/csp/test_worker_src.html94
-rw-r--r--dom/security/test/gtest/TestCSPParser.cpp6
-rw-r--r--dom/svg/DOMSVGPathSegList.cpp21
-rw-r--r--dom/svg/SVGGradientElement.cpp9
-rw-r--r--dom/svg/SVGGradientElement.h7
-rwxr-xr-x[-rw-r--r--]dom/tests/browser/browser.ini2
-rwxr-xr-xdom/tests/browser/browser_performanceAPI.js139
-rwxr-xr-xdom/tests/browser/file_workerPerformance.js65
-rwxr-xr-x[-rw-r--r--]dom/tests/mochitest/general/mochitest.ini3
-rw-r--r--dom/tests/mochitest/general/test_domWindowUtils_scrollXY.html12
-rwxr-xr-xdom/tests/mochitest/general/test_reduce_time_precision.html143
-rwxr-xr-xdom/tests/mochitest/general/worker_child.js28
-rwxr-xr-xdom/tests/mochitest/general/worker_grandchild.js10
-rw-r--r--dom/url/URL.h6
-rw-r--r--dom/url/tests/test_url.html6
-rw-r--r--dom/webidl/CSPDictionaries.webidl1
-rw-r--r--dom/webidl/Document.webidl3
-rw-r--r--dom/webidl/HTMLButtonElement.webidl3
-rw-r--r--dom/webidl/HTMLInputElement.webidl2
-rw-r--r--dom/webidl/HTMLMediaElement.webidl2
-rw-r--r--dom/webidl/HTMLMeterElement.webidl5
-rw-r--r--dom/webidl/HTMLOutputElement.webidl3
-rw-r--r--dom/webidl/HTMLProgressElement.webidl6
-rw-r--r--dom/webidl/HTMLSelectElement.webidl2
-rw-r--r--dom/webidl/HTMLTextAreaElement.webidl2
-rw-r--r--dom/webidl/Navigator.webidl2
-rw-r--r--dom/webidl/PerformanceTiming.webidl3
-rw-r--r--dom/webidl/SVGRadialGradientElement.webidl4
-rw-r--r--dom/webidl/URL.webidl5
-rw-r--r--dom/webidl/Window.webidl12
-rw-r--r--dom/webidl/moz.build4
-rw-r--r--dom/workers/WorkerScope.cpp7
-rw-r--r--dom/workers/Workers.h8
-rw-r--r--dom/xul/XULDocument.cpp14
-rw-r--r--dom/xul/XULDocument.h2
171 files changed, 2416 insertions, 784 deletions
diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp
index 886acc670..9ced64c0d 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,7 +177,7 @@ nsIContent::DoGetClasses() const
}
}
- return AsElement()->GetParsedAttr(nsGkAtoms::_class);
+ return GetParsedAttr(nsGkAtoms::_class);
}
NS_IMETHODIMP
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/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp
index 293177ce7..79f6cff51 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;
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/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/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 0bc9902e4..0fb345d22 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',
]
@@ -363,6 +364,7 @@ UNIFIED_SOURCES += [
'TextInputProcessor.cpp',
'ThirdPartyUtil.cpp',
'Timeout.cpp',
+ 'TimerClamping.cpp',
'TreeWalker.cpp',
'WebKitCSSMatrix.cpp',
'WebSocket.cpp',
@@ -411,7 +413,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 +474,7 @@ include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
-if CONFIG['MOZ_BUILD_APP'] in ['mobile/android', 'xulrunner'] or CONFIG['MOZ_PHOENIX']:
+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/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp
index 1cc352685..02c6bf1de 100644
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -6287,11 +6287,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 f688eeecf..0a293d73e 100644
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -2753,7 +2753,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,
diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp
index 8e6920a0e..eaea49b02 100644
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -61,6 +61,7 @@
#include "nsGenericHTMLElement.h"
#include "mozilla/dom/CDATASection.h"
#include "mozilla/dom/ProcessingInstruction.h"
+#include "nsDSURIContentListener.h"
#include "nsDOMString.h"
#include "nsNodeUtils.h"
#include "nsLayoutUtils.h" // for GetFrameForPoint
@@ -2456,6 +2457,15 @@ nsDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
NS_ENSURE_SUCCESS(rv, rv);
}
+ // XFO needs to be checked after CSP because it is ignored if
+ // the CSP defines frame-ancestors.
+ if (!nsDSURIContentListener::CheckFrameOptions(aChannel, docShell, NodePrincipal())) {
+ MOZ_LOG(gCspPRLog, LogLevel::Debug,
+ ("XFO doesn't like frame's ancestry, not loading."));
+ // stop! ERROR page!
+ aChannel->Cancel(NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION);
+ }
+
return NS_OK;
}
@@ -4330,6 +4340,7 @@ nsDocument::SetScopeObject(nsIGlobalObject* aGlobal)
}
}
+#ifdef MOZ_EME
static void
CheckIfContainsEMEContent(nsISupports* aSupports, void* aContainsEME)
{
@@ -4353,6 +4364,7 @@ nsDocument::ContainsEMEContent()
static_cast<void*>(&containsEME));
return containsEME;
}
+#endif // MOZ_EME
static void
CheckIfContainsMSEContent(nsISupports* aSupports, void* aContainsMSE)
@@ -8380,11 +8392,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.
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/nsGkAtomList.h b/dom/base/nsGkAtomList.h
index 0b76b2bea..e4ae7ede8 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")
@@ -950,6 +951,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")
@@ -1449,6 +1451,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")
diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp
index 8ff4b84ce..f784031f6 100644
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -6187,7 +6187,7 @@ nsGlobalWindow::GetScrollMaxY(ErrorResult& aError)
FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideBottom), aError, 0);
}
-CSSIntPoint
+CSSPoint
nsGlobalWindow::GetScrollXY(bool aDoFlush)
{
MOZ_ASSERT(IsOuterWindow());
@@ -6211,30 +6211,30 @@ nsGlobalWindow::GetScrollXY(bool aDoFlush)
return GetScrollXY(true);
}
- return sf->GetScrollPositionCSSPixels();
+ return CSSPoint::FromAppUnits(scrollPos);
}
-int32_t
+double
nsGlobalWindow::GetScrollXOuter()
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
return GetScrollXY(false).x;
}
-int32_t
+double
nsGlobalWindow::GetScrollX(ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(GetScrollXOuter, (), aError, 0);
}
-int32_t
+double
nsGlobalWindow::GetScrollYOuter()
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
return GetScrollXY(false).y;
}
-int32_t
+double
nsGlobalWindow::GetScrollY(ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(GetScrollYOuter, (), aError, 0);
diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h
index eab91c2e4..dbceeab74 100644
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -1050,15 +1050,15 @@ public:
void SetInnerHeight(JSContext* aCx, JS::Handle<JS::Value> aValue,
mozilla::dom::CallerType aCallerType,
mozilla::ErrorResult& aError);
- int32_t GetScrollXOuter();
- int32_t GetScrollX(mozilla::ErrorResult& aError);
- int32_t GetPageXOffset(mozilla::ErrorResult& aError)
+ double GetScrollXOuter();
+ double GetScrollX(mozilla::ErrorResult& aError);
+ double GetPageXOffset(mozilla::ErrorResult& aError)
{
return GetScrollX(aError);
}
- int32_t GetScrollYOuter();
- int32_t GetScrollY(mozilla::ErrorResult& aError);
- int32_t GetPageYOffset(mozilla::ErrorResult& aError)
+ double GetScrollYOuter();
+ double GetScrollY(mozilla::ErrorResult& aError);
+ double GetPageYOffset(mozilla::ErrorResult& aError)
{
return GetScrollY(aError);
}
@@ -1579,7 +1579,7 @@ public:
// If aDoFlush is true, we'll flush our own layout; otherwise we'll try to
// just flush our parent and only flush ourselves if we think we need to.
// Outer windows only.
- mozilla::CSSIntPoint GetScrollXY(bool aDoFlush);
+ mozilla::CSSPoint GetScrollXY(bool aDoFlush);
int32_t GetScrollBoundaryOuter(mozilla::Side aSide);
diff --git a/dom/base/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/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/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/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) {
diff --git a/dom/bindings/moz.build b/dom/bindings/moz.build
index eb00482c6..f1ce9e276 100644
--- a/dom/bindings/moz.build
+++ b/dom/bindings/moz.build
@@ -139,7 +139,7 @@ FINAL_LIBRARY = 'xul'
SPHINX_TREES['webidl'] = 'docs'
SPHINX_PYTHON_PACKAGE_DIRS += ['mozwebidlcodegen']
-if CONFIG['MOZ_BUILD_APP'] in ['mobile/android', 'xulrunner'] or CONFIG['MOZ_PHOENIX']:
+if CONFIG['MOZ_PHOENIX'] or CONFIG['MOZ_FENNEC'] or CONFIG['MOZ_XULRUNNER']:
# This is needed for Window.webidl
DEFINES['HAVE_SIDEBAR'] = True
diff --git a/dom/bindings/test/test_promise_rejections_from_jsimplemented.html b/dom/bindings/test/test_promise_rejections_from_jsimplemented.html
index 5428030c5..68de079ed 100644
--- a/dom/bindings/test/test_promise_rejections_from_jsimplemented.html
+++ b/dom/bindings/test/test_promise_rejections_from_jsimplemented.html
@@ -93,7 +93,7 @@ doTest@${ourFile}:56:7
checkExn.bind(null, 90, "ReferenceError",
"thereIsNoSuchContentFunction3 is not defined",
undefined, ourFile, 6,
- `doTest/<.then@${ourFile}:90:32
+ `then@${ourFile}:90:32
` + (asyncStack ? `Async*doTest@${ourFile}:89:7\n` + parentFrame : ""))),
t.testPromiseWithDOMExceptionThrowingPromiseInit().then(
ensurePromiseFail.bind(null, 7),
diff --git a/dom/browser-element/mochitest/browserElement_ScrollEvent.js b/dom/browser-element/mochitest/browserElement_ScrollEvent.js
index 5c4b4dcf9..06dc91b86 100644
--- a/dom/browser-element/mochitest/browserElement_ScrollEvent.js
+++ b/dom/browser-element/mochitest/browserElement_ScrollEvent.js
@@ -16,8 +16,8 @@ function runTest() {
iframe.addEventListener("mozbrowserscroll", function(e) {
ok(true, "got mozbrowserscroll event.");
ok(e.detail, "event.detail is not null.");
- ok(e.detail.top === 4000, "top position is correct.");
- ok(e.detail.left === 4000, "left position is correct.");
+ ok(Math.round(e.detail.top) == 4000, "top position is correct.");
+ ok(Math.round(e.detail.left) == 4000, "left position is correct.");
SimpleTest.finish();
});
diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp
index b0a430fe4..15df2b337 100644
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -92,8 +92,6 @@
#include "mozilla/gfx/PathHelpers.h"
#include "mozilla/gfx/DataSurfaceHelpers.h"
#include "mozilla/gfx/PatternHelpers.h"
-#include "mozilla/ipc/DocumentRendererParent.h"
-#include "mozilla/ipc/PDocumentRendererParent.h"
#include "mozilla/layers/PersistentBufferProvider.h"
#include "mozilla/MathAlgorithms.h"
#include "mozilla/Preferences.h"
@@ -4977,10 +4975,12 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage,
return;
}
+#ifdef MOZ_EME
if (video->ContainsRestrictedContent()) {
aError.Throw(NS_ERROR_NOT_AVAILABLE);
return;
}
+#endif
uint16_t readyState;
if (NS_SUCCEEDED(video->GetReadyState(&readyState)) &&
diff --git a/dom/canvas/DocumentRendererChild.cpp b/dom/canvas/DocumentRendererChild.cpp
deleted file mode 100644
index 15dd5fc52..000000000
--- a/dom/canvas/DocumentRendererChild.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/ipc/DocumentRendererChild.h"
-
-#include "base/basictypes.h"
-
-#include "gfx2DGlue.h"
-#include "gfxPattern.h"
-#include "mozilla/gfx/2D.h"
-#include "mozilla/RefPtr.h"
-#include "nsPIDOMWindow.h"
-#include "nsIDOMWindow.h"
-#include "nsIDocShell.h"
-#include "nsIInterfaceRequestorUtils.h"
-#include "nsComponentManagerUtils.h"
-#include "nsCSSParser.h"
-#include "nsPresContext.h"
-#include "nsCOMPtr.h"
-#include "nsColor.h"
-#include "gfxContext.h"
-#include "nsLayoutUtils.h"
-#include "nsContentUtils.h"
-#include "nsCSSValue.h"
-#include "nsRuleNode.h"
-#include "mozilla/gfx/Matrix.h"
-
-using namespace mozilla;
-using namespace mozilla::gfx;
-using namespace mozilla::ipc;
-
-DocumentRendererChild::DocumentRendererChild()
-{}
-
-DocumentRendererChild::~DocumentRendererChild()
-{}
-
-bool
-DocumentRendererChild::RenderDocument(nsPIDOMWindowOuter* window,
- const nsRect& documentRect,
- const mozilla::gfx::Matrix& transform,
- const nsString& aBGColor,
- uint32_t renderFlags,
- bool flushLayout,
- const nsIntSize& renderSize,
- nsCString& data)
-{
- if (flushLayout)
- nsContentUtils::FlushLayoutForTree(window);
-
- RefPtr<nsPresContext> presContext;
- if (window) {
- nsIDocShell* docshell = window->GetDocShell();
- if (docshell) {
- docshell->GetPresContext(getter_AddRefs(presContext));
- }
- }
- if (!presContext)
- return false;
-
- nsCSSParser parser;
- nsCSSValue bgColorValue;
- if (!parser.ParseColorString(aBGColor, nullptr, 0, bgColorValue)) {
- return false;
- }
-
- nscolor bgColor;
- if (!nsRuleNode::ComputeColor(bgColorValue, presContext, nullptr, bgColor)) {
- return false;
- }
-
- // Draw directly into the output array.
- data.SetLength(renderSize.width * renderSize.height * 4);
-
- RefPtr<DrawTarget> dt =
- Factory::CreateDrawTargetForData(BackendType::CAIRO,
- reinterpret_cast<uint8_t*>(data.BeginWriting()),
- IntSize(renderSize.width, renderSize.height),
- 4 * renderSize.width,
- SurfaceFormat::B8G8R8A8);
- if (!dt || !dt->IsValid()) {
- gfxWarning() << "DocumentRendererChild::RenderDocument failed to Factory::CreateDrawTargetForData";
- return false;
- }
- RefPtr<gfxContext> ctx = gfxContext::CreateOrNull(dt);
- MOZ_ASSERT(ctx); // already checked the draw target above
- ctx->SetMatrix(mozilla::gfx::ThebesMatrix(transform));
-
- nsCOMPtr<nsIPresShell> shell = presContext->PresShell();
- shell->RenderDocument(documentRect, renderFlags, bgColor, ctx);
-
- return true;
-}
diff --git a/dom/canvas/DocumentRendererChild.h b/dom/canvas/DocumentRendererChild.h
deleted file mode 100644
index 463ba2707..000000000
--- a/dom/canvas/DocumentRendererChild.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_DocumentRendererChild
-#define mozilla_dom_DocumentRendererChild
-
-#include "mozilla/ipc/PDocumentRendererChild.h"
-#include "nsString.h"
-#include "gfxContext.h"
-
-class nsIDOMWindow;
-
-namespace mozilla {
-namespace ipc {
-
-class DocumentRendererChild : public PDocumentRendererChild
-{
-public:
- DocumentRendererChild();
- virtual ~DocumentRendererChild();
-
- bool RenderDocument(nsPIDOMWindowOuter* window,
- const nsRect& documentRect, const gfx::Matrix& transform,
- const nsString& bgcolor,
- uint32_t renderFlags, bool flushLayout,
- const nsIntSize& renderSize, nsCString& data);
-
-private:
-
- DISALLOW_EVIL_CONSTRUCTORS(DocumentRendererChild);
-};
-
-} // namespace ipc
-} // namespace mozilla
-
-#endif
diff --git a/dom/canvas/DocumentRendererParent.cpp b/dom/canvas/DocumentRendererParent.cpp
deleted file mode 100644
index d9578ac4e..000000000
--- a/dom/canvas/DocumentRendererParent.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/ipc/DocumentRendererParent.h"
-
-#include "gfx2DGlue.h"
-#include "mozilla/gfx/2D.h"
-#include "mozilla/gfx/PathHelpers.h"
-#include "mozilla/RefPtr.h"
-#include "nsICanvasRenderingContextInternal.h"
-
-using namespace mozilla;
-using namespace mozilla::gfx;
-using namespace mozilla::ipc;
-
-DocumentRendererParent::DocumentRendererParent()
-{}
-
-DocumentRendererParent::~DocumentRendererParent()
-{}
-
-void DocumentRendererParent::SetCanvasContext(nsICanvasRenderingContextInternal* aCanvas,
- gfxContext* ctx)
-{
- mCanvas = aCanvas;
- mCanvasContext = ctx;
-}
-
-void DocumentRendererParent::DrawToCanvas(const nsIntSize& aSize,
- const nsCString& aData)
-{
- if (!mCanvas || !mCanvasContext)
- return;
-
- DrawTarget* drawTarget = mCanvasContext->GetDrawTarget();
- Rect rect(0, 0, aSize.width, aSize.height);
- MaybeSnapToDevicePixels(rect, *drawTarget, true);
- RefPtr<DataSourceSurface> dataSurface =
- Factory::CreateWrappingDataSourceSurface(reinterpret_cast<uint8_t*>(const_cast<nsCString&>(aData).BeginWriting()),
- aSize.width * 4,
- IntSize(aSize.width, aSize.height),
- SurfaceFormat::B8G8R8A8);
- SurfacePattern pattern(dataSurface, ExtendMode::CLAMP);
- drawTarget->FillRect(rect, pattern);
-
- gfxRect damageRect = mCanvasContext->UserToDevice(ThebesRect(rect));
- mCanvas->Redraw(damageRect);
-}
-
-void
-DocumentRendererParent::ActorDestroy(ActorDestroyReason aWhy)
-{
- // Implement me! Bug 1005139
-}
-
-bool
-DocumentRendererParent::Recv__delete__(const nsIntSize& renderedSize,
- const nsCString& data)
-{
- DrawToCanvas(renderedSize, data);
- return true;
-}
diff --git a/dom/canvas/DocumentRendererParent.h b/dom/canvas/DocumentRendererParent.h
deleted file mode 100644
index 432aa8264..000000000
--- a/dom/canvas/DocumentRendererParent.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_DocumentRendererParent
-#define mozilla_dom_DocumentRendererParent
-
-#include "mozilla/ipc/PDocumentRendererParent.h"
-#include "nsCOMPtr.h"
-#include "nsString.h"
-#include "gfxContext.h"
-
-class nsICanvasRenderingContextInternal;
-
-namespace mozilla {
-namespace ipc {
-
-class DocumentRendererParent : public PDocumentRendererParent
-{
-public:
- DocumentRendererParent();
- virtual ~DocumentRendererParent();
-
- void SetCanvasContext(nsICanvasRenderingContextInternal* aCanvas,
- gfxContext* ctx);
- void DrawToCanvas(const nsIntSize& renderedSize,
- const nsCString& aData);
-
- virtual void ActorDestroy(ActorDestroyReason aWhy) override;
-
- virtual bool Recv__delete__(const nsIntSize& renderedSize,
- const nsCString& data) override;
-
-private:
- nsCOMPtr<nsICanvasRenderingContextInternal> mCanvas;
- RefPtr<gfxContext> mCanvasContext;
-
- DISALLOW_EVIL_CONSTRUCTORS(DocumentRendererParent);
-};
-
-} // namespace ipc
-} // namespace mozilla
-
-#endif
diff --git a/dom/canvas/WebGL2ContextState.cpp b/dom/canvas/WebGL2ContextState.cpp
index be0a7a3cb..e6283b12d 100644
--- a/dom/canvas/WebGL2ContextState.cpp
+++ b/dom/canvas/WebGL2ContextState.cpp
@@ -7,6 +7,7 @@
#include "WebGL2Context.h"
#include "GLContext.h"
+#include "GLScreenBuffer.h"
#include "WebGLBuffer.h"
#include "WebGLContextUtils.h"
#include "WebGLFramebuffer.h"
diff --git a/dom/canvas/WebGLContextDraw.cpp b/dom/canvas/WebGLContextDraw.cpp
index 66fca7689..867e47cbd 100644
--- a/dom/canvas/WebGLContextDraw.cpp
+++ b/dom/canvas/WebGLContextDraw.cpp
@@ -16,6 +16,7 @@
#include "WebGLRenderbuffer.h"
#include "WebGLShader.h"
#include "WebGLTexture.h"
+#include "WebGLTransformFeedback.h"
#include "WebGLVertexArray.h"
#include "WebGLVertexAttribData.h"
diff --git a/dom/canvas/WebGLContextExtensions.cpp b/dom/canvas/WebGLContextExtensions.cpp
index 28ba14fa2..4a5a23274 100644
--- a/dom/canvas/WebGLContextExtensions.cpp
+++ b/dom/canvas/WebGLContextExtensions.cpp
@@ -89,6 +89,8 @@ bool WebGLContext::IsExtensionSupported(dom::CallerType callerType,
if (allowPrivilegedExts) {
switch (ext) {
+ case WebGLExtensionID::EXT_disjoint_timer_query:
+ return WebGLExtensionDisjointTimerQuery::IsSupported(this);
case WebGLExtensionID::WEBGL_debug_renderer_info:
return true;
case WebGLExtensionID::WEBGL_debug_shaders:
@@ -112,8 +114,6 @@ WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
switch (ext) {
// In alphabetical order
// EXT_
- case WebGLExtensionID::EXT_disjoint_timer_query:
- return WebGLExtensionDisjointTimerQuery::IsSupported(this);
case WebGLExtensionID::EXT_texture_filter_anisotropic:
return gl->IsExtensionSupported(gl::GLContext::EXT_texture_filter_anisotropic);
diff --git a/dom/canvas/WebGLFramebuffer.cpp b/dom/canvas/WebGLFramebuffer.cpp
index 35efa4f16..0abaf3dd7 100644
--- a/dom/canvas/WebGLFramebuffer.cpp
+++ b/dom/canvas/WebGLFramebuffer.cpp
@@ -17,7 +17,9 @@
#include "WebGLContextUtils.h"
#include "WebGLExtensions.h"
#include "WebGLRenderbuffer.h"
+#include "WebGLShader.h"
#include "WebGLTexture.h"
+#include "WebGLObjectModel.h"
namespace mozilla {
@@ -1940,6 +1942,7 @@ ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& callback,
}
}
+
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLFramebuffer,
mDepthAttachment,
mStencilAttachment,
diff --git a/dom/canvas/WebGLObjectModel.h b/dom/canvas/WebGLObjectModel.h
index e19d2fd8e..b18b790c0 100644
--- a/dom/canvas/WebGLObjectModel.h
+++ b/dom/canvas/WebGLObjectModel.h
@@ -15,6 +15,7 @@ namespace mozilla {
template<typename> class LinkedList;
class WebGLContext;
+
////
// This class is a mixin for objects that are tied to a specific
@@ -355,6 +356,16 @@ ImplCycleCollectionUnlink(mozilla::WebGLRefPtr<T>& field)
template <typename T>
inline void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& callback,
+ mozilla::WebGLRefPtr<T>& field,
+ const char* name,
+ uint32_t flags = 0)
+{
+ CycleCollectionNoteChild(callback, field.get(), name, flags);
+}
+
+template <typename T>
+inline void
+ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& callback,
const mozilla::WebGLRefPtr<T>& field,
const char* name,
uint32_t flags = 0)
@@ -362,4 +373,5 @@ ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& callback,
CycleCollectionNoteChild(callback, field.get(), name, flags);
}
+
#endif
diff --git a/dom/canvas/WebGLProgram.cpp b/dom/canvas/WebGLProgram.cpp
index fa7997f22..9b204358b 100644
--- a/dom/canvas/WebGLProgram.cpp
+++ b/dom/canvas/WebGLProgram.cpp
@@ -17,6 +17,7 @@
#include "WebGLTransformFeedback.h"
#include "WebGLUniformLocation.h"
#include "WebGLValidateStrings.h"
+#include "WebGLObjectModel.h"
namespace mozilla {
diff --git a/dom/canvas/WebGLTransformFeedback.cpp b/dom/canvas/WebGLTransformFeedback.cpp
index feec581ea..78e366531 100644
--- a/dom/canvas/WebGLTransformFeedback.cpp
+++ b/dom/canvas/WebGLTransformFeedback.cpp
@@ -8,6 +8,7 @@
#include "GLContext.h"
#include "mozilla/dom/WebGL2RenderingContextBinding.h"
#include "WebGL2Context.h"
+#include "WebGLProgram.h"
namespace mozilla {
diff --git a/dom/canvas/moz.build b/dom/canvas/moz.build
index 2b2ceba52..f7555b33d 100644
--- a/dom/canvas/moz.build
+++ b/dom/canvas/moz.build
@@ -25,11 +25,6 @@ EXPORTS += [
'nsICanvasRenderingContextInternal.h',
]
-EXPORTS.mozilla.ipc += [
- 'DocumentRendererChild.h',
- 'DocumentRendererParent.h',
-]
-
EXPORTS.mozilla.dom += [
'CanvasGradient.h',
'CanvasPath.h',
@@ -52,8 +47,6 @@ UNIFIED_SOURCES += [
'CanvasRenderingContext2D.cpp',
'CanvasRenderingContextHelper.cpp',
'CanvasUtils.cpp',
- 'DocumentRendererChild.cpp',
- 'DocumentRendererParent.cpp',
'ImageBitmap.cpp',
'ImageBitmapColorUtils.cpp',
'ImageBitmapRenderingContext.cpp',
@@ -162,7 +155,7 @@ SOURCES += [
]
# Suppress warnings from third-party code.
-if CONFIG['CLANG_CXX']:
+if CONFIG['CLANG_CXX'] or CONFIG['GNU_CXX']:
SOURCES['MurmurHash3.cpp'].flags += ['-Wno-implicit-fallthrough']
LOCAL_INCLUDES += [
diff --git a/dom/canvas/test/webgl-mochitest/mochitest.ini b/dom/canvas/test/webgl-mochitest/mochitest.ini
index d5bc8701d..ddd0dd762 100644
--- a/dom/canvas/test/webgl-mochitest/mochitest.ini
+++ b/dom/canvas/test/webgl-mochitest/mochitest.ini
@@ -14,7 +14,7 @@ fail-if = (os == 'android')
[ensure-exts/test_EXT_color_buffer_half_float.html]
fail-if = (os == 'android')
[ensure-exts/test_EXT_disjoint_timer_query.html]
-fail-if = (os == 'android') || (os == 'mac') || (os == 'win' && os_version == '5.1')
+fail-if = 1
[ensure-exts/test_EXT_frag_depth.html]
fail-if = (os == 'android')
[ensure-exts/test_EXT_sRGB.html]
diff --git a/dom/console/Console.cpp b/dom/console/Console.cpp
index 9ede26501..79e3eadc5 100644..100755
--- a/dom/console/Console.cpp
+++ b/dom/console/Console.cpp
@@ -30,6 +30,7 @@
#include "nsContentUtils.h"
#include "nsDocShell.h"
#include "nsProxyRelease.h"
+#include "mozilla/TimerClamping.h"
#include "mozilla/ConsoleTimelineMarker.h"
#include "mozilla/TimestampTimelineMarker.h"
@@ -1338,7 +1339,7 @@ Console::MethodInternal(JSContext* aCx, MethodName aMethodName,
TimeDuration duration =
mozilla::TimeStamp::Now() - workerPrivate->NowBaseTimeStamp();
- monotonicTimer = duration.ToMilliseconds();
+ monotonicTimer = TimerClamping::ReduceMsTimeValue(duration.ToMilliseconds());
}
}
diff --git a/dom/events/Event.cpp b/dom/events/Event.cpp
index a85a0d66b..2af34136e 100644..100755
--- a/dom/events/Event.cpp
+++ b/dom/events/Event.cpp
@@ -32,6 +32,7 @@
#include "nsJSEnvironment.h"
#include "nsLayoutUtils.h"
#include "nsPIWindowRoot.h"
+#include "mozilla/TimerClamping.h"
#include "WorkerPrivate.h"
namespace mozilla {
@@ -1085,6 +1086,12 @@ Event::DefaultPrevented(JSContext* aCx) const
double
Event::TimeStamp() const
{
+ return TimerClamping::ReduceMsTimeValue(TimeStampImpl());
+}
+
+double
+Event::TimeStampImpl() const
+{
if (!sReturnHighResTimeStamp) {
return static_cast<double>(mEvent->mTime);
}
diff --git a/dom/events/Event.h b/dom/events/Event.h
index 4ac6a68d5..c28226e8a 100644..100755
--- a/dom/events/Event.h
+++ b/dom/events/Event.h
@@ -62,6 +62,7 @@ private:
void ConstructorInit(EventTarget* aOwner,
nsPresContext* aPresContext,
WidgetEvent* aEvent);
+ double TimeStampImpl() const;
public:
static Event* FromSupports(nsISupports* aSupports)
diff --git a/dom/events/EventListenerManager.cpp b/dom/events/EventListenerManager.cpp
index c8db4f2a1..a8c48ede8 100644
--- a/dom/events/EventListenerManager.cpp
+++ b/dom/events/EventListenerManager.cpp
@@ -996,14 +996,12 @@ EventListenerManager::CompileEventHandlerInternal(Listener* aListener,
}
aListener = nullptr;
- uint32_t lineNo = 0;
nsAutoCString url (NS_LITERAL_CSTRING("-moz-evil:lying-event-listener"));
MOZ_ASSERT(body);
MOZ_ASSERT(aElement);
nsIURI *uri = aElement->OwnerDoc()->GetDocumentURI();
if (uri) {
uri->GetSpec(url);
- lineNo = 1;
}
nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(mTarget);
@@ -1073,8 +1071,9 @@ EventListenerManager::CompileEventHandlerInternal(Listener* aListener,
return NS_ERROR_FAILURE;
}
JS::CompileOptions options(cx);
+ // Use line 0 to make the function body starts from line 1.
options.setIntroductionType("eventHandler")
- .setFileAndLine(url.get(), lineNo)
+ .setFileAndLine(url.get(), 0)
.setVersion(JSVERSION_DEFAULT)
.setElement(&v.toObject())
.setElementAttributeName(jsStr);
diff --git a/dom/events/EventNameList.h b/dom/events/EventNameList.h
index b1be6dd76..ba2427623 100644
--- a/dom/events/EventNameList.h
+++ b/dom/events/EventNameList.h
@@ -674,6 +674,10 @@ DOCUMENT_ONLY_EVENT(selectionchange,
eSelectionChange,
EventNameType_HTMLXUL,
eBasicEventClass)
+DOCUMENT_ONLY_EVENT(visibilitychange,
+ eVisibilityChange,
+ EventNameType_HTMLXUL,
+ eBasicEventClass)
NON_IDL_EVENT(MozMouseHittest,
eMouseHitTest,
diff --git a/dom/events/EventStateManager.cpp b/dom/events/EventStateManager.cpp
index 659629066..c23cdb575 100644
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -4151,9 +4151,10 @@ EventStateManager::NotifyMouseOver(WidgetMouseEvent* aMouseEvent,
// content associated with our subdocument.
EnsureDocument(mPresContext);
if (nsIDocument *parentDoc = mDocument->GetParentDocument()) {
- if (nsIContent *docContent = parentDoc->FindContentForSubDocument(mDocument)) {
+ if (nsCOMPtr<nsIContent> docContent =
+ parentDoc->FindContentForSubDocument(mDocument)) {
if (nsIPresShell *parentShell = parentDoc->GetShell()) {
- EventStateManager* parentESM =
+ RefPtr<EventStateManager> parentESM =
parentShell->GetPresContext()->EventStateManager();
parentESM->NotifyMouseOver(aMouseEvent, docContent);
}
diff --git a/dom/events/test/test_eventTimeStamp.html b/dom/events/test/test_eventTimeStamp.html
index a3d096432..107a21f87 100644
--- a/dom/events/test/test_eventTimeStamp.html
+++ b/dom/events/test/test_eventTimeStamp.html
@@ -60,8 +60,8 @@ function testRegularEvents() {
var timeBeforeEvent = window.performance.now();
window.addEventListener("load", function(evt) {
var timeAfterEvent = window.performance.now();
- ok(evt.timeStamp > timeBeforeEvent &&
- evt.timeStamp < timeAfterEvent,
+ ok(evt.timeStamp >= timeBeforeEvent &&
+ evt.timeStamp <= timeAfterEvent,
"Event timestamp (" + evt.timeStamp + ") is in expected range: (" +
timeBeforeEvent + ", " + timeAfterEvent + ")");
testWorkerEvents();
@@ -74,11 +74,12 @@ function testWorkerEvents() {
var worker = new Worker(window.URL.createObjectURL(blob));
worker.onmessage = function(evt) {
var timeAfterEvent = window.performance.now();
- ok(evt.data > timeBeforeEvent &&
- evt.data < timeAfterEvent,
- "Event timestamp in dedicated worker (" + evt.data +
- ") is in expected range: (" +
- timeBeforeEvent + ", " + timeAfterEvent + ")");
+ // Comparing times across timelines may break now
+ // ok(evt.data >= timeBeforeEvent &&
+ // evt.data <= timeAfterEvent,
+ // "Event timestamp in dedicated worker (" + evt.data +
+ // ") is in expected range: (" +
+ // timeBeforeEvent + ", " + timeAfterEvent + ")");
worker.terminate();
testSharedWorkerEvents();
};
@@ -97,11 +98,12 @@ function testSharedWorkerEvents() {
var worker = new SharedWorker(window.URL.createObjectURL(blob));
worker.port.onmessage = function(evt) {
var timeAfterEvent = window.performance.now();
- ok(evt.data > 0 &&
- evt.data < timeAfterEvent - timeBeforeWorkerCreation,
- "Event timestamp in shared worker (" + evt.data +
- ") is in expected range: (0, " +
- (timeAfterEvent - timeBeforeWorkerCreation) + ")");
+ // Comparing times across timelines may break now
+ // ok(evt.data >= 0 &&
+ // evt.data <= timeAfterEvent - timeBeforeWorkerCreation,
+ // "Event timestamp in shared worker (" + evt.data +
+ // ") is in expected range: (0, " +
+ // (timeAfterEvent - timeBeforeWorkerCreation) + ")");
worker.port.close();
finishTests();
};
diff --git a/dom/html/HTMLAllCollection.cpp b/dom/html/HTMLAllCollection.cpp
index afa160e0c..6305cce31 100644
--- a/dom/html/HTMLAllCollection.cpp
+++ b/dom/html/HTMLAllCollection.cpp
@@ -8,6 +8,7 @@
#include "mozilla/dom/HTMLAllCollectionBinding.h"
#include "mozilla/dom/Nullable.h"
+#include "mozilla/dom/Element.h"
#include "nsHTMLDocument.h"
namespace mozilla {
@@ -86,14 +87,14 @@ IsAllNamedElement(nsIContent* aContent)
}
static bool
-DocAllResultMatch(nsIContent* aContent, int32_t aNamespaceID, nsIAtom* aAtom,
+DocAllResultMatch(Element* aElement, int32_t aNamespaceID, nsIAtom* aAtom,
void* aData)
{
- if (aContent->GetID() == aAtom) {
+ if (aElement->GetID() == aAtom) {
return true;
}
- nsGenericHTMLElement* elm = nsGenericHTMLElement::FromContent(aContent);
+ nsGenericHTMLElement* elm = nsGenericHTMLElement::FromContent(aElement);
if (!elm) {
return false;
}
diff --git a/dom/html/HTMLDataListElement.cpp b/dom/html/HTMLDataListElement.cpp
index d9ad4da09..5aa772645 100644
--- a/dom/html/HTMLDataListElement.cpp
+++ b/dom/html/HTMLDataListElement.cpp
@@ -35,11 +35,11 @@ NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement)
NS_IMPL_ELEMENT_CLONE(HTMLDataListElement)
bool
-HTMLDataListElement::MatchOptions(nsIContent* aContent, int32_t aNamespaceID,
+HTMLDataListElement::MatchOptions(Element* aElement, int32_t aNamespaceID,
nsIAtom* aAtom, void* aData)
{
- return aContent->NodeInfo()->Equals(nsGkAtoms::option, kNameSpaceID_XHTML) &&
- !aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::disabled);
+ return aElement->NodeInfo()->Equals(nsGkAtoms::option, kNameSpaceID_XHTML) &&
+ !aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::disabled);
}
} // namespace dom
diff --git a/dom/html/HTMLDataListElement.h b/dom/html/HTMLDataListElement.h
index e0aff818b..ba2a2e0b4 100644
--- a/dom/html/HTMLDataListElement.h
+++ b/dom/html/HTMLDataListElement.h
@@ -37,8 +37,8 @@ public:
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
// This function is used to generate the nsContentList (option elements).
- static bool MatchOptions(nsIContent* aContent, int32_t aNamespaceID,
- nsIAtom* aAtom, void* aData);
+ static bool MatchOptions(Element* aElement, int32_t aNamespaceID,
+ nsIAtom* aAtom, void* aData);
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLDataListElement,
nsGenericHTMLElement)
diff --git a/dom/html/HTMLFieldSetElement.cpp b/dom/html/HTMLFieldSetElement.cpp
index 865d3c9cf..d72fd1061 100644
--- a/dom/html/HTMLFieldSetElement.cpp
+++ b/dom/html/HTMLFieldSetElement.cpp
@@ -120,10 +120,10 @@ HTMLFieldSetElement::GetType(nsAString& aType)
/* static */
bool
-HTMLFieldSetElement::MatchListedElements(nsIContent* aContent, int32_t aNamespaceID,
+HTMLFieldSetElement::MatchListedElements(Element* aElement, int32_t aNamespaceID,
nsIAtom* aAtom, void* aData)
{
- nsCOMPtr<nsIFormControl> formControl = do_QueryInterface(aContent);
+ nsCOMPtr<nsIFormControl> formControl = do_QueryInterface(aElement);
return formControl;
}
diff --git a/dom/html/HTMLFieldSetElement.h b/dom/html/HTMLFieldSetElement.h
index d169434ae..96fff4582 100644
--- a/dom/html/HTMLFieldSetElement.h
+++ b/dom/html/HTMLFieldSetElement.h
@@ -124,8 +124,8 @@ private:
void NotifyElementsForFirstLegendChange(bool aNotify);
// This function is used to generate the nsContentList (listed form elements).
- static bool MatchListedElements(nsIContent* aContent, int32_t aNamespaceID,
- nsIAtom* aAtom, void* aData);
+ static bool MatchListedElements(Element* aElement, int32_t aNamespaceID,
+ nsIAtom* aAtom, void* aData);
// listed form controls elements.
RefPtr<nsContentList> mElements;
diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp
index 78f74ae0c..d46eccdbc 100644
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -8800,6 +8800,16 @@ HTMLInputElement::GetWebkitEntries(nsTArray<RefPtr<FileSystemEntry>>& aSequence)
aSequence.AppendElements(mEntries);
}
+already_AddRefed<nsINodeList>
+HTMLInputElement::GetLabels()
+{
+ if (!IsLabelable()) {
+ return nullptr;
+ }
+
+ return nsGenericHTMLElement::Labels();
+}
+
} // namespace dom
} // namespace mozilla
diff --git a/dom/html/HTMLInputElement.h b/dom/html/HTMLInputElement.h
index e5d670e08..9ca876aee 100644
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -704,6 +704,8 @@ public:
// XPCOM GetCustomVisibility() is OK
+ already_AddRefed<nsINodeList> GetLabels();
+
// XPCOM Select() is OK
Nullable<int32_t> GetSelectionStart(ErrorResult& aRv);
diff --git a/dom/html/HTMLLabelElement.cpp b/dom/html/HTMLLabelElement.cpp
index c1d22b0a6..d1c037336 100644
--- a/dom/html/HTMLLabelElement.cpp
+++ b/dom/html/HTMLLabelElement.cpp
@@ -14,6 +14,7 @@
#include "nsFocusManager.h"
#include "nsIDOMMouseEvent.h"
#include "nsQueryObject.h"
+#include "mozilla/dom/ShadowRoot.h"
// construction, destruction
@@ -268,17 +269,23 @@ HTMLLabelElement::GetLabeledElement() const
return GetFirstLabelableDescendant();
}
- // We have a @for. The id has to be linked to an element in the same document
+ // We have a @for. The id has to be linked to an element in the same tree
// and this element should be a labelable form control.
- //XXXsmaug It is unclear how this should work in case the element is in
- // Shadow DOM.
- // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=26365.
- nsIDocument* doc = GetUncomposedDoc();
- if (!doc) {
- return nullptr;
+ nsINode* root = SubtreeRoot();
+ ShadowRoot* shadow = ShadowRoot::FromNode(root);
+ Element* element = nullptr;
+
+ if (shadow) {
+ element = shadow->GetElementById(elementId);
+ } else {
+ nsIDocument* doc = GetUncomposedDoc();
+ if (doc) {
+ element = doc->GetElementById(elementId);
+ } else {
+ element = nsContentUtils::MatchElementId(root->AsContent(), elementId);
+ }
}
- Element* element = doc->GetElementById(elementId);
if (element && element->IsLabelable()) {
return static_cast<nsGenericHTMLElement*>(element);
}
diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp
index e81cd20bc..1f1a545fa 100644
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -11,7 +11,9 @@
#include "mozilla/ArrayUtils.h"
#include "mozilla/MathAlgorithms.h"
#include "mozilla/AsyncEventDispatcher.h"
+#ifdef MOZ_EME
#include "mozilla/dom/MediaEncryptedEvent.h"
+#endif
#include "base/basictypes.h"
#include "nsIDOMHTMLMediaElement.h"
@@ -820,7 +822,9 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTM
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTextTrackManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioTrackList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVideoTrackList)
+#ifdef MOZ_EME
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeys)
+#endif
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSelectedVideoStreamTrack)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@@ -845,7 +849,9 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTMLE
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTextTrackManager)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mAudioTrackList)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mVideoTrackList)
+#ifdef MOZ_EME
NS_IMPL_CYCLE_COLLECTION_UNLINK(mMediaKeys)
+#endif
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSelectedVideoStreamTrack)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@@ -1020,12 +1026,14 @@ void HTMLMediaElement::ShutdownDecoder()
void HTMLMediaElement::AbortExistingLoads()
{
+#ifdef MOZ_EME
// If there is no existing decoder then we don't have anything to
// report. This prevents reporting the initial load from an
// empty video element as a failed EME load.
if (mDecoder) {
ReportEMETelemetry();
}
+#endif
// Abort any already-running instance of the resource selection algorithm.
mLoadWaitStatus = NOT_WAITING;
@@ -1084,7 +1092,9 @@ void HTMLMediaElement::AbortExistingLoads()
mDownloadSuspendedByCache = false;
mMediaInfo = MediaInfo();
mIsEncrypted = false;
+#ifdef MOZ_EME
mPendingEncryptedInitData.mInitDatas.Clear();
+#endif
mWaitingForKey = NOT_WAITING_FOR_KEY;
mSourcePointer = nullptr;
@@ -2681,9 +2691,11 @@ HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded,
if (!window) {
return nullptr;
}
+#ifdef MOZ_EME
if (ContainsRestrictedContent()) {
return nullptr;
}
+#endif
if (!mOutputStreams.IsEmpty() &&
aGraph != mOutputStreams[0].mStream->GetInputStream()->Graph()) {
@@ -3638,6 +3650,7 @@ void HTMLMediaElement::HiddenVideoStop()
mVideoDecodeSuspendTimer = nullptr;
}
+#ifdef MOZ_EME
void
HTMLMediaElement::ReportEMETelemetry()
{
@@ -3649,6 +3662,7 @@ HTMLMediaElement::ReportEMETelemetry()
this, mLoadedDataFired ? "true" : "false"));
}
}
+#endif
void
HTMLMediaElement::ReportTelemetry()
@@ -3997,6 +4011,7 @@ nsresult HTMLMediaElement::FinishDecoderSetup(MediaDecoder* aDecoder,
ms.mFinishWhenEnded);
}
+#ifdef MOZ_EME
if (mMediaKeys) {
if (mMediaKeys->GetCDMProxy()) {
mDecoder->SetCDMProxy(mMediaKeys->GetCDMProxy());
@@ -4006,6 +4021,7 @@ nsresult HTMLMediaElement::FinishDecoderSetup(MediaDecoder* aDecoder,
return NS_ERROR_FAILURE;
}
}
+#endif
MediaEventSource<void>* waitingForKeyProducer = mDecoder->WaitingForKeyEvent();
// Not every decoder will produce waitingForKey events, only add ones that can
@@ -4468,7 +4484,11 @@ void HTMLMediaElement::MetadataLoaded(const MediaInfo* aInfo,
SetMediaInfo(*aInfo);
- mIsEncrypted = aInfo->IsEncrypted() || mPendingEncryptedInitData.IsEncrypted();
+ mIsEncrypted = aInfo->IsEncrypted()
+#ifdef MOZ_EME
+ || mPendingEncryptedInitData.IsEncrypted()
+#endif
+ ;
mTags = aTags.forget();
mLoadedDataFired = false;
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
@@ -4494,11 +4514,13 @@ void HTMLMediaElement::MetadataLoaded(const MediaInfo* aInfo,
return;
}
+#ifdef MOZ_EME
// Dispatch a distinct 'encrypted' event for each initData we have.
for (const auto& initData : mPendingEncryptedInitData.mInitDatas) {
DispatchEncrypted(initData.mInitData, initData.mType);
}
mPendingEncryptedInitData.mInitDatas.Clear();
+#endif
}
mWatchManager.ManualNotify(&HTMLMediaElement::UpdateReadyStateInternal);
@@ -5431,9 +5453,12 @@ void HTMLMediaElement::SuspendOrResumeElement(bool aPauseElement, bool aSuspendE
UpdateAudioChannelPlayingState();
if (aPauseElement) {
ReportTelemetry();
+#ifdef MOZ_EME
ReportEMETelemetry();
+#endif
- // For EME content, force destruction of the CDM client (and CDM
+#ifdef MOZ_EME
+ // For EME content, we may force destruction of the CDM client (and CDM
// instance if this is the last client for that CDM instance) and
// the CDM's decoder. This ensures the CDM gets reliable and prompt
// shutdown notifications, as it may have book-keeping it needs
@@ -5445,6 +5470,7 @@ void HTMLMediaElement::SuspendOrResumeElement(bool aPauseElement, bool aSuspendE
ShutdownDecoder();
}
}
+#endif
if (mDecoder) {
mDecoder->Pause();
mDecoder->Suspend();
@@ -5495,6 +5521,17 @@ void HTMLMediaElement::NotifyOwnerDocumentActivityChanged()
bool pauseElement = ShouldElementBePaused();
SuspendOrResumeElement(pauseElement, !IsActive());
+#ifdef MOZ_EME
+ // If the owning document has become inactive we should shutdown the CDM.
+ if (!OwnerDoc()->IsCurrentActiveDocument() && mMediaKeys) {
+ mMediaKeys->Shutdown();
+ mMediaKeys = nullptr;
+ if (mDecoder) {
+ ShutdownDecoder();
+ }
+ }
+#endif
+
AddRemoveSelfReference();
}
@@ -6270,6 +6307,7 @@ HTMLMediaElement::OnVisibilityChange(Visibility aNewVisibility)
}
+#ifdef MOZ_EME
MediaKeys*
HTMLMediaElement::GetMediaKeys() const
{
@@ -6479,6 +6517,7 @@ HTMLMediaElement::GetTopLevelPrincipal()
principal = doc->NodePrincipal();
return principal.forget();
}
+#endif //MOZ_EME
void
HTMLMediaElement::CannotDecryptWaitingForKey()
diff --git a/dom/html/HTMLMediaElement.h b/dom/html/HTMLMediaElement.h
index d40e9df46..b65049206 100644
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -20,7 +20,9 @@
#include "mozilla/dom/TextTrackManager.h"
#include "mozilla/WeakPtr.h"
#include "MediaDecoder.h"
+#ifdef MOZ_EME
#include "mozilla/dom/MediaKeys.h"
+#endif
#include "mozilla/StateWatching.h"
#include "nsGkAtoms.h"
#include "PrincipalChangeObserver.h"
@@ -630,6 +632,7 @@ public:
// XPCOM MozPreservesPitch() is OK
+#ifdef MOZ_EME
MediaKeys* GetMediaKeys() const;
already_AddRefed<Promise> SetMediaKeys(MediaKeys* mediaKeys,
@@ -651,6 +654,7 @@ public:
already_AddRefed<nsIPrincipal> GetTopLevelPrincipal();
bool ContainsRestrictedContent();
+#endif // MOZ_EME
void CannotDecryptWaitingForKey();
@@ -1198,7 +1202,9 @@ protected:
*/
void HiddenVideoStop();
+#ifdef MOZ_EME
void ReportEMETelemetry();
+#endif
void ReportTelemetry();
@@ -1471,8 +1477,10 @@ protected:
// Timer used to simulate video-suspend.
nsCOMPtr<nsITimer> mVideoDecodeSuspendTimer;
+#ifdef MOZ_EME
// Encrypted Media Extension media keys.
RefPtr<MediaKeys> mMediaKeys;
+#endif
// Stores the time at the start of the current 'played' range.
double mCurrentPlayRangeStart;
@@ -1627,8 +1635,10 @@ protected:
// Listens for waitingForKey events from the owned decoder.
MediaEventListener mWaitingForKeyListener;
+#ifdef MOZ_EME
// Init Data that needs to be sent in 'encrypted' events in MetadataLoaded().
EncryptionInfo mPendingEncryptedInitData;
+#endif
// True if the media's channel's download has been suspended.
Watchable<bool> mDownloadSuspendedByCache;
diff --git a/dom/html/HTMLSelectElement.cpp b/dom/html/HTMLSelectElement.cpp
index 24ddabb65..53f42317a 100644
--- a/dom/html/HTMLSelectElement.cpp
+++ b/dom/html/HTMLSelectElement.cpp
@@ -735,12 +735,12 @@ HTMLSelectElement::SetLength(uint32_t aLength, ErrorResult& aRv)
/* static */
bool
-HTMLSelectElement::MatchSelectedOptions(nsIContent* aContent,
+HTMLSelectElement::MatchSelectedOptions(Element* aElement,
int32_t /* unused */,
nsIAtom* /* unused */,
void* /* unused*/)
{
- HTMLOptionElement* option = HTMLOptionElement::FromContent(aContent);
+ HTMLOptionElement* option = HTMLOptionElement::FromContent(aElement);
return option && option->Selected();
}
diff --git a/dom/html/HTMLSelectElement.h b/dom/html/HTMLSelectElement.h
index d7e4350b4..8a25385de 100644
--- a/dom/html/HTMLSelectElement.h
+++ b/dom/html/HTMLSelectElement.h
@@ -247,7 +247,7 @@ public:
mOptions->IndexedSetter(aIndex, aOption, aRv);
}
- static bool MatchSelectedOptions(nsIContent* aContent, int32_t, nsIAtom*,
+ static bool MatchSelectedOptions(Element* aElement, int32_t, nsIAtom*,
void*);
nsIHTMLCollection* SelectedOptions();
diff --git a/dom/html/HTMLTableRowElement.cpp b/dom/html/HTMLTableRowElement.cpp
index 2dec9c883..ac2463400 100644
--- a/dom/html/HTMLTableRowElement.cpp
+++ b/dom/html/HTMLTableRowElement.cpp
@@ -120,10 +120,10 @@ HTMLTableRowElement::SectionRowIndex() const
}
static bool
-IsCell(nsIContent *aContent, int32_t aNamespaceID,
+IsCell(Element *aElement, int32_t aNamespaceID,
nsIAtom* aAtom, void *aData)
{
- return aContent->IsAnyOfHTMLElements(nsGkAtoms::td, nsGkAtoms::th);
+ return aElement->IsAnyOfHTMLElements(nsGkAtoms::td, nsGkAtoms::th);
}
nsIHTMLCollection*
diff --git a/dom/html/nsGenericHTMLElement.cpp b/dom/html/nsGenericHTMLElement.cpp
index d75001a83..2f890325a 100644
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -108,6 +108,7 @@
#include "mozilla/StyleSetHandle.h"
#include "mozilla/StyleSetHandleInlines.h"
#include "ReferrerPolicy.h"
+#include "mozilla/dom/HTMLLabelElement.h"
using namespace mozilla;
using namespace mozilla::dom;
@@ -493,6 +494,14 @@ nsGenericHTMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
}
}
+ // We need to consider a labels element is moved to another subtree
+ // with different root, it needs to update labels list and its root
+ // as well.
+ nsDOMSlots* slots = GetExistingDOMSlots();
+ if (slots && slots->mLabelsList) {
+ slots->mLabelsList->MaybeResetRoot(SubtreeRoot());
+ }
+
return rv;
}
@@ -513,6 +522,13 @@ nsGenericHTMLElement::UnbindFromTree(bool aDeep, bool aNullParent)
}
}
+ // We need to consider a labels element is removed from tree,
+ // it needs to update labels list and its root as well.
+ nsDOMSlots* slots = GetExistingDOMSlots();
+ if (slots && slots->mLabelsList) {
+ slots->mLabelsList->MaybeResetRoot(SubtreeRoot());
+ }
+
nsStyledElement::UnbindFromTree(aDeep, aNullParent);
}
@@ -1701,6 +1717,30 @@ nsGenericHTMLElement::IsLabelable() const
return IsAnyOfHTMLElements(nsGkAtoms::progress, nsGkAtoms::meter);
}
+/* static */ bool
+nsGenericHTMLElement::MatchLabelsElement(Element* aElement, int32_t aNamespaceID,
+ nsIAtom* aAtom, void* aData)
+{
+ HTMLLabelElement* element = HTMLLabelElement::FromContent(aElement);
+ return element && element->GetControl() == aData;
+}
+
+already_AddRefed<nsINodeList>
+nsGenericHTMLElement::Labels()
+{
+ MOZ_ASSERT(IsLabelable(),
+ "Labels() only allow labelable elements to use it.");
+ nsDOMSlots* slots = DOMSlots();
+
+ if (!slots->mLabelsList) {
+ slots->mLabelsList = new nsLabelsNodeList(SubtreeRoot(), MatchLabelsElement,
+ nullptr, this);
+ }
+
+ RefPtr<nsLabelsNodeList> labels = slots->mLabelsList;
+ return labels.forget();
+}
+
bool
nsGenericHTMLElement::IsInteractiveHTMLContent(bool aIgnoreTabindex) const
{
diff --git a/dom/html/nsGenericHTMLElement.h b/dom/html/nsGenericHTMLElement.h
index 3cca41c3d..0635c27e1 100644
--- a/dom/html/nsGenericHTMLElement.h
+++ b/dom/html/nsGenericHTMLElement.h
@@ -834,6 +834,12 @@ public:
}
virtual bool IsLabelable() const override;
+
+ static bool MatchLabelsElement(Element* aElement, int32_t aNamespaceID,
+ nsIAtom* aAtom, void* aData);
+
+ already_AddRefed<nsINodeList> Labels();
+
virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const override;
static bool TouchEventsEnabled(JSContext* /* unused */, JSObject* /* unused */);
diff --git a/dom/html/nsHTMLDocument.cpp b/dom/html/nsHTMLDocument.cpp
index 7d66aab04..be5a34d41 100644
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -1100,31 +1100,31 @@ nsHTMLDocument::Applets()
}
bool
-nsHTMLDocument::MatchLinks(nsIContent *aContent, int32_t aNamespaceID,
+nsHTMLDocument::MatchLinks(Element* aElement, int32_t aNamespaceID,
nsIAtom* aAtom, void* aData)
{
- nsIDocument* doc = aContent->GetUncomposedDoc();
+ nsIDocument* doc = aElement->GetUncomposedDoc();
if (doc) {
- NS_ASSERTION(aContent->IsInUncomposedDoc(),
+ NS_ASSERTION(aElement->IsInUncomposedDoc(),
"This method should never be called on content nodes that "
"are not in a document!");
#ifdef DEBUG
{
nsCOMPtr<nsIHTMLDocument> htmldoc =
- do_QueryInterface(aContent->GetUncomposedDoc());
+ do_QueryInterface(aElement->GetUncomposedDoc());
NS_ASSERTION(htmldoc,
"Huh, how did this happen? This should only be used with "
"HTML documents!");
}
#endif
- mozilla::dom::NodeInfo *ni = aContent->NodeInfo();
+ mozilla::dom::NodeInfo *ni = aElement->NodeInfo();
nsIAtom *localName = ni->NameAtom();
if (ni->NamespaceID() == kNameSpaceID_XHTML &&
(localName == nsGkAtoms::a || localName == nsGkAtoms::area)) {
- return aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::href);
+ return aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::href);
}
}
@@ -1148,24 +1148,24 @@ nsHTMLDocument::Links()
}
bool
-nsHTMLDocument::MatchAnchors(nsIContent *aContent, int32_t aNamespaceID,
+nsHTMLDocument::MatchAnchors(Element* aElement, int32_t aNamespaceID,
nsIAtom* aAtom, void* aData)
{
- NS_ASSERTION(aContent->IsInUncomposedDoc(),
+ NS_ASSERTION(aElement->IsInUncomposedDoc(),
"This method should never be called on content nodes that "
"are not in a document!");
#ifdef DEBUG
{
nsCOMPtr<nsIHTMLDocument> htmldoc =
- do_QueryInterface(aContent->GetUncomposedDoc());
+ do_QueryInterface(aElement->GetUncomposedDoc());
NS_ASSERTION(htmldoc,
"Huh, how did this happen? This should only be used with "
"HTML documents!");
}
#endif
- if (aContent->NodeInfo()->Equals(nsGkAtoms::a, kNameSpaceID_XHTML)) {
- return aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::name);
+ if (aElement->IsHTMLElement(nsGkAtoms::a)) {
+ return aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::name);
}
return false;
@@ -1536,6 +1536,18 @@ nsHTMLDocument::Open(JSContext* cx,
nsCOMPtr<nsIDocument> ret = this;
return ret.forget();
}
+
+ // Now double-check that our invariants still hold.
+ if (!mScriptGlobalObject) {
+ nsCOMPtr<nsIDocument> ret = this;
+ return ret.forget();
+ }
+
+ nsPIDOMWindowOuter* outer = GetWindow();
+ if (!outer || (GetInnerWindow() != outer->GetCurrentInnerWindow())) {
+ nsCOMPtr<nsIDocument> ret = this;
+ return ret.forget();
+ }
}
nsCOMPtr<nsIWebNavigation> webnav(do_QueryInterface(shell));
@@ -1952,14 +1964,14 @@ nsHTMLDocument::Writeln(JSContext* cx, const Sequence<nsString>& aText,
}
bool
-nsHTMLDocument::MatchNameAttribute(nsIContent* aContent, int32_t aNamespaceID,
+nsHTMLDocument::MatchNameAttribute(Element* aElement, int32_t aNamespaceID,
nsIAtom* aAtom, void* aData)
{
- NS_PRECONDITION(aContent, "Must have content node to work with!");
+ NS_PRECONDITION(aElement, "Must have element to work with!");
nsString* elementName = static_cast<nsString*>(aData);
return
- aContent->GetNameSpaceID() == kNameSpaceID_XHTML &&
- aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
+ aElement->GetNameSpaceID() == kNameSpaceID_XHTML &&
+ aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
*elementName, eCaseMatters);
}
@@ -2279,10 +2291,10 @@ nsHTMLDocument::GetForms()
return mForms;
}
-static bool MatchFormControls(nsIContent* aContent, int32_t aNamespaceID,
- nsIAtom* aAtom, void* aData)
+static bool MatchFormControls(Element* aElement, int32_t aNamespaceID,
+ nsIAtom* aAtom, void* aData)
{
- return aContent->IsNodeOfType(nsIContent::eHTML_FORM_CONTROL);
+ return aElement->IsNodeOfType(nsIContent::eHTML_FORM_CONTROL);
}
nsContentList*
diff --git a/dom/html/nsHTMLDocument.h b/dom/html/nsHTMLDocument.h
index 2dbbf2b57..426ebddc5 100644
--- a/dom/html/nsHTMLDocument.h
+++ b/dom/html/nsHTMLDocument.h
@@ -261,12 +261,13 @@ protected:
nsIContent *MatchId(nsIContent *aContent, const nsAString& aId);
- static bool MatchLinks(nsIContent *aContent, int32_t aNamespaceID,
+ static bool MatchLinks(mozilla::dom::Element* aElement, int32_t aNamespaceID,
+ nsIAtom* aAtom, void* aData);
+ static bool MatchAnchors(mozilla::dom::Element* aElement, int32_t aNamespaceID,
nsIAtom* aAtom, void* aData);
- static bool MatchAnchors(nsIContent *aContent, int32_t aNamespaceID,
- nsIAtom* aAtom, void* aData);
- static bool MatchNameAttribute(nsIContent* aContent, int32_t aNamespaceID,
- nsIAtom* aAtom, void* aData);
+ static bool MatchNameAttribute(mozilla::dom::Element* aElement,
+ int32_t aNamespaceID,
+ nsIAtom* aAtom, void* aData);
static void* UseExistingNameString(nsINode* aRootNode, const nsString* aName);
static void DocumentWriteTerminationFunc(nsISupports *aRef);
diff --git a/dom/html/test/forms/test_button_attributes_reflection.html b/dom/html/test/forms/test_button_attributes_reflection.html
index 26858e939..4e702b3ac 100644
--- a/dom/html/test/forms/test_button_attributes_reflection.html
+++ b/dom/html/test/forms/test_button_attributes_reflection.html
@@ -128,9 +128,12 @@ is(typeof(document.createElement("button").setCustomValidity), "function",
"button.setCustomValidity should be a function");
// .labels
-todo("labels" in document.createElement("button"),
- "button.labels isn't implemented yet");
-
+ok("labels" in document.createElement("button"),
+ "button.labels should be an IDL attribute of the button element");
+is(typeof(document.createElement("button").labels), "object",
+ "button.labels should be an object");
+ok(document.createElement("button").labels instanceof NodeList,
+ "button.labels sohuld be an instance of NodeList");
</script>
</pre>
</body>
diff --git a/dom/interfaces/security/nsIContentSecurityPolicy.idl b/dom/interfaces/security/nsIContentSecurityPolicy.idl
index ade5b1243..da4297f33 100644
--- a/dom/interfaces/security/nsIContentSecurityPolicy.idl
+++ b/dom/interfaces/security/nsIContentSecurityPolicy.idl
@@ -61,6 +61,7 @@ interface nsIContentSecurityPolicy : nsISerializable
const unsigned short BLOCK_ALL_MIXED_CONTENT = 19;
const unsigned short REQUIRE_SRI_FOR = 20;
const unsigned short SANDBOX_DIRECTIVE = 21;
+ const unsigned short WORKER_SRC_DIRECTIVE = 22;
/**
* Accessor method for a read-only string version of the policy at a given
@@ -98,6 +99,11 @@ interface nsIContentSecurityPolicy : nsISerializable
readonly attribute bool blockAllMixedContent;
/**
+ * Returns whether this policy enforces the frame-ancestors directive.
+ */
+ readonly attribute bool enforcesFrameAncestors;
+
+ /**
* Obtains the referrer policy (as integer) for this browsing context as
* specified in CSP. If there are multiple policies and...
* - only one sets a referrer policy: that policy is returned
diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl
index 249657c26..9dfccbc5c 100644
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -11,7 +11,6 @@ include protocol PContent;
include protocol PContentBridge;
include protocol PDatePicker;
include protocol PDocAccessible;
-include protocol PDocumentRenderer;
include protocol PFilePicker;
include protocol PIndexedDBPermissionRequest;
include protocol PRenderFrame;
@@ -119,7 +118,6 @@ nested(upto inside_cpow) sync protocol PBrowser
manages PColorPicker;
manages PDatePicker;
manages PDocAccessible;
- manages PDocumentRenderer;
manages PFilePicker;
manages PIndexedDBPermissionRequest;
manages PRenderFrame;
@@ -739,24 +737,6 @@ child:
async LoadRemoteScript(nsString aURL, bool aRunInGlobalScope);
/**
- * Create a asynchronous request to render whatever document is
- * loaded in the child when this message arrives. When the
- * request finishes, PDocumentRenderer:__delete__ is sent back to
- * this side to notify completion.
- *
- * |documentRect| is the area of the remote document to draw,
- * transformed by |transform|. The rendered area will have the
- * default background color |bgcolor|. |renderFlags| are the
- * nsIPresShell::RenderDocument() flags to use on the remote side,
- * and if true, |flushLayout| will do just that before rendering
- * the document. The rendered image will be of size |renderSize|.
- */
- async PDocumentRenderer(nsRect documentRect, Matrix transform,
- nsString bgcolor,
- uint32_t renderFlags, bool flushLayout,
- IntSize renderSize);
-
- /**
* Sent by the chrome process when it no longer wants this remote
* <browser>. The child side cleans up in response, then
* finalizing its death by sending back __delete__() to the
diff --git a/dom/ipc/PDocumentRenderer.ipdl b/dom/ipc/PDocumentRenderer.ipdl
deleted file mode 100644
index bdaed45d7..000000000
--- a/dom/ipc/PDocumentRenderer.ipdl
+++ /dev/null
@@ -1,25 +0,0 @@
-/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
-/* 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 protocol PBrowser;
-
-include "mozilla/GfxMessageUtils.h";
-
-using nsIntSize from "nsSize.h";
-
-namespace mozilla {
-namespace ipc {
-
-protocol PDocumentRenderer
-{
- manager PBrowser;
-
-parent:
- // Returns the width and height, in pixels, of the returned ARGB32 data.
- async __delete__(nsIntSize renderedSize, nsCString data);
-};
-
-} // namespace ipc
-} // namespace mozilla
diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp
index eaf4a32ed..f46a917d5 100644
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -22,7 +22,6 @@
#include "mozilla/dom/indexedDB/PIndexedDBPermissionRequestChild.h"
#include "mozilla/plugins/PluginWidgetChild.h"
#include "mozilla/IMEStateManager.h"
-#include "mozilla/ipc/DocumentRendererChild.h"
#include "mozilla/ipc/URIUtils.h"
#include "mozilla/layers/APZChild.h"
#include "mozilla/layers/APZCCallbackHelper.h"
@@ -2006,57 +2005,6 @@ TabChild::DeallocPDocAccessibleChild(a11y::PDocAccessibleChild* aChild)
return true;
}
-PDocumentRendererChild*
-TabChild::AllocPDocumentRendererChild(const nsRect& documentRect,
- const mozilla::gfx::Matrix& transform,
- const nsString& bgcolor,
- const uint32_t& renderFlags,
- const bool& flushLayout,
- const nsIntSize& renderSize)
-{
- return new DocumentRendererChild();
-}
-
-bool
-TabChild::DeallocPDocumentRendererChild(PDocumentRendererChild* actor)
-{
- delete actor;
- return true;
-}
-
-bool
-TabChild::RecvPDocumentRendererConstructor(PDocumentRendererChild* actor,
- const nsRect& documentRect,
- const mozilla::gfx::Matrix& transform,
- const nsString& bgcolor,
- const uint32_t& renderFlags,
- const bool& flushLayout,
- const nsIntSize& renderSize)
-{
- DocumentRendererChild *render = static_cast<DocumentRendererChild *>(actor);
-
- nsCOMPtr<nsIWebBrowser> browser = do_QueryInterface(WebNavigation());
- if (!browser)
- return true; // silently ignore
- nsCOMPtr<mozIDOMWindowProxy> window;
- if (NS_FAILED(browser->GetContentDOMWindow(getter_AddRefs(window))) ||
- !window)
- {
- return true; // silently ignore
- }
-
- nsCString data;
- bool ret = render->RenderDocument(nsPIDOMWindowOuter::From(window),
- documentRect, transform,
- bgcolor,
- renderFlags, flushLayout,
- renderSize, data);
- if (!ret)
- return true; // silently ignore
-
- return PDocumentRendererChild::Send__delete__(actor, renderSize, data);
-}
-
PColorPickerChild*
TabChild::AllocPColorPickerChild(const nsString&, const nsString&)
{
diff --git a/dom/ipc/TabChild.h b/dom/ipc/TabChild.h
index b23c7c19e..2232ffeaf 100644
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -445,27 +445,6 @@ public:
virtual bool DeallocPDocAccessibleChild(PDocAccessibleChild*) override;
- virtual PDocumentRendererChild*
- AllocPDocumentRendererChild(const nsRect& aDocumentRect,
- const gfx::Matrix& aTransform,
- const nsString& aBggcolor,
- const uint32_t& aRenderFlags,
- const bool& aFlushLayout,
- const nsIntSize& arenderSize) override;
-
- virtual bool
- DeallocPDocumentRendererChild(PDocumentRendererChild* aCctor) override;
-
- virtual bool
- RecvPDocumentRendererConstructor(PDocumentRendererChild* aActor,
- const nsRect& aDocumentRect,
- const gfx::Matrix& aTransform,
- const nsString& aBgcolor,
- const uint32_t& aRenderFlags,
- const bool& aFlushLayout,
- const nsIntSize& aRenderSize) override;
-
-
virtual PColorPickerChild*
AllocPColorPickerChild(const nsString& aTitle,
const nsString& aInitialColor) override;
diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp
index 0df4c1253..8e98de3ce 100644
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -28,7 +28,6 @@
#include "mozilla/gfx/GPUProcessManager.h"
#include "mozilla/Hal.h"
#include "mozilla/IMEStateManager.h"
-#include "mozilla/ipc/DocumentRendererParent.h"
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
#include "mozilla/layers/AsyncDragMetrics.h"
#include "mozilla/layers/InputAPZContext.h"
@@ -957,24 +956,6 @@ TabParent::GetTopLevelDocAccessible() const
return nullptr;
}
-PDocumentRendererParent*
-TabParent::AllocPDocumentRendererParent(const nsRect& documentRect,
- const gfx::Matrix& transform,
- const nsString& bgcolor,
- const uint32_t& renderFlags,
- const bool& flushLayout,
- const nsIntSize& renderSize)
-{
- return new DocumentRendererParent();
-}
-
-bool
-TabParent::DeallocPDocumentRendererParent(PDocumentRendererParent* actor)
-{
- delete actor;
- return true;
-}
-
PFilePickerParent*
TabParent::AllocPFilePickerParent(const nsString& aTitle, const int16_t& aMode)
{
diff --git a/dom/ipc/TabParent.h b/dom/ipc/TabParent.h
index 43afb0538..09bb999f3 100644
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -473,17 +473,6 @@ public:
const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId);
- virtual PDocumentRendererParent*
- AllocPDocumentRendererParent(const nsRect& documentRect,
- const gfx::Matrix& transform,
- const nsString& bgcolor,
- const uint32_t& renderFlags,
- const bool& flushLayout,
- const nsIntSize& renderSize) override;
-
- virtual bool
- DeallocPDocumentRendererParent(PDocumentRendererParent* actor) override;
-
virtual PFilePickerParent*
AllocPFilePickerParent(const nsString& aTitle,
const int16_t& aMode) override;
diff --git a/dom/ipc/moz.build b/dom/ipc/moz.build
index 153bd3aae..ff3880bc2 100644
--- a/dom/ipc/moz.build
+++ b/dom/ipc/moz.build
@@ -96,7 +96,6 @@ IPDL_SOURCES += [
'PCrashReporter.ipdl',
'PCycleCollectWithLogs.ipdl',
'PDatePicker.ipdl',
- 'PDocumentRenderer.ipdl',
'PFilePicker.ipdl',
'PMemoryReportRequest.ipdl',
'PPluginWidget.ipdl',
diff --git a/dom/locales/en-US/chrome/security/csp.properties b/dom/locales/en-US/chrome/security/csp.properties
index fc7fc04ba..4c4054cee 100644
--- a/dom/locales/en-US/chrome/security/csp.properties
+++ b/dom/locales/en-US/chrome/security/csp.properties
@@ -91,6 +91,10 @@ ignoringReportOnlyDirective = Ignoring sandbox directive when delivered in a rep
# LOCALIZATION NOTE (deprecatedReferrerDirective):
# %1$S is the value of the deprecated Referrer Directive.
deprecatedReferrerDirective = Referrer Directive ‘%1$S’ has been deprecated. Please use the Referrer-Policy header instead.
+# LOCALIZATION NOTE (IgnoringSrcBecauseOfDirective):
+# %1$S is the name of the src that is ignored.
+# %2$S is the name of the directive that causes the src to be ignored.
+IgnoringSrcBecauseOfDirective=Ignoring ‘%1$S’ because of ‘%2$S’ directive.
# CSP Errors:
# LOCALIZATION NOTE (couldntParseInvalidSource):
@@ -108,9 +112,10 @@ couldntParsePort = Couldn’t parse port in %1$S
# LOCALIZATION NOTE (duplicateDirective):
# %1$S is the name of the duplicate directive
duplicateDirective = Duplicate %1$S directives detected. All but the first instance will be ignored.
-# LOCALIZATION NOTE (deprecatedDirective):
-# %1$S is the name of the deprecated directive, %2$S is the name of the replacement.
-deprecatedDirective = Directive ‘%1$S’ has been deprecated. Please use directive ‘%2$S’ instead.
+# LOCALIZATION NOTE (deprecatedChildSrcDirective):
+# %1$S is the value of the deprecated directive.
+# Do not localize: worker-src, frame-src
+deprecatedChildSrcDirective = Directive ‘%1$S’ has been deprecated. Please use directive ‘worker-src’ to control workers, or directive ‘frame-src’ to control frames respectively.
# LOCALIZATION NOTE (couldntParseInvalidSandboxFlag):
# %1$S is the option that could not be understood
couldntParseInvalidSandboxFlag = Couldn’t parse invalid sandbox flag ‘%1$S’
diff --git a/dom/media/DOMMediaStream.cpp b/dom/media/DOMMediaStream.cpp
index 6794ee32f..c1d451035 100644..100755
--- a/dom/media/DOMMediaStream.cpp
+++ b/dom/media/DOMMediaStream.cpp
@@ -9,6 +9,7 @@
#include "nsIScriptError.h"
#include "nsIUUIDGenerator.h"
#include "nsPIDOMWindow.h"
+#include "mozilla/TimerClamping.h"
#include "mozilla/dom/MediaStreamBinding.h"
#include "mozilla/dom/MediaStreamTrackEvent.h"
#include "mozilla/dom/LocalMediaStreamBinding.h"
@@ -544,8 +545,8 @@ DOMMediaStream::CurrentTime()
if (!mPlaybackStream) {
return 0.0;
}
- return mPlaybackStream->
- StreamTimeToSeconds(mPlaybackStream->GetCurrentTime() - mLogicalStreamStartTime);
+ return TimerClamping::ReduceSTimeValue(mPlaybackStream->
+ StreamTimeToSeconds(mPlaybackStream->GetCurrentTime() - mLogicalStreamStartTime));
}
void
diff --git a/dom/media/GraphDriver.cpp b/dom/media/GraphDriver.cpp
index 9b74bd58c..40e3b72cf 100644
--- a/dom/media/GraphDriver.cpp
+++ b/dom/media/GraphDriver.cpp
@@ -1055,6 +1055,7 @@ AudioCallbackDriver::StateCallback(cubeb_state aState)
{
STREAM_LOG(LogLevel::Debug, ("AudioCallbackDriver State: %d", aState));
if (aState == CUBEB_STATE_ERROR && mShouldFallbackIfError) {
+ mShouldFallbackIfError = false;
MonitorAutoLock lock(GraphImpl()->GetMonitor());
// Fall back to a driver using a normal thread. If needed,
// the graph will try to re-open an audio stream later.
diff --git a/dom/media/MediaData.cpp b/dom/media/MediaData.cpp
index 0439a7473..4a52c22ae 100644
--- a/dom/media/MediaData.cpp
+++ b/dom/media/MediaData.cpp
@@ -90,7 +90,7 @@ ValidatePlane(const VideoData::YCbCrBuffer::Plane& aPlane)
return aPlane.mWidth <= PlanarYCbCrImage::MAX_DIMENSION &&
aPlane.mHeight <= PlanarYCbCrImage::MAX_DIMENSION &&
aPlane.mWidth * aPlane.mHeight < MAX_VIDEO_WIDTH * MAX_VIDEO_HEIGHT &&
- aPlane.mStride > 0;
+ aPlane.mStride > 0 && aPlane.mWidth <= aPlane.mStride;
}
#ifdef MOZ_WIDGET_GONK
diff --git a/dom/media/MediaDecoderOwner.h b/dom/media/MediaDecoderOwner.h
index f884686fb..f993b4324 100644
--- a/dom/media/MediaDecoderOwner.h
+++ b/dom/media/MediaDecoderOwner.h
@@ -143,11 +143,13 @@ public:
// reference to the decoder to prevent further calls into the decoder.
virtual void NotifyXPCOMShutdown() = 0;
+#ifdef MOZ_EME
// Dispatches a "encrypted" event to the HTMLMediaElement, with the
// provided init data. Actual dispatch may be delayed until HAVE_METADATA.
// Main thread only.
virtual void DispatchEncrypted(const nsTArray<uint8_t>& aInitData,
const nsAString& aInitDataType) = 0;
+#endif
};
} // namespace mozilla
diff --git a/dom/media/MediaFormatReader.cpp b/dom/media/MediaFormatReader.cpp
index 2093803ad..06e8b963b 100644
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -346,8 +346,12 @@ MediaFormatReader::DecoderFactory::DoCreateDecoder(TrackType aTrack)
if (!mOwner->mPlatform) {
mOwner->mPlatform = new PDMFactory();
if (mOwner->IsEncrypted()) {
+#ifdef MOZ_EME
MOZ_ASSERT(mOwner->mCDMProxy);
mOwner->mPlatform->SetCDMProxy(mOwner->mCDMProxy);
+#else
+ return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, "EME not supported");
+#endif
}
}
@@ -577,6 +581,7 @@ MediaFormatReader::InitInternal()
return NS_OK;
}
+#ifdef MOZ_EME
class DispatchKeyNeededEvent : public Runnable {
public:
DispatchKeyNeededEvent(AbstractMediaDecoder* aDecoder,
@@ -602,6 +607,7 @@ private:
nsTArray<uint8_t> mInitData;
nsString mInitDataType;
};
+#endif
void
MediaFormatReader::SetCDMProxy(CDMProxy* aProxy)
@@ -618,7 +624,11 @@ MediaFormatReader::SetCDMProxy(CDMProxy* aProxy)
bool
MediaFormatReader::IsWaitingOnCDMResource() {
MOZ_ASSERT(OnTaskQueue());
+#ifdef MOZ_EME
return IsEncrypted() && !mCDMProxy;
+#else
+ return false;
+#endif
}
RefPtr<MediaDecoderReader::MetadataPromise>
@@ -725,11 +735,13 @@ MediaFormatReader::OnDemuxerInitDone(nsresult)
UniquePtr<EncryptionInfo> crypto = mDemuxer->GetCrypto();
if (mDecoder && crypto && crypto->IsEncrypted()) {
+#ifdef MOZ_EME
// Try and dispatch 'encrypted'. Won't go if ready state still HAVE_NOTHING.
for (uint32_t i = 0; i < crypto->mInitDatas.Length(); i++) {
NS_DispatchToMainThread(
new DispatchKeyNeededEvent(mDecoder, crypto->mInitDatas[i].mInitData, crypto->mInitDatas[i].mType));
}
+#endif
mInfo.mCrypto = *crypto;
}
diff --git a/dom/media/MediaPrefs.h b/dom/media/MediaPrefs.h
index 62b8fc47b..b237ecd3d 100644
--- a/dom/media/MediaPrefs.h
+++ b/dom/media/MediaPrefs.h
@@ -156,10 +156,6 @@ private:
DECL_MEDIA_PREF("media.ogg.flac.enabled", FlacInOgg, bool, false);
DECL_MEDIA_PREF("media.flac.enabled", FlacEnabled, bool, true);
-#if defined(MOZ_RUST_MP4PARSE) && !defined(RELEASE_OR_BETA)
- DECL_MEDIA_PREF("media.rust.test_mode", RustTestMode, bool, false);
-#endif
-
public:
// Manage the singleton:
static MediaPrefs& GetSingleton();
diff --git a/dom/media/gtest/moz.build b/dom/media/gtest/moz.build
index fc92d5ef3..d5d02bced 100644
--- a/dom/media/gtest/moz.build
+++ b/dom/media/gtest/moz.build
@@ -35,10 +35,6 @@ if CONFIG['MOZ_WEBM_ENCODER']:
'TestWebMWriter.cpp',
]
-if CONFIG['MOZ_RUST']:
- UNIFIED_SOURCES += ['TestRust.cpp',]
-
-
TEST_HARNESS_FILES.gtest += [
'../test/gizmo-frag.mp4',
'../test/gizmo.mp4',
diff --git a/dom/media/mediasource/TrackBuffersManager.cpp b/dom/media/mediasource/TrackBuffersManager.cpp
index 4265aed81..ac6d82411 100644
--- a/dom/media/mediasource/TrackBuffersManager.cpp
+++ b/dom/media/mediasource/TrackBuffersManager.cpp
@@ -58,6 +58,7 @@ AppendStateToStr(SourceBufferAttributes::AppendState aState)
static Atomic<uint32_t> sStreamSourceID(0u);
+#ifdef MOZ_EME
class DispatchKeyNeededEvent : public Runnable {
public:
DispatchKeyNeededEvent(AbstractMediaDecoder* aDecoder,
@@ -83,6 +84,7 @@ private:
nsTArray<uint8_t> mInitData;
nsString mInitDataType;
};
+#endif
TrackBuffersManager::TrackBuffersManager(MediaSourceDecoder* aParentDecoder,
const nsACString& aType)
@@ -1097,12 +1099,14 @@ TrackBuffersManager::OnDemuxerInitDone(nsresult)
UniquePtr<EncryptionInfo> crypto = mInputDemuxer->GetCrypto();
if (crypto && crypto->IsEncrypted()) {
+#ifdef MOZ_EME
// Try and dispatch 'encrypted'. Won't go if ready state still HAVE_NOTHING.
for (uint32_t i = 0; i < crypto->mInitDatas.Length(); i++) {
NS_DispatchToMainThread(
new DispatchKeyNeededEvent(mParentDecoder, crypto->mInitDatas[i].mInitData,
crypto->mInitDatas[i].mType));
}
+#endif
info.mCrypto = *crypto;
// We clear our crypto init data array, so the MediaFormatReader will
// not emit an encrypted event for the same init data again.
diff --git a/dom/media/test/test_background_video_suspend.html b/dom/media/test/test_background_video_suspend.html
index e872eacf8..a5ac5cc2c 100644..100755
--- a/dom/media/test/test_background_video_suspend.html
+++ b/dom/media/test/test_background_video_suspend.html
@@ -15,7 +15,7 @@ var MIN_DELAY = 100;
function testDelay(v, start, min) {
let end = performance.now();
let delay = end - start;
- ok(delay > min, `${v.token} suspended with a delay of ${delay} ms`);
+ ok(delay >= min, `${v.token} suspended with a delay of ${delay} ms`);
}
startTest({
@@ -25,7 +25,7 @@ startTest({
[ "media.suspend-bkgnd-video.enabled", true ],
// User a short delay to ensure video decode suspend happens before end
// of video.
- [ "media.suspend-bkgnd-video.delay-ms", MIN_DELAY ]
+ [ "media.suspend-bkgnd-video.delay-ms", MIN_DELAY ],
],
tests: gDecodeSuspendTests,
runTest: (test, token) => {
diff --git a/dom/media/test/test_streams_element_capture.html b/dom/media/test/test_streams_element_capture.html
index 5e30a3ce4..a29eeef4d 100644..100755
--- a/dom/media/test/test_streams_element_capture.html
+++ b/dom/media/test/test_streams_element_capture.html
@@ -38,7 +38,8 @@ function startTest(test) {
var stream;
var checkEnded = function() {
- is(stream.currentTime, vout.currentTime, test.name + " stream final currentTime");
+ // We know the video time won't match up to the stream time
+ // is(stream.currentTime, vout.currentTime, test.name + " stream final currentTime");
if (test.duration) {
isGreaterThanOrEqualEps(vout.currentTime, test.duration,
test.name + " current time at end");
diff --git a/dom/media/test/test_streams_element_capture_createObjectURL.html b/dom/media/test/test_streams_element_capture_createObjectURL.html
index d5d7efc5c..d952c7142 100644..100755
--- a/dom/media/test/test_streams_element_capture_createObjectURL.html
+++ b/dom/media/test/test_streams_element_capture_createObjectURL.html
@@ -38,7 +38,8 @@ function startTest(test, token) {
var stream;
var checkEnded = function() {
- is(stream.currentTime, vout.currentTime, test.name + " stream final currentTime");
+ // We know the video time won't match up to the stream time
+ // is(stream.currentTime, vout.currentTime, test.name + " stream final currentTime");
if (test.duration) {
isGreaterThanOrEqualEps(vout.currentTime, test.duration,
test.name + " current time at end");
diff --git a/dom/media/webaudio/AudioContext.cpp b/dom/media/webaudio/AudioContext.cpp
index f61226a48..85842c811 100644..100755
--- a/dom/media/webaudio/AudioContext.cpp
+++ b/dom/media/webaudio/AudioContext.cpp
@@ -41,6 +41,7 @@
#include "nsNetUtil.h"
#include "nsPIDOMWindow.h"
#include "nsPrintfCString.h"
+#include "mozilla/TimerClamping.h"
#include "OscillatorNode.h"
#include "PannerNode.h"
#include "PeriodicWave.h"
@@ -379,10 +380,12 @@ AudioContext::CreateMediaElementSource(HTMLMediaElement& aMediaElement,
return nullptr;
}
+#ifdef MOZ_EME
if (aMediaElement.ContainsRestrictedContent()) {
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return nullptr;
}
+#endif
if (CheckClosed(aRv)) {
return nullptr;
@@ -744,7 +747,7 @@ double
AudioContext::CurrentTime() const
{
MediaStream* stream = Destination()->Stream();
- return stream->StreamTimeToSeconds(stream->GetCurrentTime());
+ return TimerClamping::ReduceSTimeValue(stream->StreamTimeToSeconds(stream->GetCurrentTime()));
}
void
diff --git a/dom/performance/Performance.cpp b/dom/performance/Performance.cpp
index 17273c55d..8dc239b05 100644..100755
--- a/dom/performance/Performance.cpp
+++ b/dom/performance/Performance.cpp
@@ -21,6 +21,7 @@
#include "mozilla/dom/PerformanceObserverBinding.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/Preferences.h"
+#include "mozilla/TimerClamping.h"
#include "WorkerPrivate.h"
#include "WorkerRunnable.h"
@@ -228,9 +229,9 @@ Performance::ClearResourceTimings()
DOMHighResTimeStamp
Performance::RoundTime(double aTime) const
{
- // Round down to the nearest 20us, because if the timer is too accurate people
+ // Round down to the nearest 2ms, because if the timer is too accurate people
// can do nasty timing attacks with it.
- const double maxResolutionMs = 0.020;
+ const double maxResolutionMs = 2;
return floor(aTime / maxResolutionMs) * maxResolutionMs;
}
diff --git a/dom/performance/PerformanceMainThread.cpp b/dom/performance/PerformanceMainThread.cpp
index b60b68f62..86d42c5f8 100644
--- a/dom/performance/PerformanceMainThread.cpp
+++ b/dom/performance/PerformanceMainThread.cpp
@@ -200,7 +200,7 @@ PerformanceMainThread::IsPerformanceTimingAttribute(const nsAString& aName)
static const char* attributes[] =
{"navigationStart", "unloadEventStart", "unloadEventEnd", "redirectStart",
"redirectEnd", "fetchStart", "domainLookupStart", "domainLookupEnd",
- "connectStart", "connectEnd", "requestStart", "responseStart",
+ "connectStart", "secureConnectionStart", "connectEnd", "requestStart", "responseStart",
"responseEnd", "domLoading", "domInteractive",
"domContentLoadedEventStart", "domContentLoadedEventEnd", "domComplete",
"loadEventStart", "loadEventEnd", nullptr};
@@ -249,6 +249,9 @@ PerformanceMainThread::GetPerformanceTimingFromString(const nsAString& aProperty
if (aProperty.EqualsLiteral("connectStart")) {
return Timing()->ConnectStart();
}
+ if (aProperty.EqualsLiteral("secureConnectionStart")) {
+ return Timing()->SecureConnectionStart();
+ }
if (aProperty.EqualsLiteral("connectEnd")) {
return Timing()->ConnectEnd();
}
diff --git a/dom/performance/PerformanceResourceTiming.h b/dom/performance/PerformanceResourceTiming.h
index abb653d66..2dd6b4a06 100644
--- a/dom/performance/PerformanceResourceTiming.h
+++ b/dom/performance/PerformanceResourceTiming.h
@@ -128,9 +128,9 @@ public:
DOMHighResTimeStamp SecureConnectionStart() const
{
- // This measurement is not available for Navigation Timing either.
- // There is a different bug submitted for it.
- return 0;
+ return mTiming && mTiming->TimingAllowed()
+ ? mTiming->SecureConnectionStartHighRes()
+ : 0;
}
virtual const PerformanceResourceTiming* ToResourceTiming() const override
diff --git a/dom/performance/PerformanceTiming.cpp b/dom/performance/PerformanceTiming.cpp
index 527cf9441..e2f76a21f 100644..100755
--- a/dom/performance/PerformanceTiming.cpp
+++ b/dom/performance/PerformanceTiming.cpp
@@ -21,7 +21,7 @@ PerformanceTiming::PerformanceTiming(Performance* aPerformance,
DOMHighResTimeStamp aZeroTime)
: mPerformance(aPerformance),
mFetchStart(0.0),
- mZeroTime(aZeroTime),
+ mZeroTime(TimerClamping::ReduceMsTimeValue(aZeroTime)),
mRedirectCount(0),
mTimingAllowed(true),
mAllRedirectsSameOrigin(true),
@@ -46,6 +46,23 @@ PerformanceTiming::PerformanceTiming(Performance* aPerformance,
mReportCrossOriginRedirect = mTimingAllowed && redirectsPassCheck;
}
+ mSecureConnection = false;
+ nsCOMPtr<nsIURI> uri;
+ if (aHttpChannel) {
+ aHttpChannel->GetURI(getter_AddRefs(uri));
+ } else {
+ nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
+ if (httpChannel) {
+ httpChannel->GetURI(getter_AddRefs(uri));
+ }
+ }
+
+ if (uri) {
+ nsresult rv = uri->SchemeIs("https", &mSecureConnection);
+ if (NS_FAILED(rv)) {
+ mSecureConnection = false;
+ }
+ }
InitializeTimingInfo(aChannel);
}
@@ -63,12 +80,41 @@ PerformanceTiming::InitializeTimingInfo(nsITimedChannel* aChannel)
aChannel->GetDomainLookupStart(&mDomainLookupStart);
aChannel->GetDomainLookupEnd(&mDomainLookupEnd);
aChannel->GetConnectStart(&mConnectStart);
+ aChannel->GetSecureConnectionStart(&mSecureConnectionStart);
aChannel->GetConnectEnd(&mConnectEnd);
aChannel->GetRequestStart(&mRequestStart);
aChannel->GetResponseStart(&mResponseStart);
aChannel->GetCacheReadStart(&mCacheReadStart);
aChannel->GetResponseEnd(&mResponseEnd);
aChannel->GetCacheReadEnd(&mCacheReadEnd);
+
+ // the performance timing api essentially requires that the event timestamps
+ // are >= asyncOpen().. but in truth the browser engages in a number of
+ // speculative activities that sometimes mean connections and lookups begin
+ // earlier. Workaround that here by just using asyncOpen as the minimum
+ // timestamp for dns and connection info.
+ if (!mAsyncOpen.IsNull()) {
+ if (!mDomainLookupStart.IsNull() && mDomainLookupStart < mAsyncOpen) {
+ mDomainLookupStart = mAsyncOpen;
+ }
+
+ if (!mDomainLookupEnd.IsNull() && mDomainLookupEnd < mAsyncOpen) {
+ mDomainLookupEnd = mAsyncOpen;
+ }
+
+ if (!mConnectStart.IsNull() && mConnectStart < mAsyncOpen) {
+ mConnectStart = mAsyncOpen;
+ }
+
+ if (mSecureConnection && !mSecureConnectionStart.IsNull() &&
+ mSecureConnectionStart < mAsyncOpen) {
+ mSecureConnectionStart = mAsyncOpen;
+ }
+
+ if (!mConnectEnd.IsNull() && mConnectEnd < mAsyncOpen) {
+ mConnectEnd = mAsyncOpen;
+ }
+ }
}
}
@@ -89,7 +135,7 @@ PerformanceTiming::FetchStartHighRes()
? TimeStampToDOMHighRes(mAsyncOpen)
: 0.0;
}
- return mFetchStart;
+ return TimerClamping::ReduceMsTimeValue(mFetchStart);
}
DOMTimeMilliSec
@@ -175,7 +221,7 @@ PerformanceTiming::RedirectStartHighRes()
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime;
}
- return TimeStampToDOMHighResOrFetchStart(mRedirectStart);
+ return TimeStampToReducedDOMHighResOrFetchStart(mRedirectStart);
}
DOMTimeMilliSec
@@ -208,7 +254,7 @@ PerformanceTiming::RedirectEndHighRes()
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime;
}
- return TimeStampToDOMHighResOrFetchStart(mRedirectEnd);
+ return TimeStampToReducedDOMHighResOrFetchStart(mRedirectEnd);
}
DOMTimeMilliSec
@@ -231,7 +277,7 @@ PerformanceTiming::DomainLookupStartHighRes()
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime;
}
- return TimeStampToDOMHighResOrFetchStart(mDomainLookupStart);
+ return TimeStampToReducedDOMHighResOrFetchStart(mDomainLookupStart);
}
DOMTimeMilliSec
@@ -248,7 +294,7 @@ PerformanceTiming::DomainLookupEndHighRes()
}
// Bug 1155008 - nsHttpTransaction is racy. Return DomainLookupStart when null
return mDomainLookupEnd.IsNull() ? DomainLookupStartHighRes()
- : TimeStampToDOMHighRes(mDomainLookupEnd);
+ : TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(mDomainLookupEnd));
}
DOMTimeMilliSec
@@ -264,7 +310,7 @@ PerformanceTiming::ConnectStartHighRes()
return mZeroTime;
}
return mConnectStart.IsNull() ? DomainLookupEndHighRes()
- : TimeStampToDOMHighRes(mConnectStart);
+ : TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(mConnectStart));
}
DOMTimeMilliSec
@@ -274,6 +320,25 @@ PerformanceTiming::ConnectStart()
}
DOMHighResTimeStamp
+PerformanceTiming::SecureConnectionStartHighRes()
+{
+ if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
+ return mZeroTime;
+ }
+ return !mSecureConnection
+ ? 0 // We use 0 here, because mZeroTime is sometimes set to the navigation
+ // start time.
+ : (mSecureConnectionStart.IsNull() ? mZeroTime
+ : TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(mSecureConnectionStart)));
+}
+
+DOMTimeMilliSec
+PerformanceTiming::SecureConnectionStart()
+{
+ return static_cast<int64_t>(SecureConnectionStartHighRes());
+}
+
+DOMHighResTimeStamp
PerformanceTiming::ConnectEndHighRes()
{
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
@@ -281,7 +346,7 @@ PerformanceTiming::ConnectEndHighRes()
}
// Bug 1155008 - nsHttpTransaction is racy. Return ConnectStart when null
return mConnectEnd.IsNull() ? ConnectStartHighRes()
- : TimeStampToDOMHighRes(mConnectEnd);
+ : TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(mConnectEnd));
}
DOMTimeMilliSec
@@ -296,7 +361,7 @@ PerformanceTiming::RequestStartHighRes()
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime;
}
- return TimeStampToDOMHighResOrFetchStart(mRequestStart);
+ return TimeStampToReducedDOMHighResOrFetchStart(mRequestStart);
}
DOMTimeMilliSec
@@ -315,7 +380,7 @@ PerformanceTiming::ResponseStartHighRes()
(!mCacheReadStart.IsNull() && mCacheReadStart < mResponseStart)) {
mResponseStart = mCacheReadStart;
}
- return TimeStampToDOMHighResOrFetchStart(mResponseStart);
+ return TimeStampToReducedDOMHighResOrFetchStart(mResponseStart);
}
DOMTimeMilliSec
@@ -336,7 +401,7 @@ PerformanceTiming::ResponseEndHighRes()
}
// Bug 1155008 - nsHttpTransaction is racy. Return ResponseStart when null
return mResponseEnd.IsNull() ? ResponseStartHighRes()
- : TimeStampToDOMHighRes(mResponseEnd);
+ : TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(mResponseEnd));
}
DOMTimeMilliSec
diff --git a/dom/performance/PerformanceTiming.h b/dom/performance/PerformanceTiming.h
index aef54a258..fc7e7d5bd 100644..100755
--- a/dom/performance/PerformanceTiming.h
+++ b/dom/performance/PerformanceTiming.h
@@ -10,6 +10,7 @@
#include "mozilla/Attributes.h"
#include "nsContentUtils.h"
#include "nsDOMNavigationTiming.h"
+#include "mozilla/TimerClamping.h"
#include "nsWrapperCache.h"
#include "Performance.h"
@@ -68,10 +69,10 @@ public:
* page), if the given TimeStamp is valid. Otherwise, it will return
* the FetchStart timing value.
*/
- inline DOMHighResTimeStamp TimeStampToDOMHighResOrFetchStart(TimeStamp aStamp)
+ inline DOMHighResTimeStamp TimeStampToReducedDOMHighResOrFetchStart(TimeStamp aStamp)
{
return (!aStamp.IsNull())
- ? TimeStampToDOMHighRes(aStamp)
+ ? TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(aStamp))
: FetchStartHighRes();
}
@@ -119,7 +120,7 @@ public:
if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0;
}
- return GetDOMTiming()->GetNavigationStart();
+ return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetNavigationStart());
}
DOMTimeMilliSec UnloadEventStart()
@@ -127,7 +128,7 @@ public:
if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0;
}
- return GetDOMTiming()->GetUnloadEventStart();
+ return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetUnloadEventStart());
}
DOMTimeMilliSec UnloadEventEnd()
@@ -135,7 +136,7 @@ public:
if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0;
}
- return GetDOMTiming()->GetUnloadEventEnd();
+ return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetUnloadEventEnd());
}
uint16_t GetRedirectCount() const;
@@ -161,6 +162,7 @@ public:
DOMHighResTimeStamp DomainLookupStartHighRes();
DOMHighResTimeStamp DomainLookupEndHighRes();
DOMHighResTimeStamp ConnectStartHighRes();
+ DOMHighResTimeStamp SecureConnectionStartHighRes();
DOMHighResTimeStamp ConnectEndHighRes();
DOMHighResTimeStamp RequestStartHighRes();
DOMHighResTimeStamp ResponseStartHighRes();
@@ -173,6 +175,7 @@ public:
DOMTimeMilliSec DomainLookupStart();
DOMTimeMilliSec DomainLookupEnd();
DOMTimeMilliSec ConnectStart();
+ DOMTimeMilliSec SecureConnectionStart();
DOMTimeMilliSec ConnectEnd();
DOMTimeMilliSec RequestStart();
DOMTimeMilliSec ResponseStart();
@@ -183,7 +186,7 @@ public:
if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0;
}
- return GetDOMTiming()->GetDomLoading();
+ return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetDomLoading());
}
DOMTimeMilliSec DomInteractive() const
@@ -191,7 +194,7 @@ public:
if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0;
}
- return GetDOMTiming()->GetDomInteractive();
+ return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetDomInteractive());
}
DOMTimeMilliSec DomContentLoadedEventStart() const
@@ -199,7 +202,7 @@ public:
if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0;
}
- return GetDOMTiming()->GetDomContentLoadedEventStart();
+ return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetDomContentLoadedEventStart());
}
DOMTimeMilliSec DomContentLoadedEventEnd() const
@@ -207,7 +210,7 @@ public:
if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0;
}
- return GetDOMTiming()->GetDomContentLoadedEventEnd();
+ return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetDomContentLoadedEventEnd());
}
DOMTimeMilliSec DomComplete() const
@@ -215,7 +218,7 @@ public:
if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0;
}
- return GetDOMTiming()->GetDomComplete();
+ return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetDomComplete());
}
DOMTimeMilliSec LoadEventStart() const
@@ -223,7 +226,7 @@ public:
if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0;
}
- return GetDOMTiming()->GetLoadEventStart();
+ return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetLoadEventStart());
}
DOMTimeMilliSec LoadEventEnd() const
@@ -231,7 +234,7 @@ public:
if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0;
}
- return GetDOMTiming()->GetLoadEventEnd();
+ return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetLoadEventEnd());
}
private:
@@ -255,6 +258,7 @@ private:
TimeStamp mDomainLookupStart;
TimeStamp mDomainLookupEnd;
TimeStamp mConnectStart;
+ TimeStamp mSecureConnectionStart;
TimeStamp mConnectEnd;
TimeStamp mRequestStart;
TimeStamp mResponseStart;
@@ -270,6 +274,8 @@ private:
// redirectEnd attributes. It is false if there were no redirects, or if
// any of the responses didn't pass the timing-allow-check
bool mReportCrossOriginRedirect;
+
+ bool mSecureConnection;
};
} // namespace dom
diff --git a/dom/performance/tests/test_performance_user_timing.js b/dom/performance/tests/test_performance_user_timing.js
index 3d05ebb77..cd8261bbd 100644
--- a/dom/performance/tests/test_performance_user_timing.js
+++ b/dom/performance/tests/test_performance_user_timing.js
@@ -263,7 +263,7 @@ var steps = [
performance.measure("test", n);
ok(true, "Measure created from reserved name as starting time: " + n);
} catch (e) {
- ok(["redirectStart", "redirectEnd", "unloadEventStart", "unloadEventEnd", "loadEventEnd"].indexOf(n) >= 0,
+ ok(["redirectStart", "redirectEnd", "unloadEventStart", "unloadEventEnd", "loadEventEnd", "secureConnectionStart"].indexOf(n) >= 0,
"Measure created from reserved name as starting time: " + n + " and threw expected error");
}
};
diff --git a/dom/performance/tests/test_worker_performance_now.js b/dom/performance/tests/test_worker_performance_now.js
index c2a905031..dee4efce6 100644
--- a/dom/performance/tests/test_worker_performance_now.js
+++ b/dom/performance/tests/test_worker_performance_now.js
@@ -26,51 +26,5 @@ var n = self.performance.now(), d = Date.now();
ok(n >= 0, "The value of now() should be equal to or greater than 0.");
ok(self.performance.now() >= n, "The value of now() should monotonically increase.");
-// The spec says performance.now() should have micro-second resolution, but allows 1ms if the platform doesn't support it.
-// Our implementation does provide micro-second resolution, except for windows XP combined with some HW properties
-// where we can't use QueryPerformanceCounters (see comments at mozilla-central/xpcom/ds/TimeStamp_windows.cpp).
-// This XP-low-res case results in about 15ms resolutions, and can be identified when perf.now() returns only integers.
-//
-// Since setTimeout might return too early/late, our goal is that perf.now() changed within 2ms
-// (or 25ms for XP-low-res), rather than specific number of setTimeout(N) invocations.
-// See bug 749894 (intermittent failures of this test)
-var platformPossiblyLowRes;
-workerTestGetOSCPU(function(oscpu) {
- platformPossiblyLowRes = oscpu.indexOf("Windows NT 5.1") == 0; // XP only
- setTimeout(checkAfterTimeout, 1);
-});
-var allInts = (n % 1) == 0; // Indicator of limited HW resolution.
-var checks = 0;
+workerTestDone();
-function checkAfterTimeout() {
- checks++;
- var d2 = Date.now();
- var n2 = self.performance.now();
-
- allInts = allInts && (n2 % 1) == 0;
- var lowResCounter = platformPossiblyLowRes && allInts;
-
- if ( n2 == n && checks < 50 && // 50 is just a failsafe. Our real goals are 2ms or 25ms.
- ( (d2 - d) < 2 // The spec allows 1ms resolution. We allow up to measured 2ms to ellapse.
- ||
- lowResCounter &&
- (d2 - d) < 25
- )
- ) {
- setTimeout(checkAfterTimeout, 1);
- return;
- }
-
- // Loose spec: 1ms resolution, or 15ms resolution for the XP-low-res case.
- // We shouldn't test that dt is actually within 2/25ms since the iterations break if it isn't, and timeout could be late.
- ok(n2 > n, "Loose - the value of now() should increase within 2ms (or 25ms if low-res counter) (delta now(): " + (n2 - n) + " ms).");
-
- // Strict spec: if it's not the XP-low-res case, while the spec allows 1ms resolution, it prefers microseconds, which we provide.
- // Since the fastest setTimeout return which I observed was ~500 microseconds, a microseconds counter should change in 1 iteretion.
- ok(n2 > n && (lowResCounter || checks == 1),
- "Strict - [if high-res counter] the value of now() should increase after one setTimeout (hi-res: " + (!lowResCounter) +
- ", iters: " + checks +
- ", dt: " + (d2 - d) +
- ", now(): " + n2 + ").");
- workerTestDone();
-};
diff --git a/dom/push/moz.build b/dom/push/moz.build
index b96099161..35683120f 100644
--- a/dom/push/moz.build
+++ b/dom/push/moz.build
@@ -16,7 +16,7 @@ EXTRA_JS_MODULES += [
'PushService.jsm',
]
-if CONFIG['MOZ_BUILD_APP'] != 'mobile/android':
+if not CONFIG['MOZ_FENNEC']:
# Everything but Fennec.
EXTRA_JS_MODULES += [
'PushServiceHttp2.jsm',
diff --git a/dom/security/nsCSPContext.cpp b/dom/security/nsCSPContext.cpp
index 815c7734d..5e435d4ca 100644
--- a/dom/security/nsCSPContext.cpp
+++ b/dom/security/nsCSPContext.cpp
@@ -156,10 +156,13 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
nsAutoString nonce;
bool parserCreated = false;
if (!isPreload) {
- nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(aRequestContext);
- if (htmlElement) {
- rv = htmlElement->GetAttribute(NS_LITERAL_STRING("nonce"), nonce);
- NS_ENSURE_SUCCESS(rv, rv);
+ if (aContentType == nsIContentPolicy::TYPE_SCRIPT ||
+ aContentType == nsIContentPolicy::TYPE_STYLESHEET) {
+ nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(aRequestContext);
+ if (htmlElement) {
+ rv = htmlElement->GetAttribute(NS_LITERAL_STRING("nonce"), nonce);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
}
nsCOMPtr<nsIScriptElement> script = do_QueryInterface(aRequestContext);
@@ -343,6 +346,20 @@ nsCSPContext::GetBlockAllMixedContent(bool *outBlockAllMixedContent)
}
NS_IMETHODIMP
+nsCSPContext::GetEnforcesFrameAncestors(bool *outEnforcesFrameAncestors)
+{
+ *outEnforcesFrameAncestors = false;
+ for (uint32_t i = 0; i < mPolicies.Length(); i++) {
+ if (!mPolicies[i]->getReportOnlyFlag() &&
+ mPolicies[i]->hasDirective(nsIContentSecurityPolicy::FRAME_ANCESTORS_DIRECTIVE)) {
+ *outEnforcesFrameAncestors = true;
+ return NS_OK;
+ }
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
nsCSPContext::GetReferrerPolicy(uint32_t* outPolicy, bool* outIsSet)
{
*outIsSet = false;
diff --git a/dom/security/nsCSPParser.cpp b/dom/security/nsCSPParser.cpp
index f1b5d8ba7..a0eba6918 100644
--- a/dom/security/nsCSPParser.cpp
+++ b/dom/security/nsCSPParser.cpp
@@ -136,6 +136,8 @@ nsCSPParser::nsCSPParser(cspTokens& aTokens,
, mUnsafeInlineKeywordSrc(nullptr)
, mChildSrc(nullptr)
, mFrameSrc(nullptr)
+ , mWorkerSrc(nullptr)
+ , mScriptSrc(nullptr)
, mParsingFrameAncestorsDir(false)
, mTokens(aTokens)
, mSelfURI(aSelfURI)
@@ -532,7 +534,7 @@ nsCSPParser::keywordSource()
// Special case handling for 'self' which is not stored internally as a keyword,
// but rather creates a nsCSPHostSrc using the selfURI
if (CSP_IsKeyword(mCurToken, CSP_SELF)) {
- return CSP_CreateHostSrcFromURI(mSelfURI);
+ return CSP_CreateHostSrcFromSelfURI(mSelfURI);
}
if (CSP_IsKeyword(mCurToken, CSP_STRICT_DYNAMIC)) {
@@ -1099,21 +1101,37 @@ nsCSPParser::directiveName()
return new nsUpgradeInsecureDirective(CSP_StringToCSPDirective(mCurToken));
}
- // child-src has it's own class to handle frame-src if necessary
+ // child-src by itself is deprecatd but will be enforced
+ // * for workers (if worker-src is not explicitly specified)
+ // * for frames (if frame-src is not explicitly specified)
if (CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::CHILD_SRC_DIRECTIVE)) {
+ const char16_t* params[] = { mCurToken.get() };
+ logWarningErrorToConsole(nsIScriptError::warningFlag,
+ "deprecatedChildSrcDirective",
+ params, ArrayLength(params));
mChildSrc = new nsCSPChildSrcDirective(CSP_StringToCSPDirective(mCurToken));
return mChildSrc;
}
- // if we have a frame-src, cache it so we can decide whether to use child-src
+ // if we have a frame-src, cache it so we can discard child-src for frames
if (CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::FRAME_SRC_DIRECTIVE)) {
- const char16_t* params[] = { mCurToken.get(), NS_LITERAL_STRING("child-src").get() };
- logWarningErrorToConsole(nsIScriptError::warningFlag, "deprecatedDirective",
- params, ArrayLength(params));
mFrameSrc = new nsCSPDirective(CSP_StringToCSPDirective(mCurToken));
return mFrameSrc;
}
+ // if we have a worker-src, cache it so we can discard child-src for workers
+ if (CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::WORKER_SRC_DIRECTIVE)) {
+ mWorkerSrc = new nsCSPDirective(CSP_StringToCSPDirective(mCurToken));
+ return mWorkerSrc;
+ }
+
+ // if we have a script-src, cache it as a fallback for worker-src
+ // in case child-src is not present
+ if (CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::SCRIPT_SRC_DIRECTIVE)) {
+ mScriptSrc = new nsCSPScriptSrcDirective(CSP_StringToCSPDirective(mCurToken));
+ return mScriptSrc;
+ }
+
if (CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::REQUIRE_SRI_FOR)) {
return new nsRequireSRIForDirective(CSP_StringToCSPDirective(mCurToken));
}
@@ -1290,9 +1308,22 @@ nsCSPParser::policy()
directive();
}
- if (mChildSrc && !mFrameSrc) {
- // if we have a child-src, it handles frame-src too, unless frame-src is set
- mChildSrc->setHandleFrameSrc();
+ if (mChildSrc) {
+ if (!mFrameSrc) {
+ // if frame-src is specified explicitly for that policy than child-src should
+ // not restrict frames; if not, than child-src needs to restrict frames.
+ mChildSrc->setRestrictFrames();
+ }
+ if (!mWorkerSrc) {
+ // if worker-src is specified explicitly for that policy than child-src should
+ // not restrict workers; if not, than child-src needs to restrict workers.
+ mChildSrc->setRestrictWorkers();
+ }
+ }
+ // if script-src is specified, but not worker-src and also no child-src, then
+ // script-src has to govern workers.
+ if (mScriptSrc && !mWorkerSrc && !mChildSrc) {
+ mScriptSrc->setRestrictWorkers();
}
return mPolicy;
diff --git a/dom/security/nsCSPParser.h b/dom/security/nsCSPParser.h
index 1bfc56c65..d500a1c18 100644
--- a/dom/security/nsCSPParser.h
+++ b/dom/security/nsCSPParser.h
@@ -243,14 +243,17 @@ class nsCSPParser {
bool mStrictDynamic; // false, if 'strict-dynamic' is not defined
nsCSPKeywordSrc* mUnsafeInlineKeywordSrc; // null, otherwise invlidate()
- // cache variables for child-src and frame-src directive handling.
- // frame-src is deprecated in favor of child-src, however if we
- // see a frame-src directive, it takes precedence for frames and iframes.
- // At the end of parsing, if we have a child-src directive, we need to
- // decide whether it will handle frames, or if there is a frame-src we
- // should honor instead.
- nsCSPChildSrcDirective* mChildSrc;
- nsCSPDirective* mFrameSrc;
+ // cache variables for child-src, frame-src and worker-src handling;
+ // in CSP 3 child-src is deprecated. For backwards compatibility
+ // child-src needs to restrict:
+ // (*) frames, in case frame-src is not expicitly specified
+ // (*) workers, in case worker-src is not expicitly specified
+ // If neither worker-src, nor child-src is present, then script-src
+ // needs to govern workers.
+ nsCSPChildSrcDirective* mChildSrc;
+ nsCSPDirective* mFrameSrc;
+ nsCSPDirective* mWorkerSrc;
+ nsCSPScriptSrcDirective* mScriptSrc;
// cache variable to let nsCSPHostSrc know that it's within
// the frame-ancestors directive.
diff --git a/dom/security/nsCSPUtils.cpp b/dom/security/nsCSPUtils.cpp
index b074a980c..49832f8f4 100644
--- a/dom/security/nsCSPUtils.cpp
+++ b/dom/security/nsCSPUtils.cpp
@@ -230,7 +230,7 @@ CSP_ContentTypeToDirective(nsContentPolicyType aType)
case nsIContentPolicy::TYPE_INTERNAL_WORKER:
case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER:
case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER:
- return nsIContentSecurityPolicy::CHILD_SRC_DIRECTIVE;
+ return nsIContentSecurityPolicy::WORKER_SRC_DIRECTIVE;
case nsIContentPolicy::TYPE_SUBDOCUMENT:
return nsIContentSecurityPolicy::FRAME_SRC_DIRECTIVE;
@@ -266,20 +266,21 @@ CSP_ContentTypeToDirective(nsContentPolicyType aType)
}
nsCSPHostSrc*
-CSP_CreateHostSrcFromURI(nsIURI* aURI)
+CSP_CreateHostSrcFromSelfURI(nsIURI* aSelfURI)
{
// Create the host first
nsCString host;
- aURI->GetHost(host);
+ aSelfURI->GetAsciiHost(host);
nsCSPHostSrc *hostsrc = new nsCSPHostSrc(NS_ConvertUTF8toUTF16(host));
+ hostsrc->setGeneratedFromSelfKeyword();
// Add the scheme.
nsCString scheme;
- aURI->GetScheme(scheme);
+ aSelfURI->GetScheme(scheme);
hostsrc->setScheme(NS_ConvertUTF8toUTF16(scheme));
int32_t port;
- aURI->GetPort(&port);
+ aSelfURI->GetPort(&port);
// Only add port if it's not default port.
if (port > 0) {
nsAutoString portStr;
@@ -348,13 +349,17 @@ CSP_IsQuotelessKeyword(const nsAString& aKey)
* @param aUpgradeInsecure
* Whether the policy makes use of the directive
* 'upgrade-insecure-requests'.
+ * @param aFromSelfURI
+ * Whether a scheme was generated from the keyword 'self'
+ * which then allows schemeless sources to match ws and wss.
*/
bool
permitsScheme(const nsAString& aEnforcementScheme,
nsIURI* aUri,
bool aReportOnly,
- bool aUpgradeInsecure)
+ bool aUpgradeInsecure,
+ bool aFromSelfURI)
{
nsAutoCString scheme;
nsresult rv = aUri->GetScheme(scheme);
@@ -373,8 +378,20 @@ permitsScheme(const nsAString& aEnforcementScheme,
// allow scheme-less sources where the protected resource is http
// and the load is https, see:
// http://www.w3.org/TR/CSP2/#match-source-expression
- if (aEnforcementScheme.EqualsASCII("http") &&
- scheme.EqualsASCII("https")) {
+ if (aEnforcementScheme.EqualsASCII("http")) {
+ if (scheme.EqualsASCII("https")) {
+ return true;
+ }
+ if ((scheme.EqualsASCII("ws") || scheme.EqualsASCII("wss")) && aFromSelfURI) {
+ return true;
+ }
+ }
+ if (aEnforcementScheme.EqualsASCII("https")) {
+ if (scheme.EqualsLiteral("wss") && aFromSelfURI) {
+ return true;
+ }
+ }
+ if (aEnforcementScheme.EqualsASCII("ws") && scheme.EqualsASCII("wss")) {
return true;
}
@@ -483,7 +500,7 @@ nsCSPSchemeSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirect
if (mInvalidated) {
return false;
}
- return permitsScheme(mScheme, aUri, aReportOnly, aUpgradeInsecure);
+ return permitsScheme(mScheme, aUri, aReportOnly, aUpgradeInsecure, false);
}
bool
@@ -503,6 +520,7 @@ nsCSPSchemeSrc::toString(nsAString& outStr) const
nsCSPHostSrc::nsCSPHostSrc(const nsAString& aHost)
: mHost(aHost)
+ , mGeneratedFromSelfKeyword(false)
, mWithinFrameAncstorsDir(false)
{
ToLowerCase(mHost);
@@ -612,7 +630,7 @@ nsCSPHostSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected
// http://www.w3.org/TR/CSP11/#match-source-expression
// 4.3) scheme matching: Check if the scheme matches.
- if (!permitsScheme(mScheme, aUri, aReportOnly, aUpgradeInsecure)) {
+ if (!permitsScheme(mScheme, aUri, aReportOnly, aUpgradeInsecure, mGeneratedFromSelfKeyword)) {
return false;
}
@@ -643,7 +661,7 @@ nsCSPHostSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected
// Before we can check if the host matches, we have to
// extract the host part from aUri.
nsAutoCString uriHost;
- nsresult rv = aUri->GetHost(uriHost);
+ nsresult rv = aUri->GetAsciiHost(uriHost);
NS_ENSURE_SUCCESS(rv, false);
nsString decodedUriHost;
@@ -1166,6 +1184,11 @@ nsCSPDirective::toDomCSPStruct(mozilla::dom::CSP& outCSP) const
outCSP.mSandbox.Value() = mozilla::Move(srcs);
return;
+ case nsIContentSecurityPolicy::WORKER_SRC_DIRECTIVE:
+ outCSP.mWorker_src.Construct();
+ outCSP.mWorker_src.Value() = mozilla::Move(srcs);
+ return;
+
// REFERRER_DIRECTIVE and REQUIRE_SRI_FOR are handled in nsCSPPolicy::toDomCSPStruct()
default:
@@ -1218,7 +1241,8 @@ bool nsCSPDirective::equals(CSPDirective aDirective) const
nsCSPChildSrcDirective::nsCSPChildSrcDirective(CSPDirective aDirective)
: nsCSPDirective(aDirective)
- , mHandleFrameSrc(false)
+ , mRestrictFrames(false)
+ , mRestrictWorkers(false)
{
}
@@ -1226,30 +1250,58 @@ nsCSPChildSrcDirective::~nsCSPChildSrcDirective()
{
}
-void nsCSPChildSrcDirective::setHandleFrameSrc()
-{
- mHandleFrameSrc = true;
-}
-
bool nsCSPChildSrcDirective::restrictsContentType(nsContentPolicyType aContentType) const
{
if (aContentType == nsIContentPolicy::TYPE_SUBDOCUMENT) {
- return mHandleFrameSrc;
+ return mRestrictFrames;
}
-
- return (aContentType == nsIContentPolicy::TYPE_INTERNAL_WORKER
- || aContentType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER
- || aContentType == nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER
- );
+ if (aContentType == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
+ aContentType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER ||
+ aContentType == nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER) {
+ return mRestrictWorkers;
+ }
+ return false;
}
bool nsCSPChildSrcDirective::equals(CSPDirective aDirective) const
{
if (aDirective == nsIContentSecurityPolicy::FRAME_SRC_DIRECTIVE) {
- return mHandleFrameSrc;
+ return mRestrictFrames;
}
+ if (aDirective == nsIContentSecurityPolicy::WORKER_SRC_DIRECTIVE) {
+ return mRestrictWorkers;
+ }
+ return (mDirective == aDirective);
+}
+
+/* =============== nsCSPScriptSrcDirective ============= */
+
+nsCSPScriptSrcDirective::nsCSPScriptSrcDirective(CSPDirective aDirective)
+ : nsCSPDirective(aDirective)
+ , mRestrictWorkers(false)
+{
+}
+
+nsCSPScriptSrcDirective::~nsCSPScriptSrcDirective()
+{
+}
- return (aDirective == nsIContentSecurityPolicy::CHILD_SRC_DIRECTIVE);
+bool nsCSPScriptSrcDirective::restrictsContentType(nsContentPolicyType aContentType) const
+{
+ if (aContentType == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
+ aContentType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER ||
+ aContentType == nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER) {
+ return mRestrictWorkers;
+ }
+ return mDirective == CSP_ContentTypeToDirective(aContentType);
+}
+
+bool nsCSPScriptSrcDirective::equals(CSPDirective aDirective) const
+{
+ if (aDirective == nsIContentSecurityPolicy::WORKER_SRC_DIRECTIVE) {
+ return mRestrictWorkers;
+ }
+ return (mDirective == aDirective);
}
/* =============== nsBlockAllMixedContentDirective ============= */
diff --git a/dom/security/nsCSPUtils.h b/dom/security/nsCSPUtils.h
index 468c734a2..91096712a 100644
--- a/dom/security/nsCSPUtils.h
+++ b/dom/security/nsCSPUtils.h
@@ -93,7 +93,8 @@ static const char* CSPStrDirectives[] = {
"child-src", // CHILD_SRC_DIRECTIVE
"block-all-mixed-content", // BLOCK_ALL_MIXED_CONTENT
"require-sri-for", // REQUIRE_SRI_FOR
- "sandbox" // SANDBOX_DIRECTIVE
+ "sandbox", // SANDBOX_DIRECTIVE
+ "worker-src" // WORKER_SRC_DIRECTIVE
};
inline const char* CSP_CSPDirectiveToString(CSPDirective aDir)
@@ -186,7 +187,7 @@ nsresult CSP_AppendCSPFromHeader(nsIContentSecurityPolicy* aCsp,
class nsCSPHostSrc;
-nsCSPHostSrc* CSP_CreateHostSrcFromURI(nsIURI* aURI);
+nsCSPHostSrc* CSP_CreateHostSrcFromSelfURI(nsIURI* aSelfURI);
bool CSP_IsValidDirective(const nsAString& aDir);
bool CSP_IsDirective(const nsAString& aValue, CSPDirective aDir);
bool CSP_IsKeyword(const nsAString& aValue, enum CSPKeyword aKey);
@@ -256,6 +257,9 @@ class nsCSPHostSrc : public nsCSPBaseSrc {
void setPort(const nsAString& aPort);
void appendPath(const nsAString &aPath);
+ inline void setGeneratedFromSelfKeyword() const
+ { mGeneratedFromSelfKeyword = true;}
+
inline void setWithinFrameAncestorsDir(bool aValue) const
{ mWithinFrameAncstorsDir = aValue; }
@@ -276,6 +280,7 @@ class nsCSPHostSrc : public nsCSPBaseSrc {
nsString mHost;
nsString mPort;
nsString mPath;
+ mutable bool mGeneratedFromSelfKeyword;
mutable bool mWithinFrameAncstorsDir;
};
@@ -441,7 +446,7 @@ class nsCSPDirective {
bool visitSrcs(nsCSPSrcVisitor* aVisitor) const;
- private:
+ protected:
CSPDirective mDirective;
nsTArray<nsCSPBaseSrc*> mSrcs;
};
@@ -449,26 +454,52 @@ class nsCSPDirective {
/* =============== nsCSPChildSrcDirective ============= */
/*
- * In CSP 2, the child-src directive covers both workers and
- * subdocuments (i.e., frames and iframes). Workers were removed
- * from script-src, but frames can be controlled by either child-src
- * or frame-src directives, so child-src needs to know whether it should
- * also restrict frames. When both are present the frame-src directive
- * takes precedent.
+ * In CSP 3 child-src is deprecated. For backwards compatibility
+ * child-src needs to restrict:
+ * (*) frames, in case frame-src is not expicitly specified
+ * (*) workers, in case worker-src is not expicitly specified
*/
class nsCSPChildSrcDirective : public nsCSPDirective {
public:
explicit nsCSPChildSrcDirective(CSPDirective aDirective);
virtual ~nsCSPChildSrcDirective();
- void setHandleFrameSrc();
+ void setRestrictFrames()
+ { mRestrictFrames = true; }
+
+ void setRestrictWorkers()
+ { mRestrictWorkers = true; }
+
+ virtual bool restrictsContentType(nsContentPolicyType aContentType) const;
+
+ virtual bool equals(CSPDirective aDirective) const;
+
+ private:
+ bool mRestrictFrames;
+ bool mRestrictWorkers;
+};
+
+/* =============== nsCSPScriptSrcDirective ============= */
+
+/*
+ * In CSP 3 worker-src restricts workers, for backwards compatibily
+ * script-src has to restrict workers as the ultimate fallback if
+ * neither worker-src nor child-src is present in a CSP.
+ */
+class nsCSPScriptSrcDirective : public nsCSPDirective {
+ public:
+ explicit nsCSPScriptSrcDirective(CSPDirective aDirective);
+ virtual ~nsCSPScriptSrcDirective();
+
+ void setRestrictWorkers()
+ { mRestrictWorkers = true; }
virtual bool restrictsContentType(nsContentPolicyType aContentType) const;
virtual bool equals(CSPDirective aDirective) const;
private:
- bool mHandleFrameSrc;
+ bool mRestrictWorkers;
};
/* =============== nsBlockAllMixedContentDirective === */
diff --git a/dom/security/test/csp/file_frame_src.js b/dom/security/test/csp/file_frame_src.js
new file mode 100644
index 000000000..8e81f0743
--- /dev/null
+++ b/dom/security/test/csp/file_frame_src.js
@@ -0,0 +1,14 @@
+let testframe = document.getElementById("testframe");
+testframe.onload = function() {
+ parent.postMessage({
+ result: "frame-allowed",
+ href: document.location.href,
+ }, "*");
+}
+testframe.onerror = function() {
+ parent.postMessage({
+ result: "frame-blocked",
+ href: document.location.href,
+ }, "*");
+}
+testframe.src = "file_frame_src_inner.html"
diff --git a/dom/security/test/csp/file_frame_src_child_governs.html b/dom/security/test/csp/file_frame_src_child_governs.html
new file mode 100644
index 000000000..a51cb75be
--- /dev/null
+++ b/dom/security/test/csp/file_frame_src_child_governs.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Security-Policy" content="child-src https://example.com">";
+</head>
+<body>
+<iframe id="testframe"></iframe>
+<script type="text/javascript" src="file_frame_src.js"></script>
+</body>
+</html>
diff --git a/dom/security/test/csp/file_frame_src_frame_governs.html b/dom/security/test/csp/file_frame_src_frame_governs.html
new file mode 100644
index 000000000..2c5d5857f
--- /dev/null
+++ b/dom/security/test/csp/file_frame_src_frame_governs.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Security-Policy" content="frame-src https://example.com; child-src 'none'">";
+</head>
+<body>
+<iframe id="testframe"></iframe>
+<script type="text/javascript" src="file_frame_src.js"></script>
+</body>
+</html>
diff --git a/dom/security/test/csp/file_frame_src_inner.html b/dom/security/test/csp/file_frame_src_inner.html
new file mode 100644
index 000000000..4a2fc6095
--- /dev/null
+++ b/dom/security/test/csp/file_frame_src_inner.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+dummy iframe
+</body>
+</html>
diff --git a/dom/security/test/csp/file_ignore_xfo.html b/dom/security/test/csp/file_ignore_xfo.html
new file mode 100644
index 000000000..6746a3adb
--- /dev/null
+++ b/dom/security/test/csp/file_ignore_xfo.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Bug 1024557: Ignore x-frame-options if CSP with frame-ancestors exists</title>
+</head>
+<body>
+<div id="cspmessage">Ignoring XFO because of CSP</div>
+</body>
+</html>
diff --git a/dom/security/test/csp/file_ignore_xfo.html^headers^ b/dom/security/test/csp/file_ignore_xfo.html^headers^
new file mode 100644
index 000000000..e93f9e3ec
--- /dev/null
+++ b/dom/security/test/csp/file_ignore_xfo.html^headers^
@@ -0,0 +1,3 @@
+Content-Security-Policy: frame-ancestors http://mochi.test:8888
+X-Frame-Options: deny
+Cache-Control: no-cache
diff --git a/dom/security/test/csp/file_image_nonce.html b/dom/security/test/csp/file_image_nonce.html
new file mode 100644
index 000000000..5d57bb837
--- /dev/null
+++ b/dom/security/test/csp/file_image_nonce.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>Bug 1355801: Nonce should not apply to images</title>
+ </head>
+<body>
+
+<img id='matchingNonce' src='http://mochi.test:8888/tests/image/test/mochitest/blue.png?a' nonce='abc'></img>
+<img id='nonMatchingNonce' src='http://mochi.test:8888/tests/image/test/mochitest/blue.png?b' nonce='bca'></img>
+<img id='noNonce' src='http://mochi.test:8888/tests/image/test/mochitest/blue.png?c'></img>
+
+<script type='application/javascript'>
+ var matchingNonce = document.getElementById('matchingNonce');
+ matchingNonce.onload = function(e) {
+ window.parent.postMessage({result: 'img-with-matching-nonce-loaded'}, '*');
+ };
+ matchingNonce.onerror = function(e) {
+ window.parent.postMessage({result: 'img-with-matching-nonce-blocked'}, '*');
+ }
+
+ var nonMatchingNonce = document.getElementById('nonMatchingNonce');
+ nonMatchingNonce.onload = function(e) {
+ window.parent.postMessage({result: 'img-with_non-matching-nonce-loaded'}, '*');
+ };
+ nonMatchingNonce.onerror = function(e) {
+ window.parent.postMessage({result: 'img-with_non-matching-nonce-blocked'}, '*');
+ }
+
+ var noNonce = document.getElementById('noNonce');
+ noNonce.onload = function(e) {
+ window.parent.postMessage({result: 'img-without-nonce-loaded'}, '*');
+ };
+ noNonce.onerror = function(e) {
+ window.parent.postMessage({result: 'img-without-nonce-blocked'}, '*');
+ }
+</script>
+</body>
+</html>
diff --git a/dom/security/test/csp/file_image_nonce.html^headers^ b/dom/security/test/csp/file_image_nonce.html^headers^
new file mode 100644
index 000000000..0d63558c4
--- /dev/null
+++ b/dom/security/test/csp/file_image_nonce.html^headers^
@@ -0,0 +1,2 @@
+Content-Security-Policy: img-src 'nonce-abc';
+Cache-Control: no-cache
diff --git a/dom/security/test/csp/file_punycode_host_src.js b/dom/security/test/csp/file_punycode_host_src.js
new file mode 100644
index 000000000..3505faf70
--- /dev/null
+++ b/dom/security/test/csp/file_punycode_host_src.js
@@ -0,0 +1,2 @@
+const LOADED = true;
+parent.postMessage({result: 'script-allowed'}, "*"); \ No newline at end of file
diff --git a/dom/security/test/csp/file_punycode_host_src.sjs b/dom/security/test/csp/file_punycode_host_src.sjs
new file mode 100644
index 000000000..3189cc063
--- /dev/null
+++ b/dom/security/test/csp/file_punycode_host_src.sjs
@@ -0,0 +1,45 @@
+// custom *.sjs for Bug 1224225
+// Punycode in CSP host sources
+
+const HTML_PART1 =
+ "<!DOCTYPE HTML>" +
+ "<html><head><meta charset=\"utf-8\">" +
+ "<title>Bug 1224225 - CSP source matching should work for punycoded domain names</title>" +
+ "</head>" +
+ "<body>" +
+ "<script id='script' src='";
+
+const TESTCASE1 = "http://sub2.ält.example.org/";
+const TESTCASE2 = "http://sub2.xn--lt-uia.example.org/"
+
+const HTML_PART2 = "tests/dom/security/test/csp/file_punycode_host_src.js'></script>" +
+ "</body>" +
+ "</html>";
+
+function handleRequest(request, response)
+{
+ // avoid confusing cache behaviors
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "text/html", false);
+
+ Components.utils.importGlobalProperties(["URLSearchParams"]);
+ const query = new URLSearchParams(request.queryString);
+
+
+ if (query.get("csp")) {
+ response.setHeader("Content-Security-Policy", query.get("csp"), false);
+ }
+ if (query.get("action") == "script-unicode-csp-punycode") {
+ response.write(HTML_PART1 + TESTCASE1 + HTML_PART2);
+ return
+ }
+ if (query.get("action") == "script-punycode-csp-punycode") {
+ response.write(HTML_PART1 + TESTCASE2 + HTML_PART2);
+ return
+ }
+
+
+ // we should never get here, but just in case
+ // return something unexpected
+ response.write("do'h");
+}
diff --git a/dom/security/test/csp/file_ro_ignore_xfo.html b/dom/security/test/csp/file_ro_ignore_xfo.html
new file mode 100644
index 000000000..85e7f0092
--- /dev/null
+++ b/dom/security/test/csp/file_ro_ignore_xfo.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Bug 1024557: Ignore x-frame-options if CSP with frame-ancestors exists</title>
+</head>
+<body>
+<div id="cspmessage">Ignoring XFO because of CSP_RO</div>
+</body>
+</html> \ No newline at end of file
diff --git a/dom/security/test/csp/file_ro_ignore_xfo.html^headers^ b/dom/security/test/csp/file_ro_ignore_xfo.html^headers^
new file mode 100644
index 000000000..ab8366f06
--- /dev/null
+++ b/dom/security/test/csp/file_ro_ignore_xfo.html^headers^
@@ -0,0 +1,3 @@
+Content-Security-Policy-Report-Only: frame-ancestors http://mochi.test:8888
+X-Frame-Options: deny
+Cache-Control: no-cache
diff --git a/dom/security/test/csp/file_spawn_service_worker.js b/dom/security/test/csp/file_spawn_service_worker.js
new file mode 100644
index 000000000..b262fa10a
--- /dev/null
+++ b/dom/security/test/csp/file_spawn_service_worker.js
@@ -0,0 +1 @@
+// dummy file
diff --git a/dom/security/test/csp/file_spawn_shared_worker.js b/dom/security/test/csp/file_spawn_shared_worker.js
new file mode 100644
index 000000000..00063bc5c
--- /dev/null
+++ b/dom/security/test/csp/file_spawn_shared_worker.js
@@ -0,0 +1,7 @@
+onconnect = function(e) {
+ var port = e.ports[0];
+ port.addEventListener("message", function(e) {
+ port.postMessage("shared worker is executing");
+ });
+ port.start();
+}
diff --git a/dom/security/test/csp/file_spawn_worker.js b/dom/security/test/csp/file_spawn_worker.js
new file mode 100644
index 000000000..acde7408c
--- /dev/null
+++ b/dom/security/test/csp/file_spawn_worker.js
@@ -0,0 +1 @@
+postMessage("worker is executing");
diff --git a/dom/security/test/csp/file_upgrade_insecure_navigation.sjs b/dom/security/test/csp/file_upgrade_insecure_navigation.sjs
new file mode 100644
index 000000000..51afa39bf
--- /dev/null
+++ b/dom/security/test/csp/file_upgrade_insecure_navigation.sjs
@@ -0,0 +1,79 @@
+// Custom *.sjs file specifically for the needs of
+// https://bugzilla.mozilla.org/show_bug.cgi?id=1271173
+
+"use strict";
+Components.utils.importGlobalProperties(["URLSearchParams"]);
+
+const TEST_NAVIGATIONAL_UPGRADE = `
+ <!DOCTYPE html>
+ <html>
+ <head><meta charset="utf-8"></head>
+ <body>
+ <a href="http://example.com/tests/dom/security/test/csp/file_upgrade_insecure_navigation.sjs?action=framenav" id="testlink">clickme</a>
+ <script type="text/javascript">
+ // before navigating the current frame we open the window and check that uir applies
+ var myWin = window.open("http://example.com/tests/dom/security/test/csp/file_upgrade_insecure_navigation.sjs?action=docnav");
+
+ window.addEventListener("message", receiveMessage, false);
+ function receiveMessage(event) {
+ myWin.close();
+ var link = document.getElementById('testlink');
+ link.click();
+ }
+ </script>
+ </body>
+ </html>`;
+
+const FRAME_NAV = `
+ <!DOCTYPE html>
+ <html>
+ <head><meta charset="utf-8"></head>
+ <body>
+ <script type="text/javascript">
+ parent.postMessage({result: document.documentURI}, "*");
+ </script>
+ </body>
+ </html>`;
+
+const DOC_NAV = `
+ <!DOCTYPE html>
+ <html>
+ <head><meta charset="utf-8"></head>
+ <body>
+ <script type="text/javascript">
+ // call back to the main testpage signaling whether the upgraded succeeded
+ window.opener.parent.postMessage({result: document.documentURI}, "*");
+ // let the opener (iframe) now that we can now close the window and move on with the test.
+ window.opener.postMessage({result: "readyToMoveOn"}, "*");
+ </script>
+ </body>
+ </html>`;
+
+function handleRequest(request, response) {
+ const query = new URLSearchParams(request.queryString);
+
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "text/html", false);
+ if (query.get("csp")) {
+ response.setHeader("Content-Security-Policy", query.get("csp"), false);
+ }
+
+ if (query.get("action") === "perform_navigation") {
+ response.write(TEST_NAVIGATIONAL_UPGRADE);
+ return;
+ }
+
+ if (query.get("action") === "framenav") {
+ response.write(FRAME_NAV);
+ return;
+ }
+
+ if (query.get("action") === "docnav") {
+ response.write(DOC_NAV);
+ return;
+ }
+
+ // we should never get here, but just in case
+ // return something unexpected
+ response.write("do'h");
+}
diff --git a/dom/security/test/csp/file_websocket_explicit.html b/dom/security/test/csp/file_websocket_explicit.html
new file mode 100644
index 000000000..51462ab74
--- /dev/null
+++ b/dom/security/test/csp/file_websocket_explicit.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Bug 1345615: Allow websocket schemes when using 'self' in CSP</title>
+ <meta http-equiv="Content-Security-Policy" content="connect-src ws:">
+</head>
+<body>
+ <script type="application/javascript">
+ /* load socket using ws */
+ var wsSocket = new WebSocket("ws://example.com/tests/dom/security/test/csp/file_websocket_self");
+ wsSocket.onopen = function(e) {
+ window.parent.postMessage({result: "explicit-ws-loaded"}, "*");
+ wsSocket.close();
+ };
+ wsSocket.onerror = function(e) {
+ window.parent.postMessage({result: "explicit-ws-blocked"}, "*");
+ };
+
+ /* load socket using wss */
+ var wssSocket = new WebSocket("wss://example.com/tests/dom/security/test/csp/file_websocket_self");
+ wssSocket.onopen = function(e) {
+ window.parent.postMessage({result: "explicit-wss-loaded"}, "*");
+ wssSocket.close();
+ };
+ wssSocket.onerror = function(e) {
+ window.parent.postMessage({result: "explicit-wss-blocked"}, "*");
+ };
+ </script>
+</body>
+</html>
diff --git a/dom/security/test/csp/file_websocket_self.html b/dom/security/test/csp/file_websocket_self.html
new file mode 100644
index 000000000..3ff5f0558
--- /dev/null
+++ b/dom/security/test/csp/file_websocket_self.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Bug 1345615: Allow websocket schemes when using 'self' in CSP</title>
+ <meta http-equiv="Content-Security-Policy" content="connect-src 'self'">
+</head>
+<body>
+ <script type="application/javascript">
+ /* load socket using ws */
+ var wsSocket = new WebSocket("ws://example.com/tests/dom/security/test/csp/file_websocket_self");
+ wsSocket.onopen = function(e) {
+ window.parent.postMessage({result: "self-ws-loaded"}, "*");
+ wsSocket.close();
+ };
+ wsSocket.onerror = function(e) {
+ window.parent.postMessage({result: "self-ws-blocked"}, "*");
+ };
+
+ /* load socket using wss */
+ var wssSocket = new WebSocket("wss://example.com/tests/dom/security/test/csp/file_websocket_self");
+ wssSocket.onopen = function(e) {
+ window.parent.postMessage({result: "self-wss-loaded"}, "*");
+ wssSocket.close();
+ };
+ wssSocket.onerror = function(e) {
+ window.parent.postMessage({result: "self-wss-blocked"}, "*");
+ };
+ </script>
+</body>
+</html>
diff --git a/dom/security/test/csp/file_websocket_self_wsh.py b/dom/security/test/csp/file_websocket_self_wsh.py
new file mode 100644
index 000000000..5fe508a91
--- /dev/null
+++ b/dom/security/test/csp/file_websocket_self_wsh.py
@@ -0,0 +1,7 @@
+from mod_pywebsocket import msgutil
+
+def web_socket_do_extra_handshake(request):
+ pass
+
+def web_socket_transfer_data(request):
+ pass
diff --git a/dom/security/test/csp/file_worker_src.js b/dom/security/test/csp/file_worker_src.js
new file mode 100644
index 000000000..ad3ade6a6
--- /dev/null
+++ b/dom/security/test/csp/file_worker_src.js
@@ -0,0 +1,52 @@
+
+let myWorker = new Worker("file_spawn_worker.js");
+myWorker.onmessage = function(event) {
+ parent.postMessage({
+ result: "worker-allowed",
+ href: document.location.href,
+ }, "*");
+}
+myWorker.onerror = function(event) {
+ parent.postMessage({
+ result: "worker-blocked",
+ href: document.location.href,
+ }, "*");
+}
+
+// --------------------------------------------
+
+var mySharedWorker = new SharedWorker('file_spawn_shared_worker.js');
+mySharedWorker.port.onmessage = function(ev) {
+ parent.postMessage({
+ result: "shared-worker-allowed",
+ href: document.location.href,
+ }, "*");
+}
+mySharedWorker.onerror = function(evt) {
+ evt.preventDefault();
+ parent.postMessage({
+ result: "shared-worker-blocked",
+ href: document.location.href,
+ }, "*");
+}
+mySharedWorker.port.start();
+mySharedWorker.port.postMessage('foo');
+
+// --------------------------------------------
+
+navigator.serviceWorker.register('file_spawn_service_worker.js')
+.then(function(reg) {
+ // registration worked
+ reg.unregister().then(function() {
+ parent.postMessage({
+ result: "service-worker-allowed",
+ href: document.location.href,
+ }, "*");
+ });
+}).catch(function(error) {
+ // registration failed
+ parent.postMessage({
+ result: "service-worker-blocked",
+ href: document.location.href,
+ }, "*");
+});
diff --git a/dom/security/test/csp/file_worker_src_child_governs.html b/dom/security/test/csp/file_worker_src_child_governs.html
new file mode 100644
index 000000000..ca8a683aa
--- /dev/null
+++ b/dom/security/test/csp/file_worker_src_child_governs.html
@@ -0,0 +1,9 @@
+<html>
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Security-Policy" content="child-src https://example.com; script-src 'nonce-foo'">";
+</head>
+<body>
+<script type="text/javascript" src="file_worker_src.js" nonce="foo"></script>
+</body>
+</html>
diff --git a/dom/security/test/csp/file_worker_src_script_governs.html b/dom/security/test/csp/file_worker_src_script_governs.html
new file mode 100644
index 000000000..0385fee57
--- /dev/null
+++ b/dom/security/test/csp/file_worker_src_script_governs.html
@@ -0,0 +1,9 @@
+<html>
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Security-Policy" content="script-src 'nonce-foo' https://example.com">";
+</head>
+<body>
+<script type="text/javascript" src="file_worker_src.js" nonce="foo"></script>
+</body>
+</html>
diff --git a/dom/security/test/csp/file_worker_src_worker_governs.html b/dom/security/test/csp/file_worker_src_worker_governs.html
new file mode 100644
index 000000000..93c8f6122
--- /dev/null
+++ b/dom/security/test/csp/file_worker_src_worker_governs.html
@@ -0,0 +1,9 @@
+<html>
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Security-Policy" content="worker-src https://example.com; child-src 'none'; script-src 'nonce-foo'">";
+</head>
+<body>
+<script type="text/javascript" src="file_worker_src.js" nonce="foo"></script>
+</body>
+</html>
diff --git a/dom/security/test/csp/mochitest.ini b/dom/security/test/csp/mochitest.ini
index 8add999c3..ca5c2c6ea 100644
--- a/dom/security/test/csp/mochitest.ini
+++ b/dom/security/test/csp/mochitest.ini
@@ -206,6 +206,18 @@ support-files =
file_iframe_srcdoc.sjs
file_iframe_sandbox_srcdoc.html
file_iframe_sandbox_srcdoc.html^headers^
+ file_ignore_xfo.html
+ file_ignore_xfo.html^headers^
+ file_ro_ignore_xfo.html
+ file_ro_ignore_xfo.html^headers^
+ file_upgrade_insecure_navigation.sjs
+ file_image_nonce.html
+ file_image_nonce.html^headers^
+ file_punycode_host_src.sjs
+ file_punycode_host_src.js
+ file_websocket_self.html
+ file_websocket_explicit.html
+ file_websocket_self_wsh.py
[test_base-uri.html]
[test_blob_data_schemes.html]
@@ -292,9 +304,30 @@ tags = mcb
[test_strict_dynamic.html]
[test_strict_dynamic_parser_inserted.html]
[test_strict_dynamic_default_src.html]
+[test_upgrade_insecure_navigation.html]
[test_iframe_sandbox_srcdoc.html]
[test_iframe_srcdoc.html]
[test_sandbox_allow_scripts.html]
support-files =
file_sandbox_allow_scripts.html
file_sandbox_allow_scripts.html^headers^
+[test_ignore_xfo.html]
+[test_image_nonce.html]
+[test_punycode_host_src.html]
+[test_websocket_self.html]
+skip-if = toolkit == 'android'
+[test_worker_src.html]
+support-files =
+ file_worker_src_worker_governs.html
+ file_worker_src_child_governs.html
+ file_worker_src_script_governs.html
+ file_worker_src.js
+ file_spawn_worker.js
+ file_spawn_shared_worker.js
+ file_spawn_service_worker.js
+[test_frame_src.html]
+support-files =
+ file_frame_src_frame_governs.html
+ file_frame_src_child_governs.html
+ file_frame_src.js
+ file_frame_src_inner.html
diff --git a/dom/security/test/csp/test_child-src_worker.html b/dom/security/test/csp/test_child-src_worker.html
index 7dcbd03f6..ea9e7b28e 100644
--- a/dom/security/test/csp/test_child-src_worker.html
+++ b/dom/security/test/csp/test_child-src_worker.html
@@ -83,19 +83,19 @@
id: "script-src-worker",
file: WORKER_TEST_FILE,
result : "blocked",
- policy : "default-src 'none'; script-src 'self' 'unsafe-inline'"
+ policy : "default-src 'none'; script-src https://www.example.org 'unsafe-inline'"
},
'script-src-service_worker': {
id: "script-src-service_worker",
file: SERVICE_WORKER_TEST_FILE,
result : "blocked",
- policy : "default-src 'none'; script-src 'self' 'unsafe-inline'"
+ policy : "default-src 'none'; script-src https://www.example.org 'unsafe-inline'"
},
'script-src-self-shared_worker': {
id: "script-src-self-shared_worker",
file: SHARED_WORKER_TEST_FILE,
result : "blocked",
- policy : "default-src 'none'; script-src 'self' 'unsafe-inline'"
+ policy : "default-src 'none'; script-src https://www.example.org 'unsafe-inline'"
},
};
diff --git a/dom/security/test/csp/test_frame_src.html b/dom/security/test/csp/test_frame_src.html
new file mode 100644
index 000000000..07de90cfa
--- /dev/null
+++ b/dom/security/test/csp/test_frame_src.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Bug 1302667 - Test frame-src</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<iframe style="width:100%;" id="testframe"></iframe>
+
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+/* Description of the test:
+ * We load a page inlcuding a frame a CSP of:
+ * >> frame-src https://example.com; child-src 'none'
+ * and make sure that frame-src governs frames correctly. In addition,
+ * we make sure that child-src is discarded in case frame-src is specified.
+ */
+
+const ORIGIN_1 = "https://example.com/tests/dom/security/test/csp/";
+const ORIGIN_2 = "https://test1.example.com/tests/dom/security/test/csp/";
+
+let TESTS = [
+ // frame-src tests
+ ORIGIN_1 + "file_frame_src_frame_governs.html",
+ ORIGIN_2 + "file_frame_src_frame_governs.html",
+ // child-src tests
+ ORIGIN_1 + "file_frame_src_child_governs.html",
+ ORIGIN_2 + "file_frame_src_child_governs.html",
+];
+
+let testIndex = 0;
+
+function checkFinish() {
+ if (testIndex >= TESTS.length) {
+ window.removeEventListener("message", receiveMessage);
+ SimpleTest.finish();
+ return;
+ }
+ runNextTest();
+}
+
+window.addEventListener("message", receiveMessage);
+function receiveMessage(event) {
+ let href = event.data.href;
+ let result = event.data.result;
+
+ if (href.startsWith("https://example.com")) {
+ if (result == "frame-allowed") {
+ ok(true, "allowing frame from https://example.com (" + result + ")");
+ }
+ else {
+ ok(false, "blocking frame from https://example.com (" + result + ")");
+ }
+ }
+ else if (href.startsWith("https://test1.example.com")) {
+ if (result == "frame-blocked") {
+ ok(true, "blocking frame from https://test1.example.com (" + result + ")");
+ }
+ else {
+ ok(false, "allowing frame from https://test1.example.com (" + result + ")");
+ }
+ }
+ else {
+ // sanity check, we should never enter that branch, bust just in case...
+ ok(false, "unexpected result: " + result);
+ }
+ checkFinish();
+}
+
+function runNextTest() {
+ document.getElementById("testframe").src = TESTS[testIndex];
+ testIndex++;
+}
+
+// fire up the tests
+runNextTest();
+
+</script>
+</body>
+</html>
diff --git a/dom/security/test/csp/test_ignore_xfo.html b/dom/security/test/csp/test_ignore_xfo.html
new file mode 100644
index 000000000..fb3aadc6c
--- /dev/null
+++ b/dom/security/test/csp/test_ignore_xfo.html
@@ -0,0 +1,59 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Bug 1024557: Ignore x-frame-options if CSP with frame-ancestors exists</title>
+ <!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<iframe style="width:100%;" id="csp_testframe"></iframe>
+<iframe style="width:100%;" id="csp_ro_testframe"></iframe>
+
+<script class="testbody" type="text/javascript">
+
+/*
+ * We load two frames using:
+ * x-frame-options: deny
+ * where the first frame uses a csp and the second a csp_ro including frame-ancestors.
+ * We make sure that xfo is ignored for regular csp but not for csp_ro.
+ */
+
+SimpleTest.waitForExplicitFinish();
+
+var testcounter = 0;
+function checkFinished() {
+ testcounter++;
+ if (testcounter < 2) {
+ return;
+ }
+ SimpleTest.finish();
+}
+
+// 1) test XFO with CSP
+var csp_testframe = document.getElementById("csp_testframe");
+csp_testframe.onload = function() {
+ var msg = csp_testframe.contentWindow.document.getElementById("cspmessage");
+ is(msg.innerHTML, "Ignoring XFO because of CSP", "Loading frame with with XFO and CSP");
+ checkFinished();
+}
+csp_testframe.onerror = function() {
+ ok(false, "sanity: should not fire onerror for csp_testframe");
+}
+csp_testframe.src = "file_ignore_xfo.html";
+
+// 2) test XFO with CSP_RO
+var csp_ro_testframe = document.getElementById("csp_ro_testframe");
+csp_ro_testframe.onload = function() {
+ var msg = csp_ro_testframe.contentWindow.document.getElementById("cspmessage");
+ is(msg, null, "Blocking frame with with XFO and CSP_RO");
+ checkFinished();
+}
+csp_ro_testframe.onerror = function() {
+ ok(false, "sanity: should not fire onerror for csp_ro_testframe");
+}
+csp_ro_testframe.src = "file_ro_ignore_xfo.html";
+
+</script>
+</body>
+</html>
diff --git a/dom/security/test/csp/test_image_nonce.html b/dom/security/test/csp/test_image_nonce.html
new file mode 100644
index 000000000..ff6d636b6
--- /dev/null
+++ b/dom/security/test/csp/test_image_nonce.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Bug 1139297 - Implement CSP upgrade-insecure-requests directive</title>
+ <!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<iframe style="width:100%;" id="testframe"></iframe>
+
+<script class="testbody" type="text/javascript">
+
+/* Description of the test:
+ * We load three images: (a) with a matching nonce,
+ (b) with a non matching nonce,
+ * (c) with no nonce
+ * and make sure that all three images get blocked because
+ * "img-src nonce-bla" should not allow an image load, not
+ * even if the nonce matches*.
+ */
+
+SimpleTest.waitForExplicitFinish();
+
+var counter = 0;
+
+function finishTest() {
+ window.removeEventListener("message", receiveMessage);
+ SimpleTest.finish();
+}
+
+function checkResults(aResult) {
+ counter++;
+ if (aResult === "img-with-matching-nonce-blocked" ||
+ aResult === "img-with_non-matching-nonce-blocked" ||
+ aResult === "img-without-nonce-blocked") {
+ ok (true, "correct result for: " + aResult);
+ }
+ else {
+ ok(false, "unexpected result: " + aResult + "\n\n");
+ }
+ if (counter < 3) {
+ return;
+ }
+ finishTest();
+}
+
+// a postMessage handler that is used by sandboxed iframes without
+// 'allow-same-origin' to bubble up results back to this main page.
+window.addEventListener("message", receiveMessage);
+function receiveMessage(event) {
+ checkResults(event.data.result);
+}
+
+document.getElementById("testframe").src = "file_image_nonce.html";
+
+</script>
+</body>
+</html>
diff --git a/dom/security/test/csp/test_punycode_host_src.html b/dom/security/test/csp/test_punycode_host_src.html
new file mode 100644
index 000000000..8d891725c
--- /dev/null
+++ b/dom/security/test/csp/test_punycode_host_src.html
@@ -0,0 +1,81 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Bug 1224225 - CSP source matching should work for punycoded domain names</title>
+ <!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<iframe style="width:100%;" id="testframe"></iframe>
+
+<script class="testbody" type="text/javascript">
+
+/* Description of the test:
+ * We load scripts within an iframe and make sure that the
+ * CSP matching is same for punycode domain names as well as IDNA.
+ */
+
+SimpleTest.waitForExplicitFinish();
+
+
+var curTest;
+var counter = -1;
+
+const tests = [
+ { // test 1
+ description: "loads script as sub2.ält.example.org, but whitelist in CSP as sub2.xn--lt-uia.example.org",
+ action: "script-unicode-csp-punycode",
+ csp: "script-src http://sub2.xn--lt-uia.example.org;",
+ expected: "script-allowed",
+
+ },
+ { // test 2
+ description: "loads script as sub2.xn--lt-uia.example.org, and whitelist in CSP as sub2.xn--lt-uia.example.org",
+ action: "script-punycode-csp-punycode",
+ csp: "script-src http://sub2.xn--lt-uia.example.org;",
+ expected: "script-allowed",
+
+ },
+ { // test 3
+ description: "loads script as sub2.xn--lt-uia.example.org, and whitelist in CSP as sub2.xn--lt-uia.example.org",
+ action: "script-punycode-csp-punycode",
+ csp: "script-src *.xn--lt-uia.example.org;",
+ expected: "script-allowed",
+
+ },
+
+];
+
+function finishTest() {
+ window.removeEventListener("message", receiveMessage);
+ SimpleTest.finish();
+}
+
+function checkResults(result) {
+ is(result, curTest.expected, curTest.description);
+ loadNextTest();
+}
+
+window.addEventListener("message", receiveMessage);
+function receiveMessage(event) {
+ checkResults(event.data.result);
+}
+
+function loadNextTest() {
+ counter++;
+ if (counter == tests.length) {
+ finishTest();
+ return;
+ }
+ curTest = tests[counter];
+ var testframe = document.getElementById("testframe");
+ testframe.src = `file_punycode_host_src.sjs?action=${curTest.action}&csp=${curTest.csp}`;
+}
+
+loadNextTest();
+
+</script>
+</body>
+</html>
diff --git a/dom/security/test/csp/test_upgrade_insecure_navigation.html b/dom/security/test/csp/test_upgrade_insecure_navigation.html
new file mode 100644
index 000000000..db6a6a1be
--- /dev/null
+++ b/dom/security/test/csp/test_upgrade_insecure_navigation.html
@@ -0,0 +1,103 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Bug 1271173 - Missing spec on Upgrade Insecure Requests(Navigational Upgrades) </title>
+ <!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<iframe style="width:100%;" id="testframe"></iframe>
+<iframe style="width:100%;" id="sandboxedtestframe"
+ sandbox="allow-scripts allow-top-navigation allow-same-origin allow-pointer-lock allow-popups"></iframe>
+
+<script class="testbody" type="text/javascript">
+/*
+ * Description of the test:
+ * We load a page into an iframe that performs a navigational request.
+ * We make sure that upgrade-insecure-requests applies and the page
+ * gets upgraded to https if same origin.
+ * Please note that uir only applies to sandboxed iframes if
+ * the value 'allow-same-origin' is specified.
+ */
+
+SimpleTest.waitForExplicitFinish();
+
+var tests = [
+ {
+ csp: "upgrade-insecure-requests;",
+ result: "https",
+ origin: "http://example.com",
+ desc: "upgrade-insecure-requests same origin should upgrade"
+ },
+ {
+ csp: "",
+ result: "http",
+ origin: "http://example.com",
+ desc: "No upgrade-insecure-requests same origin should not upgrade"
+ },
+ {
+ csp: "upgrade-insecure-requests;",
+ result: "http",
+ origin: "http://mochi.test:8888",
+ desc: "upgrade-insecure-requests cross origin should not upgrade"
+ },
+ {
+ csp: "",
+ result: "http",
+ origin: "http://mochi.test:8888",
+ desc: "No upgrade-insecure-requests cross origin should not upgrade"
+ },
+];
+
+// initializing to -1 so we start at index 0 when we start the test
+var counter = -1;
+
+function finishTest() {
+ window.removeEventListener("message", receiveMessage, false);
+ SimpleTest.finish();
+}
+
+var subtests = 0;
+
+window.addEventListener("message", receiveMessage, false);
+function receiveMessage(event) {
+ var result = event.data.result;
+ // query the scheme from the URL before comparing the result
+ var scheme = result.substring(0, result.indexOf(":"));
+ is(scheme, tests[counter].result, tests[counter].desc);
+
+ // @hardcoded 4:
+ // each test run contains of two subtests (frame and top-level)
+ // and we load each test into a regular iframe and into a
+ // sandboxed iframe. only move on to the next test once all
+ // four results from the subtests have bubbled up.
+ subtests++;
+ if (subtests != 4) {
+ return;
+ }
+ subtests = 0;
+ loadNextTest();
+}
+
+function loadNextTest() {
+ counter++;
+ if (counter == tests.length) {
+ finishTest();
+ return;
+ }
+
+ var src = tests[counter].origin;
+ src += "/tests/dom/security/test/csp/file_upgrade_insecure_navigation.sjs";
+ src += "?csp=" + escape(tests[counter].csp);
+ src += "&action=perform_navigation";
+ document.getElementById("testframe").src = src;
+ document.getElementById("sandboxedtestframe").src = src;
+}
+
+// start running the tests
+loadNextTest();
+
+</script>
+</body>
+</html>
diff --git a/dom/security/test/csp/test_websocket_self.html b/dom/security/test/csp/test_websocket_self.html
new file mode 100644
index 000000000..a03c32704
--- /dev/null
+++ b/dom/security/test/csp/test_websocket_self.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Bug 1345615: Allow websocket schemes when using 'self' in CSP</title>
+ <!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<iframe style="width:100%;" id="test_ws_self_frame"></iframe>
+<iframe style="width:100%;" id="test_ws_explicit_frame"></iframe>
+
+<script class="testbody" type="text/javascript">
+
+/* Description of the test:
+ * We load an iframe using connect-src 'self' and one
+ * iframe using connect-src ws: and make
+ * sure that in both cases ws: as well as wss: is allowed to load.
+ */
+
+SimpleTest.waitForExplicitFinish();
+
+function finishTest() {
+ window.removeEventListener("message", receiveMessage);
+ SimpleTest.finish();
+}
+
+const TOTAL_TESTS = 4;
+var counter = 0;
+
+function checkResults(result) {
+ counter++;
+ if (result === "self-ws-loaded" || result === "self-wss-loaded" ||
+ result === "explicit-ws-loaded" || result === "explicit-wss-loaded") {
+ ok(true, "Evaluating: " + result);
+ }
+ else {
+ ok(false, "Evaluating: " + result);
+ }
+ if (counter < TOTAL_TESTS) {
+ return;
+ }
+ finishTest();
+}
+
+window.addEventListener("message", receiveMessage);
+function receiveMessage(event) {
+ checkResults(event.data.result);
+}
+
+const HOST = "http://example.com/tests/dom/security/test/csp/";
+var test_ws_self_frame = document.getElementById("test_ws_self_frame");
+test_ws_self_frame.src = HOST + "file_websocket_self.html";
+
+var test_ws_explicit_frame = document.getElementById("test_ws_explicit_frame");
+test_ws_explicit_frame.src = HOST + "file_websocket_explicit.html";
+
+</script>
+</body>
+</html>
diff --git a/dom/security/test/csp/test_worker_src.html b/dom/security/test/csp/test_worker_src.html
new file mode 100644
index 000000000..3f2b44c9f
--- /dev/null
+++ b/dom/security/test/csp/test_worker_src.html
@@ -0,0 +1,94 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Bug 1302667 - Test worker-src</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<iframe style="width:100%;" id="worker-testframe"></iframe>
+<iframe style="width:100%;" id="child-testframe"></iframe>
+<iframe style="width:100%;" id="script-testframe"></iframe>
+
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+/* Description of the test:
+ * We load a page inlcuding a worker, a shared worker as well as a
+ * service worker with a CSP of:
+ * >> worker-src https://example.com; child-src 'none'; script-src 'nonce-foo'
+ * and make sure that worker-src governs these three kinds of workers correctly.
+ * In addition, we make sure that child-src as well as script-src is discarded
+ * in case worker-src is specified. Ideally we would use "script-src 'none'" but
+ * we have to whitelist the actual script that spawns the workers, hence the nonce.
+ */
+
+let testRuns = 0;
+let messageCounter = 0;
+let numberSubTests = 9; // 3 workers * 3 frames = 9
+
+function checkFinish() {
+ messageCounter = 0;
+ if (testRuns == 0) {
+ testRuns++;
+ runTests("https://test1.example.com/tests/dom/security/test/csp/")
+ return;
+ }
+ window.removeEventListener("message", receiveMessage);
+ SimpleTest.finish();
+}
+
+window.addEventListener("message", receiveMessage);
+function receiveMessage(event) {
+ let href = event.data.href;
+ let result = event.data.result;
+
+ if (href.startsWith("https://example.com")) {
+ if (result == "worker-allowed" ||
+ result == "shared-worker-allowed" ||
+ result == "service-worker-allowed") {
+ ok(true, "allowing worker from https://example.com (" + result + ")");
+ }
+ else {
+ ok(false, "blocking worker from https://example.com (" + result + ")");
+ }
+ }
+ else if (href.startsWith("https://test1.example.com")) {
+ if (result == "worker-blocked" ||
+ result == "shared-worker-blocked" ||
+ result == "service-worker-blocked") {
+ ok(true, "blocking worker from https://test1.example.com (" + result + ")");
+ }
+ else {
+ ok(false, "allowing worker from https://test1.example.com (" + result + ")");
+ }
+ }
+ else {
+ // sanity check, we should never enter that branch, bust just in case...
+ ok(false, "unexpected result: " + result);
+ }
+ messageCounter++;
+ if (messageCounter < numberSubTests) {
+ return;
+ }
+ checkFinish();
+}
+
+function runTests(aPath) {
+ document.getElementById("worker-testframe").src = aPath + "file_worker_src_worker_governs.html";
+ document.getElementById("child-testframe").src = aPath + "file_worker_src_child_governs.html";
+ document.getElementById("script-testframe").src = aPath + "file_worker_src_script_governs.html";
+}
+
+SpecialPowers.pushPrefEnv({"set": [
+ ["dom.serviceWorkers.enabled", true],
+ ["dom.serviceWorkers.testing.enabled", true],
+]}, function() {
+ runTests("https://example.com/tests/dom/security/test/csp/");
+});
+
+</script>
+</body>
+</html>
diff --git a/dom/security/test/gtest/TestCSPParser.cpp b/dom/security/test/gtest/TestCSPParser.cpp
index fafa7b5d9..893e02db5 100644
--- a/dom/security/test/gtest/TestCSPParser.cpp
+++ b/dom/security/test/gtest/TestCSPParser.cpp
@@ -204,6 +204,8 @@ TEST(CSPParser, Directives)
{
static const PolicyTest policies[] =
{
+ { "connect-src xn--mnchen-3ya.de",
+ "connect-src http://xn--mnchen-3ya.de"},
{ "default-src http://www.example.com",
"default-src http://www.example.com" },
{ "script-src http://www.example.com",
@@ -238,6 +240,10 @@ TEST(CSPParser, Directives)
"script-src 'nonce-foo' 'strict-dynamic' 'unsafe-inline' https:" },
{ "default-src 'sha256-siVR8' 'strict-dynamic' 'unsafe-inline' https: ",
"default-src 'sha256-siVR8' 'unsafe-inline' https:" },
+ { "worker-src https://example.com",
+ "worker-src https://example.com" },
+ { "worker-src http://worker.com; frame-src http://frame.com; child-src http://child.com",
+ "worker-src http://worker.com; frame-src http://frame.com; child-src http://child.com" },
};
uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);
diff --git a/dom/svg/DOMSVGPathSegList.cpp b/dom/svg/DOMSVGPathSegList.cpp
index edacdfc93..0b811cdb1 100644
--- a/dom/svg/DOMSVGPathSegList.cpp
+++ b/dom/svg/DOMSVGPathSegList.cpp
@@ -460,6 +460,18 @@ DOMSVGPathSegList::ReplaceItem(DOMSVGPathSeg& aNewItem,
float segAsRaw[1 + NS_SVG_PATH_SEG_MAX_ARGS];
domItem->ToSVGPathSegEncodedData(segAsRaw);
+ if (AnimListMirrorsBaseList()) {
+ // The anim val list is in sync with the base val list - remove mirroring
+ // animVal item if necessary. We do this *before* touching InternalList()
+ // so the removed item can correctly store its internal value.
+ DOMSVGPathSegList* animVal =
+ GetDOMWrapperIfExists(InternalAList().GetAnimValKey());
+ if (animVal->ItemAt(aIndex)) {
+ animVal->ItemAt(aIndex)->RemovingFromList();
+ animVal->ItemAt(aIndex) = nullptr;
+ }
+ }
+
if (!InternalList().mData.ReplaceElementsAt(internalIndex, 1 + oldArgCount,
segAsRaw, 1 + newArgCount,
fallible)) {
@@ -474,8 +486,13 @@ DOMSVGPathSegList::ReplaceItem(DOMSVGPathSeg& aNewItem,
int32_t delta = newArgCount - oldArgCount;
if (delta != 0) {
- for (uint32_t i = aIndex + 1; i < LengthNoFlush(); ++i) {
- mItems[i].mInternalDataIndex += delta;
+ // Sync up the internal indexes of all ItemProxys that come after aIndex:
+ UpdateListIndicesFromIndex(aIndex + 1, delta);
+ if (AnimListMirrorsBaseList()) {
+ // The anim val list is in sync with the base val list
+ DOMSVGPathSegList* animVal =
+ GetDOMWrapperIfExists(InternalAList().GetAnimValKey());
+ animVal->UpdateListIndicesFromIndex(aIndex + 1, delta);
}
}
diff --git a/dom/svg/SVGGradientElement.cpp b/dom/svg/SVGGradientElement.cpp
index 1bcac67e6..93767c934 100644
--- a/dom/svg/SVGGradientElement.cpp
+++ b/dom/svg/SVGGradientElement.cpp
@@ -198,13 +198,14 @@ SVGRadialGradientElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenP
return SVGRadialGradientElementBinding::Wrap(aCx, this, aGivenProto);
}
-nsSVGElement::LengthInfo SVGRadialGradientElement::sLengthInfo[5] =
+nsSVGElement::LengthInfo SVGRadialGradientElement::sLengthInfo[6] =
{
{ &nsGkAtoms::cx, 50, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::X },
{ &nsGkAtoms::cy, 50, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::Y },
{ &nsGkAtoms::r, 50, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::XY },
{ &nsGkAtoms::fx, 50, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::X },
{ &nsGkAtoms::fy, 50, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::Y },
+ { &nsGkAtoms::fr, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::XY },
};
//----------------------------------------------------------------------
@@ -252,6 +253,12 @@ SVGRadialGradientElement::Fy()
return mLengthAttributes[ATTR_FY].ToDOMAnimatedLength(this);
}
+already_AddRefed<SVGAnimatedLength>
+SVGRadialGradientElement::Fr()
+{
+ return mLengthAttributes[ATTR_FR].ToDOMAnimatedLength(this);
+}
+
//----------------------------------------------------------------------
// nsSVGElement methods
diff --git a/dom/svg/SVGGradientElement.h b/dom/svg/SVGGradientElement.h
index 7b2c6b220..ce9f3b4b1 100644
--- a/dom/svg/SVGGradientElement.h
+++ b/dom/svg/SVGGradientElement.h
@@ -139,13 +139,14 @@ public:
already_AddRefed<SVGAnimatedLength> R();
already_AddRefed<SVGAnimatedLength> Fx();
already_AddRefed<SVGAnimatedLength> Fy();
+ already_AddRefed<SVGAnimatedLength> Fr();
protected:
virtual LengthAttributesInfo GetLengthInfo() override;
- enum { ATTR_CX, ATTR_CY, ATTR_R, ATTR_FX, ATTR_FY };
- nsSVGLength2 mLengthAttributes[5];
- static LengthInfo sLengthInfo[5];
+ enum { ATTR_CX, ATTR_CY, ATTR_R, ATTR_FX, ATTR_FY, ATTR_FR };
+ nsSVGLength2 mLengthAttributes[6];
+ static LengthInfo sLengthInfo[6];
};
} // namespace dom
diff --git a/dom/tests/browser/browser.ini b/dom/tests/browser/browser.ini
index 35ebd56c6..4d3a60a2c 100644..100755
--- a/dom/tests/browser/browser.ini
+++ b/dom/tests/browser/browser.ini
@@ -8,6 +8,7 @@ support-files =
worker_bug1004814.js
geo_leak_test.html
dummy.html
+ file_workerPerformance.js
test_largeAllocation.html
test_largeAllocation.html^headers^
!/dom/tests/mochitest/geolocation/network_geolocation.sjs
@@ -44,3 +45,4 @@ support-files =
support-files =
test_new_window_from_content_child.html
[browser_xhr_sandbox.js]
+[browser_performanceAPI.js]
diff --git a/dom/tests/browser/browser_performanceAPI.js b/dom/tests/browser/browser_performanceAPI.js
new file mode 100755
index 000000000..2c28fe3d1
--- /dev/null
+++ b/dom/tests/browser/browser_performanceAPI.js
@@ -0,0 +1,139 @@
+/**
+ * Bug 1369303 - A test for making sure that performance APIs have been correctly
+ * spoofed or disabled.
+ */
+
+const TEST_PATH = "http://example.net/browser/" +
+ "dom/tests/browser/";
+
+const PERFORMANCE_TIMINGS = [
+ "navigationStart",
+ "unloadEventStart",
+ "unloadEventEnd",
+ "redirectStart",
+ "redirectEnd",
+ "fetchStart",
+ "domainLookupStart",
+ "domainLookupEnd",
+ "connectStart",
+ "connectEnd",
+ "requestStart",
+ "responseStart",
+ "responseEnd",
+ "domLoading",
+ "domInteractive",
+ "domContentLoadedEventStart",
+ "domContentLoadedEventEnd",
+ "domComplete",
+ "loadEventStart",
+ "loadEventEnd",
+];
+
+let isRounded = (x, expectedPrecision) => {
+ let rounded = (Math.floor(x / expectedPrecision) * expectedPrecision);
+ // First we do the perfectly normal check that should work just fine
+ if (rounded === x || x === 0)
+ return true;
+
+ // When we're diving by non-whole numbers, we may not get perfect
+ // multiplication/division because of floating points
+ if (Math.abs(rounded - x + expectedPrecision) < .0000001) {
+ return true;
+ } else if (Math.abs(rounded - x) < .0000001) {
+ return true;
+ }
+
+ // Then we handle the case where you're sub-millisecond and the timer is not
+ // We check that the timer is not sub-millisecond by assuming it is not if it
+ // returns an even number of milliseconds
+ if (expectedPrecision < 1 && Math.round(x) == x) {
+ if (Math.round(rounded) == x) {
+ return true;
+ }
+ }
+
+ ok(false, "Looming Test Failure, Additional Debugging Info: Expected Precision: " + expectedPrecision + " Measured Value: " + x +
+ " Rounded Vaue: " + rounded + " Fuzzy1: " + Math.abs(rounded - x + expectedPrecision) +
+ " Fuzzy 2: " + Math.abs(rounded - x));
+
+ return false;
+};
+
+// ================================================================================================
+// ================================================================================================
+add_task(function* () {
+ let tab = yield BrowserTestUtils.openNewForegroundTab(
+ gBrowser, TEST_PATH + "dummy.html");
+
+ yield ContentTask.spawn(tab.linkedBrowser, {
+ list: PERFORMANCE_TIMINGS,
+ precision: 2,
+ isRoundedFunc: isRounded.toString()
+ }, (data) => {
+ let timerlist = data.list;
+ let expectedPrecision = data.precision;
+ // eslint beleives that isrounded is available in this scope, but if you
+ // remove the assignment, you will see it is not
+ // eslint-disable-next-line
+ let isRounded = eval(data.isRoundedFunc);
+
+ // Check that whether the performance timing API is correctly spoofed.
+ for (let time of timerlist) {
+ ok(isRounded(content.performance.timing[time], expectedPrecision), `For reduceTimerPrecision(` + expectedPrecision + `), the timing(${time}) is not correctly rounded: ` + content.performance.timing[time]);
+ }
+
+ // Try to add some entries.
+ content.performance.mark("Test");
+ content.performance.mark("Test-End");
+ content.performance.measure("Test-Measure", "Test", "Test-End");
+
+ // Check the entries for performance.getEntries/getEntriesByType/getEntriesByName.
+ is(content.performance.getEntries().length, 3, "For reduceTimerPrecision, there should be 3 entries for performance.getEntries()");
+ for (var i = 0; i < 3; i++) {
+ let startTime = content.performance.getEntries()[i].startTime;
+ let duration = content.performance.getEntries()[i].duration;
+ ok(isRounded(startTime, expectedPrecision), "For reduceTimerPrecision(" + expectedPrecision + "), performance.getEntries(" + i + ").startTime is not rounded: " + startTime);
+ ok(isRounded(duration, expectedPrecision), "For reduceTimerPrecision(" + expectedPrecision + "), performance.getEntries(" + i + ").duration is not rounded: " + duration);
+ }
+ is(content.performance.getEntriesByType("mark").length, 2, "For reduceTimerPrecision, there should be 2 entries for performance.getEntriesByType()");
+ is(content.performance.getEntriesByName("Test", "mark").length, 1, "For reduceTimerPrecision, there should be 1 entry for performance.getEntriesByName()");
+ content.performance.clearMarks();
+ content.performance.clearMeasures();
+ content.performance.clearResourceTimings();
+ });
+ gBrowser.removeTab(tab);
+});
+
+// ================================================================================================
+// ================================================================================================
+add_task(function*() {
+ let tab = yield BrowserTestUtils.openNewForegroundTab(
+ gBrowser, TEST_PATH + "dummy.html");
+
+ yield ContentTask.spawn(tab.linkedBrowser, {
+ list: PERFORMANCE_TIMINGS,
+ precision: 2,
+ isRoundedFunc: isRounded.toString()
+ }, (data) => {
+ let expectedPrecision = data.precision;
+ let workerCall = data.workerCall;
+ return new Promise(resolve => {
+ let worker = new content.Worker("file_workerPerformance.js");
+ worker.onmessage = function(e) {
+ if (e.data.type == "status") {
+ ok(e.data.status, e.data.msg);
+ } else if (e.data.type == "finish") {
+ worker.terminate();
+ resolve();
+ } else {
+ ok(false, "Unknown message type");
+ worker.terminate();
+ resolve();
+ }
+ };
+ worker.postMessage({precision: expectedPrecision});
+ });
+ });
+
+ gBrowser.removeTab(tab);
+});
diff --git a/dom/tests/browser/file_workerPerformance.js b/dom/tests/browser/file_workerPerformance.js
new file mode 100755
index 000000000..c77ba4377
--- /dev/null
+++ b/dom/tests/browser/file_workerPerformance.js
@@ -0,0 +1,65 @@
+function ok(a, msg) {
+ postMessage({type: "status", status: !!a, msg});
+}
+
+function is(a, b, msg) {
+ ok(a === b, msg);
+}
+
+function finish() {
+ postMessage({type: "finish"});
+}
+
+let isRounded = (x, expectedPrecision) => {
+ let rounded = (Math.floor(x / expectedPrecision) * expectedPrecision);
+ // First we do the perfectly normal check that should work just fine
+ if (rounded === x || x === 0)
+ return true;
+
+ // When we're diving by non-whole numbers, we may not get perfect
+ // multiplication/division because of floating points
+ if (Math.abs(rounded - x + expectedPrecision) < .0000001) {
+ return true;
+ } else if (Math.abs(rounded - x) < .0000001) {
+ return true;
+ }
+
+ // Then we handle the case where you're sub-millisecond and the timer is not
+ // We check that the timer is not sub-millisecond by assuming it is not if it
+ // returns an even number of milliseconds
+ if (expectedPrecision < 1 && Math.round(x) == x) {
+ if (Math.round(rounded) == x) {
+ return true;
+ }
+ }
+
+ ok(false, "Looming Test Failure, Additional Debugging Info: Expected Precision: " + expectedPrecision + " Measured Value: " + x +
+ " Rounded Vaue: " + rounded + " Fuzzy1: " + Math.abs(rounded - x + expectedPrecision) +
+ " Fuzzy 2: " + Math.abs(rounded - x));
+
+ return false;
+};
+
+function runRTPTests(expectedPrecision) {
+ // Try to add some entries.
+ performance.mark("Test");
+ performance.mark("Test-End");
+ performance.measure("Test-Measure", "Test", "Test-End");
+
+ // Check the entries in performance.getEntries/getEntriesByType/getEntriesByName.
+ is(performance.getEntries().length, 3, "In a worker, for reduceTimerPrecision: Incorrect number of entries for performance.getEntries() for workers: " + performance.getEntries().length);
+ for (var i = 0; i < 3; i++) {
+ let startTime = performance.getEntries()[i].startTime;
+ let duration = performance.getEntries()[i].duration;
+ ok(isRounded(startTime, expectedPrecision), "In a worker, for reduceTimerPrecision(" + expectedPrecision + "), performance.getEntries(" + i.toString() + ").startTime is not rounded: " + startTime.toString());
+ ok(isRounded(duration, expectedPrecision), "In a worker, for reduceTimerPrecision(" + expectedPrecision + "), performance.getEntries(" + i.toString() + ").duration is not rounded: " + duration.toString());
+ }
+ is(performance.getEntriesByType("mark").length, 2, "In a worker, for reduceTimerPrecision: Incorrect number of entries for performance.getEntriesByType() for workers: " + performance.getEntriesByType("resource").length);
+ is(performance.getEntriesByName("Test", "mark").length, 1, "In a worker, for reduceTimerPrecision: Incorrect number of entries for performance.getEntriesByName() for workers: " + performance.getEntriesByName("Test", "mark").length);
+
+ finish();
+}
+
+self.onmessage = function(e) {
+ runRTPTests(e.data.precision);
+};
diff --git a/dom/tests/mochitest/general/mochitest.ini b/dom/tests/mochitest/general/mochitest.ini
index d59527801..d00ea1d4b 100644..100755
--- a/dom/tests/mochitest/general/mochitest.ini
+++ b/dom/tests/mochitest/general/mochitest.ini
@@ -43,6 +43,8 @@ support-files =
frameStoragePrevented.html
frameStorageChrome.html
frameStorageNullprincipal.sjs
+ worker_child.js
+ worker_grandchild.js
workerStorageAllowed.js
workerStoragePrevented.js
storagePermissionsUtils.js
@@ -108,6 +110,7 @@ support-files = test_offsets.js
[test_picture_mutations.html]
[test_pointerPreserves3D.html]
[test_pointerPreserves3DClip.html]
+[test_reduce_time_precision.html]
[test_resource_timing.html]
[test_resource_timing_cross_origin.html]
[test_resource_timing_frameset.html]
diff --git a/dom/tests/mochitest/general/test_domWindowUtils_scrollXY.html b/dom/tests/mochitest/general/test_domWindowUtils_scrollXY.html
index c6ee89ee3..cf27e5d87 100644
--- a/dom/tests/mochitest/general/test_domWindowUtils_scrollXY.html
+++ b/dom/tests/mochitest/general/test_domWindowUtils_scrollXY.html
@@ -31,13 +31,13 @@
function checkGetScrollXYState(flush, vals, testName) {
let scrollX = {}, scrollY = {};
domWindowUtils.getScrollXY(flush, scrollX, scrollY);
- is(scrollX.value, vals[0], "getScrollXY x for test: " + testName);
- is(scrollY.value, vals[1], "getScrollXY y for test: " + testName);
+ is(Math.round(scrollX.value), vals[0], "getScrollXY x for test: " + testName);
+ is(Math.round(scrollY.value), vals[1], "getScrollXY y for test: " + testName);
}
function checkWindowScrollState(vals, testName) {
- is(cwindow.scrollX, vals[0], "scrollX for test: " + testName);
- is(cwindow.scrollY, vals[1], "scrollY for test: " + testName);
+ is(Math.round(cwindow.scrollX), vals[0], "scrollX for test: " + testName);
+ is(Math.round(cwindow.scrollY), vals[1], "scrollY for test: " + testName);
}
// Check initial state (0, 0)
@@ -67,8 +67,8 @@
let scrollX = {}, scrollY = {};
domWindowUtils.getScrollXY(false, scrollX, scrollY);
- is(scrollX.value, 0, "scrollX is zero for display:none iframe");
- is(scrollY.value, 0, "scrollY is zero for display:none iframe");
+ is(Math.round(scrollX.value), 0, "scrollX is zero for display:none iframe");
+ is(Math.round(scrollY.value), 0, "scrollY is zero for display:none iframe");
}
SimpleTest.waitForExplicitFinish();
diff --git a/dom/tests/mochitest/general/test_reduce_time_precision.html b/dom/tests/mochitest/general/test_reduce_time_precision.html
new file mode 100755
index 000000000..6f149f28d
--- /dev/null
+++ b/dom/tests/mochitest/general/test_reduce_time_precision.html
@@ -0,0 +1,143 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Tor bug
+https://trac.torproject.org/projects/tor/ticket/1517
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Tor Bug 1517 and Mozilla Bug 1424341</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://trac.torproject.org/projects/tor/ticket/1517">Tor Bug 1517</a>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1424341">Mozilla Bug 1424341</a>
+
+<!-- Canvas for testing 'currentTime' -->
+<canvas id="test-canvas" width="100" height="100"></canvas>
+
+<!-- The main testing script -->
+<script type="application/javascript">
+ SimpleTest.requestFlakyTimeout("testing JS time-based fingerprinting");
+
+ // Prepare for test of AudioContext.currentTime
+ let audioContext = new AudioContext();
+ // Prepare for test of CanvasStream.currentTime
+ let canvas = document.getElementById("test-canvas");
+ let context = canvas.getContext("2d");
+ context.fillText("test", 20, 20);
+ let canvasStream = canvas.captureStream(25);
+
+ // Known ways to generate time stamps, in milliseconds
+ const timeStampCodes = [
+ "performance.now()",
+ "new Date().getTime()",
+ "new Event(\"\").timeStamp",
+ "new File([], \"\").lastModified",
+ "new File([], \"\").lastModifiedDate.getTime()",
+ ];
+ // These are measured in seconds, so we need to scale them up
+ var timeStampCodesDOM = timeStampCodes.concat([
+ "audioContext.currentTime * 1000",
+ "canvasStream.currentTime * 1000",
+ ]);
+
+ let isRounded = (x) => {
+ expectedPrecision = 2;
+ let rounded = (Math.floor(x / expectedPrecision) * expectedPrecision);
+ // First we do the perfectly normal check that should work just fine
+ if (rounded === x || x === 0)
+ return true;
+
+ // When we're diving by non-whole numbers, we may not get perfect
+ // multiplication/division because of floating points.
+ // When dealing with ms since epoch, a double's precision is on the order
+ // of 1/5 of a microsecond, so we use a value a little higher than that as
+ // our epsilon.
+ // To be clear, this error is introduced in our re-calculation of 'rounded'
+ // above in JavaScript.
+ if (Math.abs(rounded - x + expectedPrecision) < .0005) {
+ return true;
+ } else if (Math.abs(rounded - x) < .0005) {
+ return true;
+ }
+
+ // Then we handle the case where you're sub-millisecond and the timer is not
+ // We check that the timer is not sub-millisecond by assuming it is not if it
+ // returns an even number of milliseconds
+ if (expectedPrecision < 1 && Math.round(x) == x) {
+ if (Math.round(rounded) == x) {
+ return true;
+ }
+ }
+
+ ok(false, "Looming Test Failure, Additional Debugging Info: Expected Precision: " + expectedPrecision + " Measured Value: " + x +
+ " Rounded Vaue: " + rounded + " Fuzzy1: " + Math.abs(rounded - x + expectedPrecision) +
+ " Fuzzy 2: " + Math.abs(rounded - x));
+
+ return false;
+ };
+
+ // ================================================================================================
+ // ================================================================================================
+
+ function* checkWorker(worker) {
+ // The child worker will send the results back.
+ let checkWorkerTimeStamps = () => new Promise(function(resolve) {
+ let onMessage = function(event) {
+ worker.removeEventListener("message", onMessage);
+
+ let timeStamps = event.data;
+ for (let i = 0; i < timeStampCodes.length; i++) {
+ let timeStamp = timeStamps[i];
+ ok(isRounded(timeStamp),
+ "'" + timeStampCodes[i] +
+ "' should be rounded to nearest 2 ms in workers; saw " +
+ timeStamp);
+ }
+ resolve();
+ };
+ worker.addEventListener("message", onMessage);
+ });
+
+ // Send the codes to its child worker.
+ worker.postMessage(timeStampCodes);
+
+ // First, check the child's results.
+ yield checkWorkerTimeStamps();
+ // Then, check the grandchild's results.
+ yield checkWorkerTimeStamps();
+
+ worker.terminate();
+ }
+
+ add_task(function*() {
+ let worker = new Worker("worker_child.js");
+ // Allow ~550 ms to elapse, so we can get non-zero
+ // time values for all elements.
+ yield new Promise(resolve => window.setTimeout(resolve, 550));
+ yield checkWorker(worker);
+ });
+
+ // ================================================================================================
+ // ================================================================================================
+
+
+ add_task(function*() {
+ // Loop through each timeStampCode, evaluate it,
+ // and check if it is rounded
+ for (let timeStampCode of timeStampCodesDOM) {
+ let timeStamp = eval(timeStampCode);
+ ok(isRounded(timeStamp),
+ "'" + timeStampCode + "' should be rounded to nearest 2ms" +
+ " saw " + timeStamp);
+ }
+ });
+
+</script>
+
+
+</body>
+</html>
diff --git a/dom/tests/mochitest/general/worker_child.js b/dom/tests/mochitest/general/worker_child.js
new file mode 100755
index 000000000..fa340fc65
--- /dev/null
+++ b/dom/tests/mochitest/general/worker_child.js
@@ -0,0 +1,28 @@
+let timeStampCodes;
+let worker = new Worker("worker_grandchild.js");
+
+function listenToParent(event) {
+ self.removeEventListener("message", listenToParent);
+ timeStampCodes = event.data;
+
+ let timeStamps = [];
+ for (let timeStampCode of timeStampCodes) {
+ timeStamps.push(eval(timeStampCode));
+ }
+ // Send the timeStamps to the parent.
+ postMessage(timeStamps);
+
+ // Tell the grandchild to start.
+ worker.postMessage(timeStampCodes);
+}
+
+// The worker grandchild will send results back.
+function listenToChild(event) {
+ worker.removeEventListener("message", listenToChild);
+ // Pass the results to the parent.
+ postMessage(event.data);
+ worker.terminate();
+}
+
+worker.addEventListener("message", listenToChild);
+self.addEventListener("message", listenToParent);
diff --git a/dom/tests/mochitest/general/worker_grandchild.js b/dom/tests/mochitest/general/worker_grandchild.js
new file mode 100755
index 000000000..cd21508b2
--- /dev/null
+++ b/dom/tests/mochitest/general/worker_grandchild.js
@@ -0,0 +1,10 @@
+self.addEventListener("message", function(event) {
+ let timeStampCodes = event.data;
+
+ let timeStamps = [];
+ for (let timeStampCode of timeStampCodes) {
+ timeStamps.push(eval(timeStampCode));
+ }
+ // Send the timeStamps to the parent.
+ postMessage(timeStamps);
+});
diff --git a/dom/url/URL.h b/dom/url/URL.h
index 16b4678ba..45e4dd289 100644
--- a/dom/url/URL.h
+++ b/dom/url/URL.h
@@ -155,6 +155,12 @@ public:
GetHref(aRetval, aRv);
}
+ void
+ ToJSON(nsAString& aResult, ErrorResult& aRv) const
+ {
+ GetHref(aResult, aRv);
+ }
+
// URLSearchParamsObserver
void
URLSearchParamsUpdated(URLSearchParams* aSearchParams) override;
diff --git a/dom/url/tests/test_url.html b/dom/url/tests/test_url.html
index 3f3f727d6..d07a752bb 100644
--- a/dom/url/tests/test_url.html
+++ b/dom/url/tests/test_url.html
@@ -438,5 +438,11 @@
url = new URL("data:text/html,<a href=\"http://example.org/?q\">Link</a>");
is(url.href, "data:text/html,<a%20href=\"http://example.org/?q\">Link</a>");
</script>
+
+ <script>
+ var u = new URL('http://www.example.org');
+ ok(u.toJSON(), 'http://www.example.org', "URL.toJSON()");
+ is(JSON.stringify(u), "\"http://www.example.org/\"", "JSON.stringify(u) works");
+ </script>
</body>
</html>
diff --git a/dom/webidl/CSPDictionaries.webidl b/dom/webidl/CSPDictionaries.webidl
index 54008f13a..f8de1c9ad 100644
--- a/dom/webidl/CSPDictionaries.webidl
+++ b/dom/webidl/CSPDictionaries.webidl
@@ -30,6 +30,7 @@ dictionary CSP {
sequence<DOMString> block-all-mixed-content;
sequence<DOMString> require-sri-for;
sequence<DOMString> sandbox;
+ sequence<DOMString> worker-src;
};
dictionary CSPPolicies {
diff --git a/dom/webidl/Document.webidl b/dom/webidl/Document.webidl
index c895fad39..f05656e84 100644
--- a/dom/webidl/Document.webidl
+++ b/dom/webidl/Document.webidl
@@ -275,10 +275,11 @@ partial interface Document {
object registerElement(DOMString name, optional ElementRegistrationOptions options);
};
-// http://dvcs.w3.org/hg/webperf/raw-file/tip/specs/PageVisibility/Overview.html#sec-document-interface
+// https://w3c.github.io/page-visibility/#extensions-to-the-document-interface
partial interface Document {
readonly attribute boolean hidden;
readonly attribute VisibilityState visibilityState;
+ attribute EventHandler onvisibilitychange;
};
// http://dev.w3.org/csswg/cssom/#extensions-to-the-document-interface
diff --git a/dom/webidl/HTMLButtonElement.webidl b/dom/webidl/HTMLButtonElement.webidl
index c50e09ae0..579efa39c 100644
--- a/dom/webidl/HTMLButtonElement.webidl
+++ b/dom/webidl/HTMLButtonElement.webidl
@@ -44,6 +44,5 @@ interface HTMLButtonElement : HTMLElement {
boolean reportValidity();
void setCustomValidity(DOMString error);
-// Not yet implemented:
-// readonly attribute NodeList labels;
+ readonly attribute NodeList labels;
};
diff --git a/dom/webidl/HTMLInputElement.webidl b/dom/webidl/HTMLInputElement.webidl
index d3d537f84..050d19510 100644
--- a/dom/webidl/HTMLInputElement.webidl
+++ b/dom/webidl/HTMLInputElement.webidl
@@ -111,7 +111,7 @@ interface HTMLInputElement : HTMLElement {
boolean reportValidity();
void setCustomValidity(DOMString error);
- // Bug 850365 readonly attribute NodeList labels;
+ readonly attribute NodeList? labels;
void select();
diff --git a/dom/webidl/HTMLMediaElement.webidl b/dom/webidl/HTMLMediaElement.webidl
index 456579ec1..313686dac 100644
--- a/dom/webidl/HTMLMediaElement.webidl
+++ b/dom/webidl/HTMLMediaElement.webidl
@@ -153,6 +153,7 @@ partial interface HTMLMediaElement {
attribute EventHandler onmozinterruptend;
};
+#ifdef MOZ_EME
// Encrypted Media Extensions
partial interface HTMLMediaElement {
[Pref="media.eme.apiVisible"]
@@ -168,6 +169,7 @@ partial interface HTMLMediaElement {
[Pref="media.eme.apiVisible"]
attribute EventHandler onwaitingforkey;
};
+#endif
// This is just for testing
partial interface HTMLMediaElement {
diff --git a/dom/webidl/HTMLMeterElement.webidl b/dom/webidl/HTMLMeterElement.webidl
index 1f80764e9..104e00353 100644
--- a/dom/webidl/HTMLMeterElement.webidl
+++ b/dom/webidl/HTMLMeterElement.webidl
@@ -26,8 +26,5 @@ interface HTMLMeterElement : HTMLElement {
[SetterThrows]
attribute double optimum;
- /**
- * The labels attribute will be done with bug 556743.
- */
- //readonly attribute NodeList labels;
+ readonly attribute NodeList labels;
};
diff --git a/dom/webidl/HTMLOutputElement.webidl b/dom/webidl/HTMLOutputElement.webidl
index 05dcf1800..d0e4ecbe6 100644
--- a/dom/webidl/HTMLOutputElement.webidl
+++ b/dom/webidl/HTMLOutputElement.webidl
@@ -33,6 +33,5 @@ interface HTMLOutputElement : HTMLElement {
boolean reportValidity();
void setCustomValidity(DOMString error);
-// Not yet implemented (bug 556743).
-// readonly attribute NodeList labels;
+ readonly attribute NodeList labels;
};
diff --git a/dom/webidl/HTMLProgressElement.webidl b/dom/webidl/HTMLProgressElement.webidl
index 3d1000d22..028728e22 100644
--- a/dom/webidl/HTMLProgressElement.webidl
+++ b/dom/webidl/HTMLProgressElement.webidl
@@ -17,9 +17,5 @@ interface HTMLProgressElement : HTMLElement {
[SetterThrows]
attribute double max;
readonly attribute double position;
-
- /**
- * The labels attribute will be done with bug 567740.
- */
- //readonly attribute NodeList labels;
+ readonly attribute NodeList labels;
};
diff --git a/dom/webidl/HTMLSelectElement.webidl b/dom/webidl/HTMLSelectElement.webidl
index 74fc7b2cf..b18ca3634 100644
--- a/dom/webidl/HTMLSelectElement.webidl
+++ b/dom/webidl/HTMLSelectElement.webidl
@@ -53,7 +53,7 @@ interface HTMLSelectElement : HTMLElement {
boolean reportValidity();
void setCustomValidity(DOMString error);
-// NYI: readonly attribute NodeList labels;
+ readonly attribute NodeList labels;
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=20720
void remove();
diff --git a/dom/webidl/HTMLTextAreaElement.webidl b/dom/webidl/HTMLTextAreaElement.webidl
index b1005ed42..4df687a0b 100644
--- a/dom/webidl/HTMLTextAreaElement.webidl
+++ b/dom/webidl/HTMLTextAreaElement.webidl
@@ -57,7 +57,7 @@ interface HTMLTextAreaElement : HTMLElement {
boolean reportValidity();
void setCustomValidity(DOMString error);
- // readonly attribute NodeList labels;
+ readonly attribute NodeList labels;
void select();
[Throws]
diff --git a/dom/webidl/Navigator.webidl b/dom/webidl/Navigator.webidl
index 56461e429..5452f3247 100644
--- a/dom/webidl/Navigator.webidl
+++ b/dom/webidl/Navigator.webidl
@@ -348,12 +348,14 @@ partial interface Navigator {
readonly attribute LegacyMozTCPSocket mozTCPSocket;
};
+#ifdef MOZ_EME
partial interface Navigator {
[Pref="media.eme.apiVisible", NewObject]
Promise<MediaKeySystemAccess>
requestMediaKeySystemAccess(DOMString keySystem,
sequence<MediaKeySystemConfiguration> supportedConfigurations);
};
+#endif
#ifdef NIGHTLY_BUILD
partial interface Navigator {
diff --git a/dom/webidl/PerformanceTiming.webidl b/dom/webidl/PerformanceTiming.webidl
index f75a46b7c..e14201440 100644
--- a/dom/webidl/PerformanceTiming.webidl
+++ b/dom/webidl/PerformanceTiming.webidl
@@ -21,8 +21,7 @@ interface PerformanceTiming {
readonly attribute unsigned long long domainLookupEnd;
readonly attribute unsigned long long connectStart;
readonly attribute unsigned long long connectEnd;
- // secureConnectionStart will be implemneted in bug 772589
- // readonly attribute unsigned long long secureConnectionStart;
+ readonly attribute unsigned long long secureConnectionStart;
readonly attribute unsigned long long requestStart;
readonly attribute unsigned long long responseStart;
readonly attribute unsigned long long responseEnd;
diff --git a/dom/webidl/SVGRadialGradientElement.webidl b/dom/webidl/SVGRadialGradientElement.webidl
index d4a3724f6..8d7ce9016 100644
--- a/dom/webidl/SVGRadialGradientElement.webidl
+++ b/dom/webidl/SVGRadialGradientElement.webidl
@@ -21,5 +21,7 @@ interface SVGRadialGradientElement : SVGGradientElement {
readonly attribute SVGAnimatedLength fx;
[Constant]
readonly attribute SVGAnimatedLength fy;
- // readonly attribute SVGAnimatedLength fr;
+ // XXX: Bug 1242048
+ // [SameObject]
+ readonly attribute SVGAnimatedLength fr;
};
diff --git a/dom/webidl/URL.webidl b/dom/webidl/URL.webidl
index 0baa9913c..4d491e1b3 100644
--- a/dom/webidl/URL.webidl
+++ b/dom/webidl/URL.webidl
@@ -44,9 +44,12 @@ interface URL {
attribute USVString pathname;
[Throws]
attribute USVString search;
- readonly attribute URLSearchParams searchParams;
+ [SameObject] readonly attribute URLSearchParams searchParams;
[Throws]
attribute USVString hash;
+
+ [Throws]
+ USVString toJSON();
};
partial interface URL {
diff --git a/dom/webidl/Window.webidl b/dom/webidl/Window.webidl
index 055a274cc..36b1f0313 100644
--- a/dom/webidl/Window.webidl
+++ b/dom/webidl/Window.webidl
@@ -182,14 +182,10 @@ partial interface Window {
[ChromeOnly] void mozScrollSnap();
// The four properties below are double per spec at the moment, but whether
// that will continue is unclear.
- //[Replaceable, Throws] readonly attribute double scrollX;
- //[Replaceable, Throws] readonly attribute double pageXOffset;
- //[Replaceable, Throws] readonly attribute double scrollY;
- //[Replaceable, Throws] readonly attribute double pageYOffset;
- [Replaceable, Throws] readonly attribute long scrollX;
- [Replaceable, Throws] readonly attribute long pageXOffset;
- [Replaceable, Throws] readonly attribute long scrollY;
- [Replaceable, Throws] readonly attribute long pageYOffset;
+ [Replaceable, Throws] readonly attribute double scrollX;
+ [Throws] readonly attribute double pageXOffset;
+ [Replaceable, Throws] readonly attribute double scrollY;
+ [Throws] readonly attribute double pageYOffset;
// client
// These are writable because we allow chrome to write them. And they need
diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build
index f24c366e8..8682aee97 100644
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -9,6 +9,7 @@ GENERATED_WEBIDL_FILES = [
]
PREPROCESSED_WEBIDL_FILES = [
+ 'HTMLMediaElement.webidl',
'Navigator.webidl',
'Node.webidl',
'Promise.webidl',
@@ -210,7 +211,6 @@ WEBIDL_FILES = [
'HTMLLIElement.webidl',
'HTMLLinkElement.webidl',
'HTMLMapElement.webidl',
- 'HTMLMediaElement.webidl',
'HTMLMenuElement.webidl',
'HTMLMenuItemElement.webidl',
'HTMLMetaElement.webidl',
@@ -773,7 +773,7 @@ if CONFIG['MOZ_BUILD_APP'] in ['xulrunner'] or CONFIG['MOZ_PHOENIX'] or CONFIG['
'BrowserFeedWriter.webidl',
]
-if CONFIG['MOZ_BUILD_APP'] in ['mobile/android', 'xulrunner'] or CONFIG['MOZ_PHOENIX']:
+if CONFIG['MOZ_PHOENIX'] or CONFIG['MOZ_FENNEC'] or CONFIG['MOZ_XULRUNNER']:
WEBIDL_FILES += [
'External.webidl',
]
diff --git a/dom/workers/WorkerScope.cpp b/dom/workers/WorkerScope.cpp
index d9a987b62..54252e53b 100644
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -968,11 +968,4 @@ IsDebuggerSandbox(JSObject* object)
SimpleGlobalObject::GlobalType::WorkerDebuggerSandbox;
}
-bool
-GetterOnlyJSNative(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
-{
- JS_ReportErrorNumberASCII(aCx, js::GetErrorMessage, nullptr, JSMSG_GETTER_ONLY);
- return false;
-}
-
END_WORKERS_NAMESPACE
diff --git a/dom/workers/Workers.h b/dom/workers/Workers.h
index ad083d3b8..cd15a4d7c 100644
--- a/dom/workers/Workers.h
+++ b/dom/workers/Workers.h
@@ -362,14 +362,6 @@ IsDebuggerGlobal(JSObject* global);
bool
IsDebuggerSandbox(JSObject* object);
-// Throws the JSMSG_GETTER_ONLY exception. This shouldn't be used going
-// forward -- getter-only properties should just use JS_PSG for the setter
-// (implying no setter at all), which will not throw when set in non-strict
-// code but will in strict code. Old code should use this only for temporary
-// compatibility reasons.
-extern bool
-GetterOnlyJSNative(JSContext* aCx, unsigned aArgc, JS::Value* aVp);
-
END_WORKERS_NAMESPACE
#endif // mozilla_dom_workers_workers_h__
diff --git a/dom/xul/XULDocument.cpp b/dom/xul/XULDocument.cpp
index ae3cdb7eb..1dcb55aee 100644
--- a/dom/xul/XULDocument.cpp
+++ b/dom/xul/XULDocument.cpp
@@ -1919,26 +1919,26 @@ XULDocument::StartLayout(void)
/* static */
bool
-XULDocument::MatchAttribute(nsIContent* aContent,
+XULDocument::MatchAttribute(Element* aElement,
int32_t aNamespaceID,
nsIAtom* aAttrName,
void* aData)
{
- NS_PRECONDITION(aContent, "Must have content node to work with!");
+ NS_PRECONDITION(aElement, "Must have content node to work with!");
nsString* attrValue = static_cast<nsString*>(aData);
if (aNamespaceID != kNameSpaceID_Unknown &&
aNamespaceID != kNameSpaceID_Wildcard) {
return attrValue->EqualsLiteral("*") ?
- aContent->HasAttr(aNamespaceID, aAttrName) :
- aContent->AttrValueIs(aNamespaceID, aAttrName, *attrValue,
+ aElement->HasAttr(aNamespaceID, aAttrName) :
+ aElement->AttrValueIs(aNamespaceID, aAttrName, *attrValue,
eCaseMatters);
}
// Qualified name match. This takes more work.
- uint32_t count = aContent->GetAttrCount();
+ uint32_t count = aElement->GetAttrCount();
for (uint32_t i = 0; i < count; ++i) {
- const nsAttrName* name = aContent->GetAttrNameAt(i);
+ const nsAttrName* name = aElement->GetAttrNameAt(i);
bool nameMatch;
if (name->IsAtom()) {
nameMatch = name->Atom() == aAttrName;
@@ -1950,7 +1950,7 @@ XULDocument::MatchAttribute(nsIContent* aContent,
if (nameMatch) {
return attrValue->EqualsLiteral("*") ||
- aContent->AttrValueIs(name->NamespaceID(), name->LocalName(),
+ aElement->AttrValueIs(name->NamespaceID(), name->LocalName(),
*attrValue, eCaseMatters);
}
}
diff --git a/dom/xul/XULDocument.h b/dom/xul/XULDocument.h
index a2f82bb89..06abb797f 100644
--- a/dom/xul/XULDocument.h
+++ b/dom/xul/XULDocument.h
@@ -180,7 +180,7 @@ public:
NS_IMETHOD OnScriptCompileComplete(JSScript* aScript, nsresult aStatus) override;
static bool
- MatchAttribute(nsIContent* aContent,
+ MatchAttribute(Element* aContent,
int32_t aNameSpaceID,
nsIAtom* aAttrName,
void* aData);