diff --git a/browser/base/content/test/general/title_test.svg b/browser/base/content/test/general/title_test.svg
new file mode 100644
index 0000000000..7638fd5ccb
--- /dev/null
+++ b/browser/base/content/test/general/title_test.svg
@@ -0,0 +1,59 @@
+
diff --git a/build/mach_bootstrap.py b/build/mach_bootstrap.py
index 211d98abe2..820fe27f23 100644
--- a/build/mach_bootstrap.py
+++ b/build/mach_bootstrap.py
@@ -50,9 +50,9 @@ SEARCH_PATHS = [
'testing/firefox-ui/harness',
'testing/firefox-ui/tests',
'testing/luciddream',
+ 'testing/marionette/harness',
+ 'testing/marionette/harness/marionette/runner/mixins/browsermob-proxy-py',
'testing/marionette/client',
- 'testing/marionette/client/marionette/runner/mixins/browsermob-proxy-py',
- 'testing/marionette/driver',
'testing/mozbase/mozcrash',
'testing/mozbase/mozdebug',
'testing/mozbase/mozdevice',
diff --git a/build/pgo/server-locations.txt b/build/pgo/server-locations.txt
index bb359d9f70..a034c02ad6 100644
--- a/build/pgo/server-locations.txt
+++ b/build/pgo/server-locations.txt
@@ -258,3 +258,6 @@ https://sha256ee.example.com:443 privileged,cer
https://ssl3.example.com:443 privileged,ssl3
https://rc4.example.com:443 privileged,rc4
https://ssl3rc4.example.com:443 privileged,ssl3,rc4
+
+# Hosts for youtube rewrite tests
+https://mochitest.youtube.com:443
diff --git a/build/virtualenv_packages.txt b/build/virtualenv_packages.txt
index 122804e652..4179884c74 100644
--- a/build/virtualenv_packages.txt
+++ b/build/virtualenv_packages.txt
@@ -1,7 +1,7 @@
-marionette_driver.pth:testing/marionette/driver
-browsermobproxy.pth:testing/marionette/client/marionette/runner/mixins/browsermob-proxy-py
+marionette_driver.pth:testing/marionette/client
+browsermobproxy.pth:testing/marionette/harness/marionette/runner/mixins/browsermob-proxy-py
wptserve.pth:testing/web-platform/tests/tools/wptserve
-marionette.pth:testing/marionette/client
+marionette.pth:testing/marionette/harness
blessings.pth:python/blessings
configobj.pth:python/configobj
jsmin.pth:python/jsmin
diff --git a/configure.in b/configure.in
index e5138eb512..4ae68a00bb 100644
--- a/configure.in
+++ b/configure.in
@@ -8839,6 +8839,16 @@ fi
MOZ_CONFIG_ICU()
+dnl ========================================================
+dnl mask as short hand property
+dnl ========================================================
+dnl Uncommenting the next line would enable mask-as-shorthand feature.
+dnl MOZ_ENABLE_MASK_AS_SHORTHAND=1
+if test "$MOZ_ENABLE_MASK_AS_SHORTHAND"; then
+ AC_DEFINE(MOZ_ENABLE_MASK_AS_SHORTHAND)
+fi
+AC_SUBST(MOZ_ENABLE_MASK_AS_SHORTHAND)
+
if test -z "$JS_SHARED_LIBRARY"; then
AC_DEFINE(MOZ_STATIC_JS)
fi
diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index dcf2ed229d..aae0044498 100644
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -5783,10 +5783,14 @@ nsDocShell::SetPosition(int32_t aX, int32_t aY)
NS_IMETHODIMP
nsDocShell::SetPositionDesktopPix(int32_t aX, int32_t aY)
{
- // Added to nsIBaseWindow in bug 1247335;
- // implement if a use-case is found.
- NS_ASSERTION(false, "implement me!");
- return NS_ERROR_NOT_IMPLEMENTED;
+ nsCOMPtr ownerWindow(do_QueryInterface(mTreeOwner));
+ if (ownerWindow) {
+ return ownerWindow->SetPositionDesktopPix(aX, aY);
+ }
+
+ double scale = 1.0;
+ GetDevicePixelsPerDesktopPixel(&scale);
+ return SetPosition(NSToIntRound(aX * scale), NSToIntRound(aY * scale));
}
NS_IMETHODIMP
diff --git a/dom/animation/AnimationEffectTiming.cpp b/dom/animation/AnimationEffectTiming.cpp
index 6fe676af43..07bb66a101 100644
--- a/dom/animation/AnimationEffectTiming.cpp
+++ b/dom/animation/AnimationEffectTiming.cpp
@@ -8,6 +8,7 @@
#include "mozilla/dom/AnimatableBinding.h"
#include "mozilla/dom/AnimationEffectTimingBinding.h"
+#include "mozilla/TimingParams.h"
namespace mozilla {
namespace dom {
@@ -39,26 +40,20 @@ AnimationEffectTiming::SetEndDelay(double aEndDelay)
}
void
-AnimationEffectTiming::SetDuration(const UnrestrictedDoubleOrString& aDuration)
+AnimationEffectTiming::SetDuration(const UnrestrictedDoubleOrString& aDuration,
+ ErrorResult& aRv)
{
- if (mTiming.mDuration.IsUnrestrictedDouble() &&
- aDuration.IsUnrestrictedDouble() &&
- mTiming.mDuration.GetAsUnrestrictedDouble() ==
- aDuration.GetAsUnrestrictedDouble()) {
+ Maybe newDuration =
+ TimingParams::ParseDuration(aDuration, aRv);
+ if (aRv.Failed()) {
return;
}
- if (mTiming.mDuration.IsString() && aDuration.IsString() &&
- mTiming.mDuration.GetAsString() == aDuration.GetAsString()) {
+ if (mTiming.mDuration == newDuration) {
return;
}
- if (aDuration.IsUnrestrictedDouble()) {
- mTiming.mDuration.SetAsUnrestrictedDouble() =
- aDuration.GetAsUnrestrictedDouble();
- } else {
- mTiming.mDuration.SetAsString() = aDuration.GetAsString();
- }
+ mTiming.mDuration = newDuration;
NotifyTimingUpdate();
}
diff --git a/dom/animation/AnimationEffectTiming.h b/dom/animation/AnimationEffectTiming.h
index 1f3afae6dc..b98b28bbdc 100644
--- a/dom/animation/AnimationEffectTiming.h
+++ b/dom/animation/AnimationEffectTiming.h
@@ -25,7 +25,8 @@ public:
void Unlink() override { mEffect = nullptr; }
void SetEndDelay(double aEndDelay);
- void SetDuration(const UnrestrictedDoubleOrString& aDuration);
+ void SetDuration(const UnrestrictedDoubleOrString& aDuration,
+ ErrorResult& aRv);
private:
void NotifyTimingUpdate();
diff --git a/dom/animation/AnimationEffectTimingReadOnly.cpp b/dom/animation/AnimationEffectTimingReadOnly.cpp
index 1d61c6dbfc..52c7179830 100644
--- a/dom/animation/AnimationEffectTimingReadOnly.cpp
+++ b/dom/animation/AnimationEffectTimingReadOnly.cpp
@@ -26,6 +26,17 @@ AnimationEffectTimingReadOnly::WrapObject(JSContext* aCx, JS::Handle
return AnimationEffectTimingReadOnlyBinding::Wrap(aCx, this, aGivenProto);
}
+void
+AnimationEffectTimingReadOnly::GetDuration(
+ OwningUnrestrictedDoubleOrString& aRetVal) const
+{
+ if (mTiming.mDuration) {
+ aRetVal.SetAsUnrestrictedDouble() = mTiming.mDuration->ToMilliseconds();
+ } else {
+ aRetVal.SetAsString().AssignLiteral("auto");
+ }
+}
+
void
AnimationEffectTimingReadOnly::GetEasing(nsString& aRetVal) const
{
diff --git a/dom/animation/AnimationEffectTimingReadOnly.h b/dom/animation/AnimationEffectTimingReadOnly.h
index 2715530493..6c570342b1 100644
--- a/dom/animation/AnimationEffectTimingReadOnly.h
+++ b/dom/animation/AnimationEffectTimingReadOnly.h
@@ -41,10 +41,7 @@ public:
FillMode Fill() const { return mTiming.mFill; }
double IterationStart() const { return mTiming.mIterationStart; }
double Iterations() const { return mTiming.mIterations; }
- void GetDuration(OwningUnrestrictedDoubleOrString& aRetVal) const
- {
- aRetVal = mTiming.mDuration;
- }
+ void GetDuration(OwningUnrestrictedDoubleOrString& aRetVal) const;
PlaybackDirection Direction() const { return mTiming.mDirection; }
void GetEasing(nsString& aRetVal) const;
diff --git a/dom/animation/KeyframeEffect.cpp b/dom/animation/KeyframeEffect.cpp
index bf73d13dcb..5c0c9a2f51 100644
--- a/dom/animation/KeyframeEffect.cpp
+++ b/dom/animation/KeyframeEffect.cpp
@@ -238,12 +238,12 @@ KeyframeEffectReadOnly::GetComputedTimingAt(
// Always return the same object to benefit from return-value optimization.
ComputedTiming result;
- if (aTiming.mDuration.IsUnrestrictedDouble()) {
- double durationMs = aTiming.mDuration.GetAsUnrestrictedDouble();
- if (!IsNaN(durationMs) && durationMs >= 0.0f) {
- result.mDuration = StickyTimeDuration::FromMilliseconds(durationMs);
- }
+ if (aTiming.mDuration) {
+ MOZ_ASSERT(aTiming.mDuration.ref() >= zeroDuration,
+ "Iteration duration should be positive");
+ result.mDuration = aTiming.mDuration.ref();
}
+
result.mIterations = IsNaN(aTiming.mIterations) || aTiming.mIterations < 0.0f ?
1.0f :
aTiming.mIterations;
diff --git a/dom/animation/KeyframeEffect.h b/dom/animation/KeyframeEffect.h
index f66460de3c..7f44bf1c18 100644
--- a/dom/animation/KeyframeEffect.h
+++ b/dom/animation/KeyframeEffect.h
@@ -204,9 +204,13 @@ public:
const UnrestrictedDoubleOrKeyframeEffectOptions& aOptions,
ErrorResult& aRv)
{
+ TimingParams timingParams =
+ TimingParams::FromOptionsUnion(aOptions, aTarget, aRv);
+ if (aRv.Failed()) {
+ return nullptr;
+ }
return ConstructKeyframeEffect(
- aGlobal, aTarget, aFrames,
- TimingParams::FromOptionsUnion(aOptions, aTarget), aRv);
+ aGlobal, aTarget, aFrames, timingParams, aRv);
}
void GetTarget(Nullable& aRv) const;
@@ -431,9 +435,13 @@ public:
const UnrestrictedDoubleOrKeyframeEffectOptions& aOptions,
ErrorResult& aRv)
{
+ TimingParams timingParams =
+ TimingParams::FromOptionsUnion(aOptions, aTarget, aRv);
+ if (aRv.Failed()) {
+ return nullptr;
+ }
return ConstructKeyframeEffect(
- aGlobal, aTarget, aFrames,
- TimingParams::FromOptionsUnion(aOptions, aTarget), aRv);
+ aGlobal, aTarget, aFrames, timingParams, aRv);
}
// More generalized version for Animatable.animate.
diff --git a/dom/animation/TimingParams.cpp b/dom/animation/TimingParams.cpp
index dbb1df9f9d..702d14a629 100644
--- a/dom/animation/TimingParams.cpp
+++ b/dom/animation/TimingParams.cpp
@@ -8,24 +8,6 @@
namespace mozilla {
-TimingParams::TimingParams(const dom::AnimationEffectTimingProperties& aRhs,
- const dom::Element* aTarget)
- : mDuration(aRhs.mDuration)
- , mDelay(TimeDuration::FromMilliseconds(aRhs.mDelay))
- , mEndDelay(TimeDuration::FromMilliseconds(aRhs.mEndDelay))
- , mIterations(aRhs.mIterations)
- , mIterationStart(aRhs.mIterationStart)
- , mDirection(aRhs.mDirection)
- , mFill(aRhs.mFill)
-{
- mFunction = AnimationUtils::ParseEasing(aTarget, aRhs.mEasing);
-}
-
-TimingParams::TimingParams(double aDuration)
-{
- mDuration.SetAsUnrestrictedDouble() = aDuration;
-}
-
template
static const dom::AnimationEffectTimingProperties&
GetTimingProperties(const OptionsType& aOptions);
@@ -52,10 +34,18 @@ template
static TimingParams
TimingParamsFromOptionsUnion(
const OptionsType& aOptions,
- const Nullable& aTarget)
+ const Nullable& aTarget,
+ ErrorResult& aRv)
{
+ TimingParams result;
if (aOptions.IsUnrestrictedDouble()) {
- return TimingParams(aOptions.GetAsUnrestrictedDouble());
+ double durationInMs = aOptions.GetAsUnrestrictedDouble();
+ if (durationInMs >= 0) {
+ result.mDuration.emplace(
+ StickyTimeDuration::FromMilliseconds(durationInMs));
+ } else {
+ aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
+ }
} else {
// If aTarget is a pseudo element, we pass its parent element because
// TimingParams only needs its owner doc to parse easing and both pseudo
@@ -72,41 +62,48 @@ TimingParamsFromOptionsUnion(
targetElement = target.GetAsCSSPseudoElement().ParentElement();
}
}
- return TimingParams(GetTimingProperties(aOptions), targetElement);
+ const dom::AnimationEffectTimingProperties& timing =
+ GetTimingProperties(aOptions);
+ Maybe duration =
+ TimingParams::ParseDuration(timing.mDuration, aRv);
+ if (aRv.Failed()) {
+ return result;
+ }
+ result.mDuration = duration;
+ result.mDelay = TimeDuration::FromMilliseconds(timing.mDelay);
+ result.mEndDelay = TimeDuration::FromMilliseconds(timing.mEndDelay);
+ result.mIterations = timing.mIterations;
+ result.mIterationStart = timing.mIterationStart;
+ result.mDirection = timing.mDirection;
+ result.mFill = timing.mFill;
+ result.mFunction =
+ AnimationUtils::ParseEasing(targetElement, timing.mEasing);
}
+ return result;
}
/* static */ TimingParams
TimingParams::FromOptionsUnion(
const dom::UnrestrictedDoubleOrKeyframeEffectOptions& aOptions,
- const Nullable& aTarget)
+ const Nullable& aTarget,
+ ErrorResult& aRv)
{
- return TimingParamsFromOptionsUnion(aOptions, aTarget);
+ return TimingParamsFromOptionsUnion(aOptions, aTarget, aRv);
}
/* static */ TimingParams
TimingParams::FromOptionsUnion(
const dom::UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
- const Nullable& aTarget)
+ const Nullable& aTarget,
+ ErrorResult& aRv)
{
- return TimingParamsFromOptionsUnion(aOptions, aTarget);
+ return TimingParamsFromOptionsUnion(aOptions, aTarget, aRv);
}
bool
TimingParams::operator==(const TimingParams& aOther) const
{
- bool durationEqual;
- if (mDuration.IsUnrestrictedDouble()) {
- durationEqual = aOther.mDuration.IsUnrestrictedDouble() &&
- (mDuration.GetAsUnrestrictedDouble() ==
- aOther.mDuration.GetAsUnrestrictedDouble());
- } else {
- // We consider all string values and uninitialized values as meaning "auto".
- // Since mDuration is either a string or uninitialized, we consider it equal
- // if aOther.mDuration is also either a string or uninitialized.
- durationEqual = !aOther.mDuration.IsUnrestrictedDouble();
- }
- return durationEqual &&
+ return mDuration == aOther.mDuration &&
mDelay == aOther.mDelay &&
mIterations == aOther.mIterations &&
mIterationStart == aOther.mIterationStart &&
diff --git a/dom/animation/TimingParams.h b/dom/animation/TimingParams.h
index 442ebc482d..26829afcb2 100644
--- a/dom/animation/TimingParams.h
+++ b/dom/animation/TimingParams.h
@@ -33,20 +33,39 @@ class ElementOrCSSPseudoElement;
struct TimingParams
{
TimingParams() = default;
- TimingParams(const dom::AnimationEffectTimingProperties& aTimingProperties,
- const dom::Element* aTarget);
- explicit TimingParams(double aDuration);
static TimingParams FromOptionsUnion(
const dom::UnrestrictedDoubleOrKeyframeEffectOptions& aOptions,
- const Nullable& aTarget);
+ const Nullable& aTarget,
+ ErrorResult& aRv);
static TimingParams FromOptionsUnion(
const dom::UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
- const Nullable& aTarget);
+ const Nullable& aTarget,
+ ErrorResult& aRv);
- // The unitialized state of mDuration represents "auto".
- // Bug 1237173: We will replace this with Maybe.
- dom::OwningUnrestrictedDoubleOrString mDuration;
+ // Range-checks and validates an UnrestrictedDoubleOrString or
+ // OwningUnrestrictedDoubleOrString object and converts to a
+ // StickyTimeDuration value or Nothing() if aDuration is "auto".
+ // Caller must check aRv.Failed().
+ template
+ static Maybe ParseDuration(DoubleOrString& aDuration,
+ ErrorResult& aRv) {
+ Maybe result;
+ if (aDuration.IsUnrestrictedDouble()) {
+ double durationInMs = aDuration.GetAsUnrestrictedDouble();
+ if (durationInMs >= 0) {
+ result.emplace(StickyTimeDuration::FromMilliseconds(durationInMs));
+ return result;
+ }
+ } else if (aDuration.GetAsString().EqualsLiteral("auto")) {
+ return result;
+ }
+ aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
+ return result;
+ }
+
+ // mDuration.isNothing() represents the "auto" value
+ Maybe mDuration;
TimeDuration mDelay; // Initializes to zero
TimeDuration mEndDelay;
double mIterations = 1.0; // Can be NaN, negative, +/-Infinity
diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp
index 61a561fa5c..5b981c2fb3 100644
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -3425,9 +3425,14 @@ Element::Animate(const Nullable& aTarget,
}
}
+ TimingParams timingParams =
+ TimingParams::FromOptionsUnion(aOptions, aTarget, aError);
+ if (aError.Failed()) {
+ return nullptr;
+ }
+
RefPtr effect =
- KeyframeEffect::Constructor(global, aTarget, frames,
- TimingParams::FromOptionsUnion(aOptions, aTarget), aError);
+ KeyframeEffect::Constructor(global, aTarget, frames, timingParams, aError);
if (aError.Failed()) {
return nullptr;
}
diff --git a/dom/base/File.cpp b/dom/base/File.cpp
index ca07193795..724c281d2e 100644
--- a/dom/base/File.cpp
+++ b/dom/base/File.cpp
@@ -227,12 +227,6 @@ Blob::IsFile() const
return mImpl->IsFile();
}
-bool
-Blob::IsDirectory() const
-{
- return mImpl->IsDirectory();
-}
-
const nsTArray>*
Blob::GetSubBlobImpls() const
{
@@ -420,11 +414,10 @@ File::Create(nsISupports* aParent, BlobImpl* aImpl)
/* static */ already_AddRefed
File::Create(nsISupports* aParent, const nsAString& aName,
const nsAString& aContentType, uint64_t aLength,
- int64_t aLastModifiedDate, BlobDirState aDirState)
+ int64_t aLastModifiedDate)
{
RefPtr file = new File(aParent,
- new BlobImplBase(aName, aContentType, aLength, aLastModifiedDate,
- aDirState));
+ new BlobImplBase(aName, aContentType, aLength, aLastModifiedDate));
return file.forget();
}
@@ -946,17 +939,6 @@ BlobImplFile::SetPath(const nsAString& aPath)
mPath = aPath;
}
-void
-BlobImplFile::LookupAndCacheIsDirectory()
-{
- MOZ_ASSERT(mIsFile,
- "This should only be called when this object has been created "
- "from an nsIFile to note that the nsIFile is a directory");
- bool isDir;
- mFile->IsDirectory(&isDir);
- mDirState = isDir ? BlobDirState::eIsDir : BlobDirState::eIsNotDir;
-}
-
////////////////////////////////////////////////////////////////////////////
// EmptyBlobImpl implementation
diff --git a/dom/base/File.h b/dom/base/File.h
index c43439071d..a052eb8b7b 100644
--- a/dom/base/File.h
+++ b/dom/base/File.h
@@ -44,18 +44,6 @@ class BlobImpl;
class File;
class OwningArrayBufferOrArrayBufferViewOrBlobOrString;
-/**
- * Used to indicate when a Blob/BlobImpl that was created from an nsIFile
- * (when IsFile() will return true) was from an nsIFile for which
- * nsIFile::IsDirectory() returned true. This is a tri-state to enable us to
- * assert that the state is always set when callers request it.
- */
-enum BlobDirState : uint32_t {
- eIsDir,
- eIsNotDir,
- eUnknownIfDir
-};
-
class Blob : public nsIDOMBlob
, public nsIXHRSendable
, public nsIMutable
@@ -101,12 +89,6 @@ public:
bool IsFile() const;
- /**
- * This may return true if the Blob was created from an nsIFile that is a
- * directory.
- */
- bool IsDirectory() const;
-
const nsTArray>* GetSubBlobImpls() const;
// This method returns null if this Blob is not a File; it returns
@@ -114,9 +96,6 @@ public:
// otherwise it returns a new File object with the same BlobImpl.
already_AddRefed ToFile();
- // XXXjwatt Consider having a ToDirectory() method. The need for a FileSystem
- // object complicates that though.
-
// This method creates a new File object with the given name and the same
// BlobImpl.
already_AddRefed ToFile(const nsAString& aName,
@@ -194,7 +173,7 @@ public:
static already_AddRefed
Create(nsISupports* aParent, const nsAString& aName,
const nsAString& aContentType, uint64_t aLength,
- int64_t aLastModifiedDate, BlobDirState aDirState);
+ int64_t aLastModifiedDate);
// The returned File takes ownership of aMemoryBuffer. aMemoryBuffer will be
// freed by moz_free so it must be allocated by moz_malloc or something
@@ -339,28 +318,6 @@ public:
virtual bool IsFile() const = 0;
- /**
- * Called when this BlobImpl was created from an nsIFile in order to call
- * nsIFile::IsDirectory() and cache the result so that when the BlobImpl is
- * copied to another process that informaton is available.
- * nsIFile::IsDirectory() does synchronous I/O, and BlobImpl objects may be
- * created on the main thread or in a non-chrome process (where I/O is not
- * allowed). Do not call this on a non-chrome process, and preferably do not
- * call it on the main thread.
- *
- * Not all creators of BlobImplFile will call this method, in which case
- * calling IsDirectory will MOZ_ASSERT.
- */
- virtual void LookupAndCacheIsDirectory() = 0;
- virtual void SetIsDirectory(bool aIsDir) = 0;
- virtual bool IsDirectory() const = 0;
-
- /**
- * Prefer IsDirectory(). This exists to help consumer code pass on state from
- * one BlobImpl when creating another.
- */
- virtual BlobDirState GetDirState() const = 0;
-
// True if this implementation can be sent to other threads.
virtual bool MayBeClonedToOtherThreads() const
{
@@ -377,11 +334,9 @@ class BlobImplBase : public BlobImpl
{
public:
BlobImplBase(const nsAString& aName, const nsAString& aContentType,
- uint64_t aLength, int64_t aLastModifiedDate,
- BlobDirState aDirState = BlobDirState::eUnknownIfDir)
+ uint64_t aLength, int64_t aLastModifiedDate)
: mIsFile(true)
, mImmutable(false)
- , mDirState(aDirState)
, mContentType(aContentType)
, mName(aName)
, mStart(0)
@@ -397,7 +352,6 @@ public:
uint64_t aLength)
: mIsFile(true)
, mImmutable(false)
- , mDirState(BlobDirState::eUnknownIfDir)
, mContentType(aContentType)
, mName(aName)
, mStart(0)
@@ -412,7 +366,6 @@ public:
BlobImplBase(const nsAString& aContentType, uint64_t aLength)
: mIsFile(false)
, mImmutable(false)
- , mDirState(BlobDirState::eUnknownIfDir)
, mContentType(aContentType)
, mStart(0)
, mLength(aLength)
@@ -427,7 +380,6 @@ public:
uint64_t aLength)
: mIsFile(false)
, mImmutable(false)
- , mDirState(BlobDirState::eUnknownIfDir)
, mContentType(aContentType)
, mStart(aStart)
, mLength(aLength)
@@ -518,36 +470,6 @@ public:
return mIsFile;
}
- virtual void LookupAndCacheIsDirectory() override
- {
- MOZ_ASSERT(false, "Why is this being called on a non-BlobImplFile?");
- }
-
- virtual void SetIsDirectory(bool aIsDir) override
- {
- MOZ_ASSERT(mIsFile,
- "This should only be called when this object has been created "
- "from an nsIFile to note that the nsIFile is a directory");
- mDirState = aIsDir ? BlobDirState::eIsDir : BlobDirState::eIsNotDir;
- }
-
- /**
- * Returns true if the nsIFile that this object wraps is a directory.
- */
- virtual bool IsDirectory() const override
- {
- MOZ_ASSERT(mDirState != BlobDirState::eUnknownIfDir,
- "Must only be used by callers for whom the code paths are "
- "know to call LookupAndCacheIsDirectory() or "
- "SetIsDirectory()");
- return mDirState == BlobDirState::eIsDir;
- }
-
- virtual BlobDirState GetDirState() const override
- {
- return mDirState;
- }
-
virtual bool IsSizeUnknown() const override
{
return mLength == UINT64_MAX;
@@ -565,7 +487,6 @@ protected:
bool mIsFile;
bool mImmutable;
- BlobDirState mDirState;
nsString mContentType;
nsString mName;
@@ -590,8 +511,7 @@ public:
BlobImplMemory(void* aMemoryBuffer, uint64_t aLength, const nsAString& aName,
const nsAString& aContentType, int64_t aLastModifiedDate)
- : BlobImplBase(aName, aContentType, aLength, aLastModifiedDate,
- BlobDirState::eIsNotDir)
+ : BlobImplBase(aName, aContentType, aLength, aLastModifiedDate)
, mDataOwner(new DataOwner(aMemoryBuffer, aLength))
{
NS_ASSERTION(mDataOwner && mDataOwner->mData, "must have data");
@@ -792,8 +712,6 @@ public:
void SetPath(const nsAString& aFullPath);
- virtual void LookupAndCacheIsDirectory() override;
-
// We always have size and date for this kind of blob.
virtual bool IsSizeUnknown() const override { return false; }
virtual bool IsDateUnknown() const override { return false; }
diff --git a/dom/base/FileList.cpp b/dom/base/FileList.cpp
index 5b807e7dea..4018dc1e53 100644
--- a/dom/base/FileList.cpp
+++ b/dom/base/FileList.cpp
@@ -4,6 +4,7 @@
* 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/dom/Directory.h"
#include "mozilla/dom/FileList.h"
#include "mozilla/dom/FileListBinding.h"
#include "mozilla/dom/File.h"
@@ -11,7 +12,7 @@
namespace mozilla {
namespace dom {
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FileList, mFiles, mParent)
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FileList, mFilesOrDirectories, mParent)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FileList)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
@@ -28,6 +29,20 @@ FileList::WrapObject(JSContext* aCx, JS::Handle aGivenProto)
return mozilla::dom::FileListBinding::Wrap(aCx, this, aGivenProto);
}
+void
+FileList::Append(File* aFile)
+{
+ OwningFileOrDirectory* element = mFilesOrDirectories.AppendElement();
+ element->SetAsFile() = aFile;
+}
+
+void
+FileList::Append(Directory* aDirectory)
+{
+ OwningFileOrDirectory* element = mFilesOrDirectories.AppendElement();
+ element->SetAsDirectory() = aDirectory;
+}
+
NS_IMETHODIMP
FileList::GetLength(uint32_t* aLength)
{
@@ -37,12 +52,76 @@ FileList::GetLength(uint32_t* aLength)
}
NS_IMETHODIMP
-FileList::Item(uint32_t aIndex, nsISupports** aFile)
+FileList::Item(uint32_t aIndex, nsISupports** aValue)
{
- nsCOMPtr file = Item(aIndex);
- file.forget(aFile);
+ if (aIndex >= mFilesOrDirectories.Length()) {
+ return NS_ERROR_FAILURE;
+ }
+
+ if (mFilesOrDirectories[aIndex].IsFile()) {
+ nsCOMPtr file = mFilesOrDirectories[aIndex].GetAsFile();
+ file.forget(aValue);
+ return NS_OK;
+ }
+
+ MOZ_ASSERT(mFilesOrDirectories[aIndex].IsDirectory());
+ RefPtr directory = mFilesOrDirectories[aIndex].GetAsDirectory();
+ directory.forget(aValue);
return NS_OK;
}
+void
+FileList::Item(uint32_t aIndex, Nullable& aValue,
+ ErrorResult& aRv) const
+{
+ if (aIndex >= mFilesOrDirectories.Length()) {
+ aValue.SetNull();
+ return;
+ }
+
+ aValue.SetValue(mFilesOrDirectories[aIndex]);
+}
+
+void
+FileList::IndexedGetter(uint32_t aIndex, bool& aFound,
+ Nullable& aFileOrDirectory,
+ ErrorResult& aRv) const
+{
+ aFound = aIndex < mFilesOrDirectories.Length();
+ Item(aIndex, aFileOrDirectory, aRv);
+}
+
+void
+FileList::ToSequence(Sequence& aSequence,
+ ErrorResult& aRv) const
+{
+ MOZ_ASSERT(aSequence.IsEmpty());
+ if (mFilesOrDirectories.IsEmpty()) {
+ return;
+ }
+
+ if (!aSequence.SetLength(mFilesOrDirectories.Length(),
+ mozilla::fallible_t())) {
+ aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+
+ for (uint32_t i = 0; i < mFilesOrDirectories.Length(); ++i) {
+ aSequence[i] = mFilesOrDirectories[i];
+ }
+}
+
+bool
+FileList::ClonableToDifferentThreadOrProcess() const
+{
+ for (uint32_t i = 0; i < mFilesOrDirectories.Length(); ++i) {
+ if (mFilesOrDirectories[i].IsDirectory()) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
} // namespace dom
} // namespace mozilla
diff --git a/dom/base/FileList.h b/dom/base/FileList.h
index 3e262153c2..b6aeeb7940 100644
--- a/dom/base/FileList.h
+++ b/dom/base/FileList.h
@@ -8,6 +8,7 @@
#define mozilla_dom_FileList_h
#include "mozilla/dom/BindingDeclarations.h"
+#include "mozilla/dom/UnionTypes.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIDOMFileList.h"
#include "nsWrapperCache.h"
@@ -39,15 +40,13 @@ public:
return mParent;
}
- bool Append(File* aFile)
- {
- return mFiles.AppendElement(aFile);
- }
+ void Append(File* aFile);
+ void Append(Directory* aDirectory);
bool Remove(uint32_t aIndex)
{
- if (aIndex < mFiles.Length()) {
- mFiles.RemoveElementAt(aIndex);
+ if (aIndex < mFilesOrDirectories.Length()) {
+ mFilesOrDirectories.RemoveElementAt(aIndex);
return true;
}
@@ -56,7 +55,7 @@ public:
void Clear()
{
- return mFiles.Clear();
+ return mFilesOrDirectories.Clear();
}
static FileList* FromSupports(nsISupports* aSupports)
@@ -76,29 +75,34 @@ public:
return static_cast(aSupports);
}
- File* Item(uint32_t aIndex)
+ const OwningFileOrDirectory& UnsafeItem(uint32_t aIndex) const
{
- return mFiles.SafeElementAt(aIndex);
+ MOZ_ASSERT(aIndex < Length());
+ return mFilesOrDirectories[aIndex];
}
- File* IndexedGetter(uint32_t aIndex, bool& aFound)
+ void Item(uint32_t aIndex,
+ Nullable& aFileOrDirectory,
+ ErrorResult& aRv) const;
+
+ void IndexedGetter(uint32_t aIndex, bool& aFound,
+ Nullable& aFileOrDirectory,
+ ErrorResult& aRv) const;
+
+ uint32_t Length() const
{
- aFound = aIndex < mFiles.Length();
- if (!aFound) {
- return nullptr;
- }
- return mFiles.ElementAt(aIndex);
+ return mFilesOrDirectories.Length();
}
- uint32_t Length()
- {
- return mFiles.Length();
- }
+ void ToSequence(Sequence& aSequence,
+ ErrorResult& aRv) const;
+
+ bool ClonableToDifferentThreadOrProcess() const;
private:
~FileList() {}
- nsTArray> mFiles;
+ nsTArray mFilesOrDirectories;
nsCOMPtr mParent;
};
diff --git a/dom/base/FormData.cpp b/dom/base/FormData.cpp
index fd55894bc4..d629eee431 100644
--- a/dom/base/FormData.cpp
+++ b/dom/base/FormData.cpp
@@ -125,7 +125,7 @@ FormData::Append(const nsAString& aName, Blob& aBlob,
return;
}
- AddNameBlobPair(aName, file);
+ AddNameBlobOrNullPair(aName, file);
}
void
@@ -179,12 +179,18 @@ FormData::Has(const nsAString& aName)
}
nsresult
-FormData::AddNameBlobPair(const nsAString& aName, Blob* aBlob)
+FormData::AddNameBlobOrNullPair(const nsAString& aName, Blob* aBlob)
{
- MOZ_ASSERT(aBlob);
+ RefPtr file;
+
+ if (!aBlob) {
+ FormDataTuple* data = mFormData.AppendElement();
+ SetNameValuePair(data, aName, EmptyString(), true /* aWasNullBlob */);
+ return NS_OK;
+ }
ErrorResult rv;
- RefPtr file = GetOrCreateFileCalledBlob(*aBlob, rv);
+ file = GetOrCreateFileCalledBlob(*aBlob, rv);
if (NS_WARN_IF(rv.Failed())) {
return rv.StealNSResult();
}
@@ -269,10 +275,12 @@ FormData::GetValueAtIndex(uint32_t aIndex) const
void
FormData::SetNameValuePair(FormDataTuple* aData,
const nsAString& aName,
- const nsAString& aValue)
+ const nsAString& aValue,
+ bool aWasNullBlob)
{
MOZ_ASSERT(aData);
aData->name = aName;
+ aData->wasNullBlob = aWasNullBlob;
aData->value.SetAsUSVString() = aValue;
}
@@ -285,6 +293,7 @@ FormData::SetNameFilePair(FormDataTuple* aData,
MOZ_ASSERT(aFile);
aData->name = aName;
+ aData->wasNullBlob = false;
aData->value.SetAsBlob() = aFile;
}
@@ -366,13 +375,16 @@ FormData::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
nsFSMultipartFormData fs(NS_LITERAL_CSTRING("UTF-8"), nullptr);
for (uint32_t i = 0; i < mFormData.Length(); ++i) {
- if (mFormData[i].value.IsBlob()) {
- fs.AddNameBlobPair(mFormData[i].name, mFormData[i].value.GetAsBlob());
+ if (mFormData[i].wasNullBlob) {
+ MOZ_ASSERT(mFormData[i].value.IsUSVString());
+ fs.AddNameBlobOrNullPair(mFormData[i].name, nullptr);
} else if (mFormData[i].value.IsUSVString()) {
fs.AddNameValuePair(mFormData[i].name,
mFormData[i].value.GetAsUSVString());
} else {
- MOZ_CRASH("This should no be possible.");
+ MOZ_ASSERT(mFormData[i].value.IsBlob());
+ fs.AddNameBlobOrNullPair(mFormData[i].name,
+ mFormData[i].value.GetAsBlob());
}
}
diff --git a/dom/base/FormData.h b/dom/base/FormData.h
index 66373730cb..00652e8411 100644
--- a/dom/base/FormData.h
+++ b/dom/base/FormData.h
@@ -35,6 +35,7 @@ private:
struct FormDataTuple
{
nsString name;
+ bool wasNullBlob;
OwningBlobOrUSVString value;
};
@@ -45,7 +46,8 @@ private:
void SetNameValuePair(FormDataTuple* aData,
const nsAString& aName,
- const nsAString& aValue);
+ const nsAString& aValue,
+ bool aWasNullBlob = false);
void SetNameFilePair(FormDataTuple* aData,
const nsAString& aName,
@@ -114,8 +116,8 @@ public:
return NS_OK;
}
- virtual nsresult AddNameBlobPair(const nsAString& aName,
- Blob* aBlob) override;
+ virtual nsresult AddNameBlobOrNullPair(const nsAString& aName,
+ Blob* aBlob) override;
typedef bool (*FormDataEntryCallback)(const nsString& aName,
const OwningBlobOrUSVString& aValue,
diff --git a/dom/base/StructuredCloneHolder.cpp b/dom/base/StructuredCloneHolder.cpp
index f0da538093..1313e53251 100644
--- a/dom/base/StructuredCloneHolder.cpp
+++ b/dom/base/StructuredCloneHolder.cpp
@@ -10,6 +10,7 @@
#include "mozilla/AutoRestore.h"
#include "mozilla/dom/BlobBinding.h"
#include "mozilla/dom/CryptoKey.h"
+#include "mozilla/dom/Directory.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/FileList.h"
#include "mozilla/dom/FileListBinding.h"
@@ -723,36 +724,59 @@ ReadFileList(JSContext* aCx,
{
RefPtr fileList = new FileList(aHolder->ParentDuringRead());
- uint32_t tag, offset;
- // Offset is the index of the blobImpl from which we can find the blobImpl
- // for this FileList.
- if (!JS_ReadUint32Pair(aReader, &tag, &offset)) {
- return nullptr;
- }
-
- MOZ_ASSERT(tag == 0);
-
- // |aCount| is the number of BlobImpls to use from the |offset|.
+ // |aCount| is the number of Files or Directory for this FileList.
for (uint32_t i = 0; i < aCount; ++i) {
- uint32_t index = offset + i;
- MOZ_ASSERT(index < aHolder->BlobImpls().Length());
-
- RefPtr blobImpl = aHolder->BlobImpls()[index];
- MOZ_ASSERT(blobImpl->IsFile());
-
- ErrorResult rv;
- blobImpl = EnsureBlobForBackgroundManager(blobImpl, nullptr, rv);
- if (NS_WARN_IF(rv.Failed())) {
- rv.SuppressException();
+ uint32_t tagOrDirectoryType, indexOrLengthOfString;
+ if (!JS_ReadUint32Pair(aReader, &tagOrDirectoryType,
+ &indexOrLengthOfString)) {
return nullptr;
}
- MOZ_ASSERT(blobImpl);
+ MOZ_ASSERT(tagOrDirectoryType == SCTAG_DOM_BLOB ||
+ tagOrDirectoryType == Directory::eDOMRootDirectory ||
+ tagOrDirectoryType == Directory::eNotDOMRootDirectory);
- RefPtr file = File::Create(aHolder->ParentDuringRead(), blobImpl);
- if (!fileList->Append(file)) {
+ if (tagOrDirectoryType == SCTAG_DOM_BLOB) {
+ MOZ_ASSERT(indexOrLengthOfString < aHolder->BlobImpls().Length());
+
+ RefPtr blobImpl =
+ aHolder->BlobImpls()[indexOrLengthOfString];
+ MOZ_ASSERT(blobImpl->IsFile());
+
+ ErrorResult rv;
+ blobImpl = EnsureBlobForBackgroundManager(blobImpl, nullptr, rv);
+ if (NS_WARN_IF(rv.Failed())) {
+ rv.SuppressException();
+ return nullptr;
+ }
+
+ RefPtr file =
+ File::Create(aHolder->ParentDuringRead(), blobImpl);
+ MOZ_ASSERT(file);
+
+ fileList->Append(file);
+ continue;
+ }
+
+ nsAutoString path;
+ path.SetLength(indexOrLengthOfString);
+ size_t charSize = sizeof(nsString::char_type);
+ if (!JS_ReadBytes(aReader, (void*) path.BeginWriting(),
+ indexOrLengthOfString * charSize)) {
return nullptr;
}
+
+ nsCOMPtr file;
+ nsresult rv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(path), true,
+ getter_AddRefs(file));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return nullptr;
+ }
+
+ RefPtr directory =
+ Directory::Create(aHolder->ParentDuringRead(), file,
+ (Directory::DirectoryType) tagOrDirectoryType);
+ fileList->Append(directory);
}
if (!ToJSValue(aCx, fileList, &val)) {
@@ -765,7 +789,13 @@ ReadFileList(JSContext* aCx,
// The format of the FileList serialization is:
// - pair of ints: SCTAG_DOM_FILELIST, Length of the FileList
-// - pair of ints: 0, The offset of the BlobImpl array
+// - for each element of the FileList:
+// - if it's a blob:
+// - pair of ints: SCTAG_DOM_BLOB, index of the BlobImpl in the array
+// mBlobImplArray.
+// - else:
+// - pair of ints: 0/1 is root, string length
+// - value string
bool
WriteFileList(JSStructuredCloneWriter* aWriter,
FileList* aFileList,
@@ -775,13 +805,8 @@ WriteFileList(JSStructuredCloneWriter* aWriter,
MOZ_ASSERT(aFileList);
MOZ_ASSERT(aHolder);
- // A FileList is serialized writing the X number of elements and the offset
- // from mBlobImplArray. The Read will take X elements from mBlobImplArray
- // starting from the offset.
if (!JS_WriteUint32Pair(aWriter, SCTAG_DOM_FILELIST,
- aFileList->Length()) ||
- !JS_WriteUint32Pair(aWriter, 0,
- aHolder->BlobImpls().Length())) {
+ aFileList->Length())) {
return false;
}
@@ -789,18 +814,39 @@ WriteFileList(JSStructuredCloneWriter* aWriter,
nsTArray> blobImpls;
for (uint32_t i = 0; i < aFileList->Length(); ++i) {
- RefPtr blobImpl =
- EnsureBlobForBackgroundManager(aFileList->Item(i)->Impl(), nullptr, rv);
- if (NS_WARN_IF(rv.Failed())) {
- rv.SuppressException();
- return false;
+ const OwningFileOrDirectory& data = aFileList->UnsafeItem(i);
+
+ if (data.IsFile()) {
+ RefPtr blobImpl =
+ EnsureBlobForBackgroundManager(data.GetAsFile()->Impl(), nullptr, rv);
+ if (NS_WARN_IF(rv.Failed())) {
+ rv.SuppressException();
+ return false;
+ }
+
+ if (!JS_WriteUint32Pair(aWriter, SCTAG_DOM_BLOB,
+ aHolder->BlobImpls().Length())) {
+ return false;
+ }
+
+ aHolder->BlobImpls().AppendElement(blobImpl);
+ continue;
}
- MOZ_ASSERT(blobImpl);
- blobImpls.AppendElement(blobImpl);
+ MOZ_ASSERT(data.IsDirectory());
+
+ nsAutoString path;
+ data.GetAsDirectory()->GetFullRealPath(path);
+
+ size_t charSize = sizeof(nsString::char_type);
+ if (!JS_WriteUint32Pair(aWriter,
+ (uint32_t)data.GetAsDirectory()->Type(),
+ path.Length()) ||
+ !JS_WriteBytes(aWriter, path.get(), path.Length() * charSize)) {
+ return false;
+ }
}
- aHolder->BlobImpls().AppendElements(blobImpls);
return true;
}
@@ -1004,7 +1050,9 @@ StructuredCloneHolder::CustomWriteHandler(JSContext* aCx,
// See if this is a FileList object.
{
FileList* fileList = nullptr;
- if (NS_SUCCEEDED(UNWRAP_OBJECT(FileList, aObj, fileList))) {
+ if (NS_SUCCEEDED(UNWRAP_OBJECT(FileList, aObj, fileList)) &&
+ (mSupportedContext == SameProcessSameThread ||
+ fileList->ClonableToDifferentThreadOrProcess())) {
return WriteFileList(aWriter, fileList, this);
}
}
diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp
index 384a092666..20c7cb7d5c 100644
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -7576,7 +7576,6 @@ nsContentUtils::TransferableToIPCTransferable(nsITransferable* aTransferable,
// has this data available to it when passed over:
blobImpl->GetSize(rv);
blobImpl->GetLastModified(rv);
- blobImpl->LookupAndCacheIsDirectory();
} else {
if (aInSyncMessage) {
// Can't do anything.
diff --git a/dom/base/nsIDOMFileList.idl b/dom/base/nsIDOMFileList.idl
index 338bd72793..8e6dcf52a3 100644
--- a/dom/base/nsIDOMFileList.idl
+++ b/dom/base/nsIDOMFileList.idl
@@ -5,7 +5,7 @@
#include "nsISupports.idl"
-[uuid(57128a85-34de-42db-a252-84dd57724a59)]
+[builtinclass, uuid(57128a85-34de-42db-a252-84dd57724a59)]
interface nsIDOMFileList : nsISupports
{
readonly attribute unsigned long length;
diff --git a/dom/base/test/file_bug1250148.sjs b/dom/base/test/file_bug1250148.sjs
new file mode 100644
index 0000000000..a85347896b
--- /dev/null
+++ b/dom/base/test/file_bug1250148.sjs
@@ -0,0 +1,60 @@
+const CC = Components.Constructor;
+const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
+ "nsIBinaryInputStream",
+ "setInputStream");
+
+function utf8decode(s) {
+ return decodeURIComponent(escape(s));
+}
+
+function utf8encode(s) {
+ return unescape(encodeURIComponent(s));
+}
+
+function handleRequest(request, response) {
+ var bodyStream = new BinaryInputStream(request.bodyInputStream);
+
+ var requestBody = "";
+ while ((bodyAvail = bodyStream.available()) > 0) {
+ requestBody += bodyStream.readBytes(bodyAvail);
+ }
+
+ var result = [];
+
+ if (request.method == "POST") {
+ var contentTypeParams = {};
+ request.getHeader("Content-Type").split(/\s*\;\s*/).forEach(function(s) {
+ if (s.indexOf('=') >= 0) {
+ let [name, value] = s.split('=');
+ contentTypeParams[name] = value;
+ }
+ else {
+ contentTypeParams[''] = s;
+ }
+ });
+
+ if (contentTypeParams[''] == "multipart/form-data" &&
+ request.queryString == "") {
+ requestBody.split("--" + contentTypeParams.boundary).slice(1, -1).forEach(function (s) {
+
+ let headers = {};
+ let headerEnd = s.indexOf("\r\n\r\n");
+ s.substr(2, headerEnd-2).split("\r\n").forEach(function(s) {
+ // We're assuming UTF8 for now
+ let [name, value] = s.split(': ');
+ headers[name] = utf8decode(value);
+ });
+
+ let body = s.substring(headerEnd + 4, s.length - 2);
+ if (!headers["Content-Type"] || headers["Content-Type"] == "text/plain") {
+ // We're assuming UTF8 for now
+ body = utf8decode(body);
+ }
+ result.push({ headers: headers, body: body});
+ });
+ }
+ }
+
+ response.setHeader("Content-Type", "text/plain; charset=utf-8", false);
+ response.write(utf8encode(JSON.stringify(result)));
+}
diff --git a/dom/base/test/mochitest.ini b/dom/base/test/mochitest.ini
index 0ea90b5b13..edec3586a8 100644
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -257,6 +257,7 @@ support-files =
referrer_change_server.sjs
file_change_policy_redirect.html
file_bug1198095.js
+ file_bug1250148.sjs
[test_anonymousContent_api.html]
[test_anonymousContent_append_after_reflow.html]
@@ -848,3 +849,5 @@ skip-if = buildapp == 'b2g' #no ssl support
[test_document.all_iteration.html]
[test_bug1198095.html]
[test_bug1187157.html]
+[test_bug769117.html]
+[test_bug1250148.html]
diff --git a/dom/base/test/script_postmessages_fileList.js b/dom/base/test/script_postmessages_fileList.js
index 8c8af4289a..8382958f32 100644
--- a/dom/base/test/script_postmessages_fileList.js
+++ b/dom/base/test/script_postmessages_fileList.js
@@ -1,15 +1,25 @@
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.importGlobalProperties(["File"]);
-let testFile = Cc["@mozilla.org/file/directory_service;1"]
- .getService(Ci.nsIDirectoryService)
- .QueryInterface(Ci.nsIProperties)
- .get("ProfD", Ci.nsIFile);
-testFile.append("prefs.js");
-
addMessageListener("file.open", function () {
+ var testFile = Cc["@mozilla.org/file/directory_service;1"]
+ .getService(Ci.nsIDirectoryService)
+ .QueryInterface(Ci.nsIProperties)
+ .get("ProfD", Ci.nsIFile);
+ testFile.append("prefs.js");
+
sendAsyncMessage("file.opened", {
file: new File(testFile)
});
});
+addMessageListener("dir.open", function () {
+ var testFile = Cc["@mozilla.org/file/directory_service;1"]
+ .getService(Ci.nsIDirectoryService)
+ .QueryInterface(Ci.nsIProperties)
+ .get("ProfD", Ci.nsIFile);
+
+ sendAsyncMessage("dir.opened", {
+ dir: testFile.path
+ });
+});
diff --git a/dom/base/test/test_bug1187157.html b/dom/base/test/test_bug1187157.html
index dda4804a7b..37942f0051 100644
--- a/dom/base/test/test_bug1187157.html
+++ b/dom/base/test/test_bug1187157.html
@@ -15,14 +15,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=789315
+
+
+
diff --git a/dom/base/test/test_bug1250148.html b/dom/base/test/test_bug1250148.html
new file mode 100644
index 0000000000..1584360442
--- /dev/null
+++ b/dom/base/test/test_bug1250148.html
@@ -0,0 +1,52 @@
+
+
+
+