diff --git a/configure.in b/configure.in
index d91d92e94d3a..7cdf8e5624cc 100644
--- a/configure.in
+++ b/configure.in
@@ -7798,6 +7798,25 @@ AC_SUBST(PROFILE_GEN_LDFLAGS)
AC_SUBST(PROFILE_USE_CFLAGS)
AC_SUBST(PROFILE_USE_LDFLAGS)
+dnl =============================================
+dnl Support for -fno-integrated-as (recent clang)
+dnl =============================================
+dnl Under clang 3.4+, use -fno-integrated-as to
+dnl build libvpx's vp8_asm_enc_offsets.c
+
+_SAVE_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -fno-integrated-as"
+
+AC_MSG_CHECKING([whether C compiler supports -fno-integrated-as])
+AC_TRY_COMPILE([], [return 0;],
+ [ NO_INTEGRATED_AS_CFLAGS="-fno-integrated-as"
+ result="yes" ], result="no")
+AC_MSG_RESULT([$result])
+
+CFLAGS="$_SAVE_CFLAGS"
+
+AC_SUBST(NO_INTEGRATED_AS_CFLAGS)
+
fi # ! SKIP_COMPILER_CHECKS
AC_DEFINE(CPP_THROW_NEW, [throw()])
diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h
index 9259c24482e3..64f5484ce983 100644
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -66,6 +66,7 @@ class nsIStyleRule;
class nsIStyleSheet;
class nsIURI;
class nsIVariant;
+class nsLocation;
class nsViewManager;
class nsPresContext;
class nsRange;
@@ -2184,7 +2185,7 @@ public:
const nsAString& aQualifiedName,
mozilla::ErrorResult& rv);
void GetInputEncoding(nsAString& aInputEncoding);
- already_AddRefed GetLocation() const;
+ already_AddRefed GetLocation() const;
void GetReferrer(nsAString& aReferrer) const;
void GetLastModified(nsAString& aLastModified) const;
void GetReadyState(nsAString& aReadyState) const;
diff --git a/content/base/src/Link.cpp b/content/base/src/Link.cpp
index d5994b6cbed5..21f10cf3c1df 100644
--- a/content/base/src/Link.cpp
+++ b/content/base/src/Link.cpp
@@ -128,7 +128,7 @@ Link::GetURI() const
}
void
-Link::SetProtocol(const nsAString &aProtocol)
+Link::SetProtocol(const nsAString &aProtocol, ErrorResult& aError)
{
nsCOMPtr uri(GetURIToMutate());
if (!uri) {
@@ -147,7 +147,7 @@ Link::SetProtocol(const nsAString &aProtocol)
}
void
-Link::SetPassword(const nsAString &aPassword)
+Link::SetPassword(const nsAString &aPassword, ErrorResult& aError)
{
nsCOMPtr uri(GetURIToMutate());
if (!uri) {
@@ -160,7 +160,7 @@ Link::SetPassword(const nsAString &aPassword)
}
void
-Link::SetUsername(const nsAString &aUsername)
+Link::SetUsername(const nsAString &aUsername, ErrorResult& aError)
{
nsCOMPtr uri(GetURIToMutate());
if (!uri) {
@@ -173,7 +173,7 @@ Link::SetUsername(const nsAString &aUsername)
}
void
-Link::SetHost(const nsAString &aHost)
+Link::SetHost(const nsAString &aHost, ErrorResult& aError)
{
nsCOMPtr uri(GetURIToMutate());
if (!uri) {
@@ -186,7 +186,7 @@ Link::SetHost(const nsAString &aHost)
}
void
-Link::SetHostname(const nsAString &aHostname)
+Link::SetHostname(const nsAString &aHostname, ErrorResult& aError)
{
nsCOMPtr uri(GetURIToMutate());
if (!uri) {
@@ -199,7 +199,7 @@ Link::SetHostname(const nsAString &aHostname)
}
void
-Link::SetPathname(const nsAString &aPathname)
+Link::SetPathname(const nsAString &aPathname, ErrorResult& aError)
{
nsCOMPtr uri(GetURIToMutate());
nsCOMPtr url(do_QueryInterface(uri));
@@ -213,7 +213,7 @@ Link::SetPathname(const nsAString &aPathname)
}
void
-Link::SetSearch(const nsAString& aSearch)
+Link::SetSearch(const nsAString& aSearch, ErrorResult& aError)
{
SetSearchInternal(aSearch);
UpdateURLSearchParams();
@@ -234,7 +234,7 @@ Link::SetSearchInternal(const nsAString& aSearch)
}
void
-Link::SetPort(const nsAString &aPort)
+Link::SetPort(const nsAString &aPort, ErrorResult& aError)
{
nsCOMPtr uri(GetURIToMutate());
if (!uri) {
@@ -259,7 +259,7 @@ Link::SetPort(const nsAString &aPort)
}
void
-Link::SetHash(const nsAString &aHash)
+Link::SetHash(const nsAString &aHash, ErrorResult& aError)
{
nsCOMPtr uri(GetURIToMutate());
if (!uri) {
@@ -272,7 +272,7 @@ Link::SetHash(const nsAString &aHash)
}
void
-Link::GetOrigin(nsAString &aOrigin)
+Link::GetOrigin(nsAString &aOrigin, ErrorResult& aError)
{
aOrigin.Truncate();
@@ -287,7 +287,7 @@ Link::GetOrigin(nsAString &aOrigin)
}
void
-Link::GetProtocol(nsAString &_protocol)
+Link::GetProtocol(nsAString &_protocol, ErrorResult& aError)
{
nsCOMPtr uri(GetURI());
if (!uri) {
@@ -303,7 +303,7 @@ Link::GetProtocol(nsAString &_protocol)
}
void
-Link::GetUsername(nsAString& aUsername)
+Link::GetUsername(nsAString& aUsername, ErrorResult& aError)
{
aUsername.Truncate();
@@ -318,7 +318,7 @@ Link::GetUsername(nsAString& aUsername)
}
void
-Link::GetPassword(nsAString &aPassword)
+Link::GetPassword(nsAString &aPassword, ErrorResult& aError)
{
aPassword.Truncate();
@@ -333,7 +333,7 @@ Link::GetPassword(nsAString &aPassword)
}
void
-Link::GetHost(nsAString &_host)
+Link::GetHost(nsAString &_host, ErrorResult& aError)
{
_host.Truncate();
@@ -351,7 +351,7 @@ Link::GetHost(nsAString &_host)
}
void
-Link::GetHostname(nsAString &_hostname)
+Link::GetHostname(nsAString &_hostname, ErrorResult& aError)
{
_hostname.Truncate();
@@ -371,7 +371,7 @@ Link::GetHostname(nsAString &_hostname)
}
void
-Link::GetPathname(nsAString &_pathname)
+Link::GetPathname(nsAString &_pathname, ErrorResult& aError)
{
_pathname.Truncate();
@@ -391,7 +391,7 @@ Link::GetPathname(nsAString &_pathname)
}
void
-Link::GetSearch(nsAString &_search)
+Link::GetSearch(nsAString &_search, ErrorResult& aError)
{
_search.Truncate();
@@ -411,7 +411,7 @@ Link::GetSearch(nsAString &_search)
}
void
-Link::GetPort(nsAString &_port)
+Link::GetPort(nsAString &_port, ErrorResult& aError)
{
_port.Truncate();
@@ -433,7 +433,7 @@ Link::GetPort(nsAString &_port)
}
void
-Link::GetHash(nsAString &_hash)
+Link::GetHash(nsAString &_hash, ErrorResult& aError)
{
_hash.Truncate();
diff --git a/content/base/src/Link.h b/content/base/src/Link.h
index c378ddde085e..9ade6e495275 100644
--- a/content/base/src/Link.h
+++ b/content/base/src/Link.h
@@ -57,27 +57,27 @@ public:
/**
* Helper methods for modifying and obtaining parts of the URI of the Link.
*/
- void SetProtocol(const nsAString &aProtocol);
- void SetUsername(const nsAString &aUsername);
- void SetPassword(const nsAString &aPassword);
- void SetHost(const nsAString &aHost);
- void SetHostname(const nsAString &aHostname);
- void SetPathname(const nsAString &aPathname);
- void SetSearch(const nsAString &aSearch);
+ void SetProtocol(const nsAString &aProtocol, ErrorResult& aError);
+ void SetUsername(const nsAString &aUsername, ErrorResult& aError);
+ void SetPassword(const nsAString &aPassword, ErrorResult& aError);
+ void SetHost(const nsAString &aHost, ErrorResult& aError);
+ void SetHostname(const nsAString &aHostname, ErrorResult& aError);
+ void SetPathname(const nsAString &aPathname, ErrorResult& aError);
+ void SetSearch(const nsAString &aSearch, ErrorResult& aError);
void SetSearchParams(mozilla::dom::URLSearchParams& aSearchParams);
- void SetPort(const nsAString &aPort);
- void SetHash(const nsAString &aHash);
- void GetOrigin(nsAString &aOrigin);
- void GetProtocol(nsAString &_protocol);
- void GetUsername(nsAString &aUsername);
- void GetPassword(nsAString &aPassword);
- void GetHost(nsAString &_host);
- void GetHostname(nsAString &_hostname);
- void GetPathname(nsAString &_pathname);
- void GetSearch(nsAString &_search);
+ void SetPort(const nsAString &aPort, ErrorResult& aError);
+ void SetHash(const nsAString &aHash, ErrorResult& aError);
+ void GetOrigin(nsAString &aOrigin, ErrorResult& aError);
+ void GetProtocol(nsAString &_protocol, ErrorResult& aError);
+ void GetUsername(nsAString &aUsername, ErrorResult& aError);
+ void GetPassword(nsAString &aPassword, ErrorResult& aError);
+ void GetHost(nsAString &_host, ErrorResult& aError);
+ void GetHostname(nsAString &_hostname, ErrorResult& aError);
+ void GetPathname(nsAString &_pathname, ErrorResult& aError);
+ void GetSearch(nsAString &_search, ErrorResult& aError);
URLSearchParams* SearchParams();
- void GetPort(nsAString &_port);
- void GetHash(nsAString &_hash);
+ void GetPort(nsAString &_port, ErrorResult& aError);
+ void GetHash(nsAString &_hash, ErrorResult& aError);
/**
* Invalidates any link caching, and resets the state to the default.
diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp
index 839e4de5d02b..ecd2b82af969 100644
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -223,6 +223,7 @@
#include "nsContentPermissionHelper.h"
#include "mozilla/dom/DOMStringList.h"
#include "nsWindowMemoryReporter.h"
+#include "nsLocation.h"
using namespace mozilla;
using namespace mozilla::dom;
@@ -6546,7 +6547,7 @@ nsDocument::GetLocation(nsIDOMLocation **_retval)
return NS_OK;
}
-already_AddRefed
+already_AddRefed
nsIDocument::GetLocation() const
{
nsCOMPtr w = do_QueryInterface(mScriptGlobalObject);
@@ -6557,7 +6558,7 @@ nsIDocument::GetLocation() const
nsCOMPtr loc;
w->GetLocation(getter_AddRefs(loc));
- return loc.forget();
+ return loc.forget().downcast();
}
Element*
diff --git a/content/canvas/src/CanvasRenderingContext2D.cpp b/content/canvas/src/CanvasRenderingContext2D.cpp
index 623d114ca6aa..c0bde17a4983 100644
--- a/content/canvas/src/CanvasRenderingContext2D.cpp
+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
@@ -367,7 +367,7 @@ public:
mCtx->CurrentState().op);
}
- operator DrawTarget*()
+ operator DrawTarget*()
{
return mTarget;
}
@@ -944,7 +944,8 @@ CanvasRenderingContext2D::EnsureTarget()
if (glue && glue->GetGrContext() && glue->GetGLContext()) {
mTarget = Factory::CreateDrawTargetSkiaWithGrContext(glue->GetGrContext(), size, format);
if (mTarget) {
- mStream = gfx::SurfaceStream::CreateForType(SurfaceStreamType::TripleBuffer, glue->GetGLContext());
+ mStream = gl::SurfaceStream::CreateForType(gl::SurfaceStreamType::TripleBuffer,
+ glue->GetGLContext());
AddDemotableContext(this);
} else {
printf_stderr("Failed to create a SkiaGL DrawTarget, falling back to software\n");
@@ -2526,7 +2527,7 @@ CanvasRenderingContext2D::AddHitRegion(const HitRegionOptions& options, ErrorRes
nsINode::DeleteProperty);
#endif
}
-
+
// finally, add the region to the list
RegionInfo info;
info.mId = options.mId;
@@ -3468,7 +3469,7 @@ CanvasRenderingContext2D::DrawDirectlyToCanvas(
nsRefPtr context = new gfxContext(tempTarget);
context->SetMatrix(contextMatrix);
-
+
// FLAG_CLAMP is added for increased performance
uint32_t modifiedFlags = image.mDrawingFlags | imgIContainer::FLAG_CLAMP;
diff --git a/content/canvas/src/CanvasRenderingContext2D.h b/content/canvas/src/CanvasRenderingContext2D.h
index 5c7b8dacf49f..9f9d784bfedc 100644
--- a/content/canvas/src/CanvasRenderingContext2D.h
+++ b/content/canvas/src/CanvasRenderingContext2D.h
@@ -30,7 +30,7 @@ class nsGlobalWindow;
class nsXULElement;
namespace mozilla {
-namespace gfx {
+namespace gl {
class SourceSurface;
class SurfaceStream;
}
@@ -393,21 +393,21 @@ public:
double endAngle, bool anticlockwise, mozilla::ErrorResult& error);
void GetMozCurrentTransform(JSContext* cx,
- JS::MutableHandle result,
- mozilla::ErrorResult& error) const;
+ JS::MutableHandle result,
+ mozilla::ErrorResult& error) const;
void SetMozCurrentTransform(JSContext* cx,
JS::Handle currentTransform,
mozilla::ErrorResult& error);
void GetMozCurrentTransformInverse(JSContext* cx,
- JS::MutableHandle result,
- mozilla::ErrorResult& error) const;
+ JS::MutableHandle result,
+ mozilla::ErrorResult& error) const;
void SetMozCurrentTransformInverse(JSContext* cx,
JS::Handle currentTransform,
mozilla::ErrorResult& error);
void GetFillRule(nsAString& fillRule);
void SetFillRule(const nsAString& fillRule);
void GetMozDash(JSContext* cx, JS::MutableHandle retval,
- mozilla::ErrorResult& error);
+ mozilla::ErrorResult& error);
void SetMozDash(JSContext* cx, const JS::Value& mozDash,
mozilla::ErrorResult& error);
@@ -661,7 +661,7 @@ protected:
void DrawImage(const HTMLImageOrCanvasOrVideoElement &imgElt,
double sx, double sy, double sw, double sh,
- double dx, double dy, double dw, double dh,
+ double dx, double dy, double dw, double dh,
uint8_t optional_argc, mozilla::ErrorResult& error);
void DrawDirectlyToCanvas(const nsLayoutUtils::DirectDrawInfo& image,
@@ -711,7 +711,7 @@ protected:
// sErrorTarget.
mozilla::RefPtr mTarget;
- RefPtr mStream;
+ RefPtr mStream;
/**
* Flag to avoid duplicate calls to InvalidateFrame. Set to true whenever
@@ -789,7 +789,7 @@ protected:
// The spec says we should not draw shadows if the operator is OVER.
// If it's over and the alpha value is zero, nothing needs to be drawn.
- return NS_GET_A(state.shadowColor) != 0 &&
+ return NS_GET_A(state.shadowColor) != 0 &&
(state.shadowBlur != 0 || state.shadowOffset.x != 0 || state.shadowOffset.y != 0);
}
diff --git a/content/canvas/src/WebGLContextDraw.cpp b/content/canvas/src/WebGLContextDraw.cpp
index 0d70767f6463..d4854aaf5402 100644
--- a/content/canvas/src/WebGLContextDraw.cpp
+++ b/content/canvas/src/WebGLContextDraw.cpp
@@ -450,7 +450,17 @@ WebGLContext::ValidateBufferFetching(const char *info)
maxVertices = std::min(maxVertices, checked_maxAllowedCount.value());
hasPerVertex = true;
} else {
- maxInstances = std::min(maxInstances, checked_maxAllowedCount.value() / vd.divisor);
+ CheckedUint32 checked_curMaxInstances = checked_maxAllowedCount * vd.divisor;
+
+ uint32_t curMaxInstances = UINT32_MAX;
+ // If this isn't valid, it's because we overflowed our
+ // uint32 above. Just leave this as UINT32_MAX, since
+ // sizeof(uint32) becomes our limiting factor.
+ if (checked_curMaxInstances.isValid()) {
+ curMaxInstances = checked_curMaxInstances.value();
+ }
+
+ maxInstances = std::min(maxInstances, curMaxInstances);
}
}
diff --git a/content/html/content/public/HTMLAudioElement.h b/content/html/content/public/HTMLAudioElement.h
index 4beac8c8fa00..ba06f2f899de 100644
--- a/content/html/content/public/HTMLAudioElement.h
+++ b/content/html/content/public/HTMLAudioElement.h
@@ -7,7 +7,6 @@
#define mozilla_dom_HTMLAudioElement_h
#include "mozilla/Attributes.h"
-#include "nsIDOMHTMLAudioElement.h"
#include "mozilla/dom/HTMLMediaElement.h"
#include "mozilla/dom/TypedArray.h"
@@ -17,21 +16,18 @@ typedef uint16_t nsMediaReadyState;
namespace mozilla {
namespace dom {
-class HTMLAudioElement MOZ_FINAL : public HTMLMediaElement,
- public nsIDOMHTMLAudioElement
+class HTMLAudioElement MOZ_FINAL : public HTMLMediaElement
{
public:
- HTMLAudioElement(already_AddRefed& aNodeInfo);
+ typedef mozilla::dom::NodeInfo NodeInfo;
- // nsISupports
- NS_DECL_ISUPPORTS_INHERITED
+ HTMLAudioElement(already_AddRefed& aNodeInfo);
// nsIDOMHTMLMediaElement
using HTMLMediaElement::GetPaused;
- NS_FORWARD_NSIDOMHTMLMEDIAELEMENT(HTMLMediaElement::)
- virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const;
- virtual nsresult SetAcceptHeader(nsIHttpChannel* aChannel);
+ virtual nsresult Clone(NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
+ virtual nsresult SetAcceptHeader(nsIHttpChannel* aChannel) MOZ_OVERRIDE;
virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE { return this; }
diff --git a/content/html/content/public/HTMLMediaElement.h b/content/html/content/public/HTMLMediaElement.h
index cde2717092c5..9bb7726a4232 100644
--- a/content/html/content/public/HTMLMediaElement.h
+++ b/content/html/content/public/HTMLMediaElement.h
@@ -72,6 +72,7 @@ class AudioTrackList;
class VideoTrackList;
class HTMLMediaElement : public nsGenericHTMLElement,
+ public nsIDOMHTMLMediaElement,
public nsIObserver,
public MediaDecoderOwner,
public nsIAudioChannelAgentCallback
diff --git a/content/html/content/public/HTMLVideoElement.h b/content/html/content/public/HTMLVideoElement.h
index 80843332ce0d..c62aad859414 100644
--- a/content/html/content/public/HTMLVideoElement.h
+++ b/content/html/content/public/HTMLVideoElement.h
@@ -8,7 +8,6 @@
#define mozilla_dom_HTMLVideoElement_h
#include "mozilla/Attributes.h"
-#include "nsIDOMHTMLVideoElement.h"
#include "mozilla/dom/HTMLMediaElement.h"
namespace mozilla {
@@ -17,41 +16,38 @@ namespace dom {
class WakeLock;
class VideoPlaybackQuality;
-class HTMLVideoElement MOZ_FINAL : public HTMLMediaElement,
- public nsIDOMHTMLVideoElement
+class HTMLVideoElement MOZ_FINAL : public HTMLMediaElement
{
public:
- HTMLVideoElement(already_AddRefed& aNodeInfo);
+ typedef mozilla::dom::NodeInfo NodeInfo;
+
+ HTMLVideoElement(already_AddRefed& aNodeInfo);
NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLVideoElement, video)
- // nsISupports
- NS_DECL_ISUPPORTS_INHERITED
-
- // nsIDOMHTMLMediaElement
using HTMLMediaElement::GetPaused;
- NS_FORWARD_NSIDOMHTMLMEDIAELEMENT(HTMLMediaElement::)
- // nsIDOMHTMLVideoElement
- NS_DECL_NSIDOMHTMLVIDEOELEMENT
+ NS_IMETHOD_(bool) IsVideo() MOZ_OVERRIDE {
+ return true;
+ }
virtual bool ParseAttribute(int32_t aNamespaceID,
- nsIAtom* aAttribute,
- const nsAString& aValue,
- nsAttrValue& aResult);
+ nsIAtom* aAttribute,
+ const nsAString& aValue,
+ nsAttrValue& aResult) MOZ_OVERRIDE;
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const MOZ_OVERRIDE;
static void Init();
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const MOZ_OVERRIDE;
- virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
+ virtual nsresult Clone(NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
// Set size with the current video frame's height and width.
// If there is no video frame, returns NS_ERROR_FAILURE.
nsresult GetVideoSize(nsIntSize* size);
- virtual nsresult SetAcceptHeader(nsIHttpChannel* aChannel);
+ virtual nsresult SetAcceptHeader(nsIHttpChannel* aChannel) MOZ_OVERRIDE;
// WebIDL
@@ -85,7 +81,10 @@ public:
return mMediaSize.height == -1 ? 0 : mMediaSize.height;
}
- // XPCOM GetPoster is OK
+ void GetPoster(nsAString& aValue)
+ {
+ GetURIAttr(nsGkAtoms::poster, nullptr, aValue);
+ }
void SetPoster(const nsAString& aValue, ErrorResult& aRv)
{
SetHTMLAttr(nsGkAtoms::poster, aValue, aRv);
diff --git a/content/html/content/src/HTMLAnchorElement.cpp b/content/html/content/src/HTMLAnchorElement.cpp
index 860fd5d8113e..ceb36a23ed70 100644
--- a/content/html/content/src/HTMLAnchorElement.cpp
+++ b/content/html/content/src/HTMLAnchorElement.cpp
@@ -300,13 +300,17 @@ HTMLAnchorElement::RelList()
NS_IMETHODIMP \
HTMLAnchorElement::Get##_part(nsAString& a##_part) \
{ \
- Link::Get##_part(a##_part); \
+ ErrorResult rv; \
+ Link::Get##_part(a##_part, rv); \
+ MOZ_ASSERT(!rv.Failed()); \
return NS_OK; \
} \
NS_IMETHODIMP \
HTMLAnchorElement::Set##_part(const nsAString& a##_part) \
{ \
- Link::Set##_part(a##_part); \
+ ErrorResult rv; \
+ Link::Set##_part(a##_part, rv); \
+ MOZ_ASSERT(!rv.Failed()); \
return NS_OK; \
}
diff --git a/content/html/content/src/HTMLAnchorElement.h b/content/html/content/src/HTMLAnchorElement.h
index 5d86f52ff704..9a0d4e24d947 100644
--- a/content/html/content/src/HTMLAnchorElement.h
+++ b/content/html/content/src/HTMLAnchorElement.h
@@ -86,7 +86,7 @@ public:
virtual bool HasDeferredDNSPrefetchRequest();
// WebIDL API
- void GetHref(nsString& aValue)
+ void GetHref(nsAString& aValue, ErrorResult& rv)
{
GetHTMLURIAttr(nsGkAtoms::href, aValue);
}
@@ -145,11 +145,32 @@ public:
// Link::GetOrigin is OK for us
+ using Link::GetProtocol;
+ using Link::SetProtocol;
+
// Link::GetUsername is OK for us
// Link::SetUsername is OK for us
- // Link::Getpassword is OK for us
- // Link::Setpassword is OK for us
+ // Link::GetPassword is OK for us
+ // Link::SetPassword is OK for us
+
+ using Link::GetHost;
+ using Link::SetHost;
+
+ using Link::GetHostname;
+ using Link::SetHostname;
+
+ using Link::GetPort;
+ using Link::SetPort;
+
+ using Link::GetPathname;
+ using Link::SetPathname;
+
+ using Link::GetSearch;
+ using Link::SetSearch;
+
+ using Link::GetHash;
+ using Link::SetHash;
// The XPCOM URI decomposition attributes are fine for us
void GetCoords(nsString& aValue)
@@ -192,9 +213,9 @@ public:
{
SetHTMLAttr(nsGkAtoms::shape, aValue, rv);
}
- void Stringify(nsAString& aResult)
+ void Stringify(nsAString& aResult, ErrorResult& aError)
{
- GetHref(aResult);
+ GetHref(aResult, aError);
}
protected:
diff --git a/content/html/content/src/HTMLAreaElement.cpp b/content/html/content/src/HTMLAreaElement.cpp
index f1bd40cc8a6e..94927087c9b8 100644
--- a/content/html/content/src/HTMLAreaElement.cpp
+++ b/content/html/content/src/HTMLAreaElement.cpp
@@ -202,13 +202,17 @@ HTMLAreaElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
NS_IMETHODIMP \
HTMLAreaElement::Get##_part(nsAString& a##_part) \
{ \
- Link::Get##_part(a##_part); \
+ ErrorResult rv; \
+ Link::Get##_part(a##_part, rv); \
+ MOZ_ASSERT(!rv.Failed()); \
return NS_OK; \
} \
NS_IMETHODIMP \
HTMLAreaElement::Set##_part(const nsAString& a##_part) \
{ \
- Link::Set##_part(a##_part); \
+ ErrorResult rv; \
+ Link::Set##_part(a##_part, rv); \
+ MOZ_ASSERT(!rv.Failed()); \
return NS_OK; \
}
diff --git a/content/html/content/src/HTMLAreaElement.h b/content/html/content/src/HTMLAreaElement.h
index 0c1f53ecca33..fb6502a93972 100644
--- a/content/html/content/src/HTMLAreaElement.h
+++ b/content/html/content/src/HTMLAreaElement.h
@@ -90,7 +90,10 @@ public:
SetHTMLAttr(nsGkAtoms::shape, aShape, aError);
}
- // The XPCOM GetHref is OK for us
+ void GetHref(nsAString& aHref, ErrorResult& aError)
+ {
+ aError = GetHref(aHref);
+ }
void SetHref(const nsAString& aHref, ErrorResult& aError)
{
aError = SetHref(aHref);
@@ -124,10 +127,11 @@ public:
SetHTMLAttr(nsGkAtoms::rel, aRel, aError);
}
nsDOMTokenList* RelList();
+
// The Link::GetOrigin is OK for us
- // The XPCOM GetProtocol is OK for us
- // The XPCOM SetProtocol is OK for us
+ using Link::GetProtocol;
+ using Link::SetProtocol;
// The Link::GetUsername is OK for us
// The Link::SetUsername is OK for us
@@ -135,23 +139,23 @@ public:
// The Link::GetPassword is OK for us
// The Link::SetPassword is OK for us
- // The XPCOM GetHost is OK for us
- // The XPCOM SetHost is OK for us
+ using Link::GetHost;
+ using Link::SetHost;
- // The XPCOM GetHostname is OK for us
- // The XPCOM SetHostname is OK for us
+ using Link::GetHostname;
+ using Link::SetHostname;
- // The XPCOM GetPort is OK for us
- // The XPCOM SetPort is OK for us
+ using Link::GetPort;
+ using Link::SetPort;
- // The XPCOM GetPathname is OK for us
- // The XPCOM SetPathname is OK for us
+ using Link::GetPathname;
+ using Link::SetPathname;
- // The XPCOM GetSearch is OK for us
- // The XPCOM SetSearch is OK for us
+ using Link::GetSearch;
+ using Link::SetSearch;
- // The XPCOM GetHash is OK for us
- // The XPCOM SetHash is OK for us
+ using Link::GetHash;
+ using Link::SetHash;
// The Link::GetSearchParams is OK for us
// The Link::SetSearchParams is OK for us
@@ -166,9 +170,9 @@ public:
SetHTMLBoolAttr(nsGkAtoms::nohref, aValue, aError);
}
- void Stringify(nsAString& aResult)
+ void Stringify(nsAString& aResult, ErrorResult& aError)
{
- GetHref(aResult);
+ GetHref(aResult, aError);
}
protected:
diff --git a/content/html/content/src/HTMLAudioElement.cpp b/content/html/content/src/HTMLAudioElement.cpp
index b4babceaad01..ee8a2168a7b2 100644
--- a/content/html/content/src/HTMLAudioElement.cpp
+++ b/content/html/content/src/HTMLAudioElement.cpp
@@ -7,7 +7,6 @@
#include "mozilla/dom/HTMLAudioElement.h"
#include "mozilla/dom/HTMLAudioElementBinding.h"
#include "nsError.h"
-#include "nsIDOMHTMLAudioElement.h"
#include "nsGenericHTMLElement.h"
#include "nsGkAtoms.h"
#include "nsIDocument.h"
@@ -29,13 +28,10 @@ namespace dom {
extern bool IsAudioAPIEnabled();
-NS_IMPL_ISUPPORTS_INHERITED(HTMLAudioElement, HTMLMediaElement,
- nsIDOMHTMLMediaElement, nsIDOMHTMLAudioElement)
-
NS_IMPL_ELEMENT_CLONE(HTMLAudioElement)
-HTMLAudioElement::HTMLAudioElement(already_AddRefed& aNodeInfo)
+HTMLAudioElement::HTMLAudioElement(already_AddRefed& aNodeInfo)
: HTMLMediaElement(aNodeInfo)
{
}
@@ -44,7 +40,6 @@ HTMLAudioElement::~HTMLAudioElement()
{
}
-
already_AddRefed
HTMLAudioElement::Audio(const GlobalObject& aGlobal,
const Optional& aSrc,
diff --git a/content/html/content/src/HTMLMediaElement.cpp b/content/html/content/src/HTMLMediaElement.cpp
index d76e1cdfe44b..497ed0fb505c 100644
--- a/content/html/content/src/HTMLMediaElement.cpp
+++ b/content/html/content/src/HTMLMediaElement.cpp
@@ -48,7 +48,6 @@
#include "nsICategoryManager.h"
#include "MediaResource.h"
-#include "nsIDOMHTMLVideoElement.h"
#include "nsIContentPolicy.h"
#include "nsContentPolicyUtils.h"
#include "nsCrossSiteListenerProxy.h"
@@ -458,6 +457,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTMLE
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLMediaElement)
+ NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLMediaElement)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_ENTRY(nsIAudioChannelAgentCallback)
NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement)
@@ -488,6 +488,12 @@ HTMLMediaElement::SetMozAudioChannelType(const nsAString& aValue)
return SetAttrHelper(nsGkAtoms::mozaudiochannel, aValue);
}
+NS_IMETHODIMP_(bool)
+HTMLMediaElement::IsVideo()
+{
+ return false;
+}
+
already_AddRefed
HTMLMediaElement::GetMozSrcObject() const
{
@@ -1820,8 +1826,7 @@ HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded)
// holistically.
uint8_t hints = 0;
if (Preferences::GetBool("media.capturestream_hints.enabled")) {
- nsCOMPtr video = do_QueryObject(this);
- if (video && GetVideoFrameContainer()) {
+ if (IsVideo() && GetVideoFrameContainer()) {
hints = DOMMediaStream::HINT_CONTENTS_VIDEO | DOMMediaStream::HINT_CONTENTS_AUDIO;
} else {
hints = DOMMediaStream::HINT_CONTENTS_AUDIO;
@@ -2763,11 +2768,14 @@ public:
}
aGraph->DispatchToMainThreadAfterStreamStateUpdate(event.forget());
}
- virtual void NotifyFinished(MediaStreamGraph* aGraph) MOZ_OVERRIDE
+ virtual void NotifyEvent(MediaStreamGraph* aGraph,
+ MediaStreamListener::MediaStreamGraphEvent event) MOZ_OVERRIDE
{
- nsCOMPtr event =
- NS_NewRunnableMethod(this, &StreamListener::DoNotifyFinished);
- aGraph->DispatchToMainThreadAfterStreamStateUpdate(event.forget());
+ if (event == EVENT_FINISHED) {
+ nsCOMPtr event =
+ NS_NewRunnableMethod(this, &StreamListener::DoNotifyFinished);
+ aGraph->DispatchToMainThreadAfterStreamStateUpdate(event.forget());
+ }
}
virtual void NotifyHasCurrentData(MediaStreamGraph* aGraph) MOZ_OVERRIDE
{
@@ -3275,9 +3283,9 @@ VideoFrameContainer* HTMLMediaElement::GetVideoFrameContainer()
return mVideoFrameContainer;
// Only video frames need an image container.
- nsCOMPtr video = do_QueryObject(this);
- if (!video)
+ if (!IsVideo()) {
return nullptr;
+ }
mVideoFrameContainer =
new VideoFrameContainer(this, LayerManager::CreateAsynchronousImageContainer());
@@ -3884,9 +3892,8 @@ void HTMLMediaElement::UpdateAudioChannelPlayingState()
if (!mAudioChannelAgent) {
return;
}
- nsCOMPtr video = do_QueryObject(this);
// Use a weak ref so the audio channel agent can't leak |this|.
- if (AudioChannel::Normal == mAudioChannel && video) {
+ if (AudioChannel::Normal == mAudioChannel && IsVideo()) {
mAudioChannelAgent->InitWithVideo(OwnerDoc()->GetWindow(),
static_cast(mAudioChannel),
this, true);
diff --git a/content/html/content/src/HTMLMetaElement.cpp b/content/html/content/src/HTMLMetaElement.cpp
index 0364d2612ef0..0d8f0f4ab7c4 100644
--- a/content/html/content/src/HTMLMetaElement.cpp
+++ b/content/html/content/src/HTMLMetaElement.cpp
@@ -48,6 +48,21 @@ HTMLMetaElement::SetItemValueText(const nsAString& aValue)
}
+nsresult
+HTMLMetaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+ const nsAttrValue* aValue, bool aNotify)
+{
+ if (aNameSpaceID == kNameSpaceID_None) {
+ if (aName == nsGkAtoms::content) {
+ nsIDocument *document = GetCurrentDoc();
+ CreateAndDispatchEvent(document, NS_LITERAL_STRING("DOMMetaChanged"));
+ }
+ }
+
+ return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
+ aNotify);
+}
+
nsresult
HTMLMetaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
diff --git a/content/html/content/src/HTMLMetaElement.h b/content/html/content/src/HTMLMetaElement.h
index 71598df5530a..d5ea4b8d4829 100644
--- a/content/html/content/src/HTMLMetaElement.h
+++ b/content/html/content/src/HTMLMetaElement.h
@@ -30,6 +30,10 @@ public:
bool aCompileEventHandlers) MOZ_OVERRIDE;
virtual void UnbindFromTree(bool aDeep = true,
bool aNullParent = true) MOZ_OVERRIDE;
+
+ virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+ const nsAttrValue* aValue, bool aNotify) MOZ_OVERRIDE;
+
void CreateAndDispatchEvent(nsIDocument* aDoc, const nsAString& aEventName);
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
diff --git a/content/html/content/src/HTMLVideoElement.cpp b/content/html/content/src/HTMLVideoElement.cpp
index 1b52e68a97c3..4705e6de6074 100644
--- a/content/html/content/src/HTMLVideoElement.cpp
+++ b/content/html/content/src/HTMLVideoElement.cpp
@@ -4,7 +4,6 @@
* 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 "nsIDOMHTMLVideoElement.h"
#include "nsIDOMHTMLSourceElement.h"
#include "mozilla/dom/HTMLVideoElement.h"
#include "mozilla/dom/HTMLVideoElementBinding.h"
@@ -40,31 +39,9 @@ namespace dom {
static bool sVideoStatsEnabled;
-NS_IMPL_ISUPPORTS_INHERITED(HTMLVideoElement, HTMLMediaElement,
- nsIDOMHTMLMediaElement, nsIDOMHTMLVideoElement)
-
NS_IMPL_ELEMENT_CLONE(HTMLVideoElement)
-// nsIDOMHTMLVideoElement
-NS_IMPL_INT_ATTR(HTMLVideoElement, Width, width)
-NS_IMPL_INT_ATTR(HTMLVideoElement, Height, height)
-
-// nsIDOMHTMLVideoElement
-/* readonly attribute unsigned long videoWidth; */
-NS_IMETHODIMP HTMLVideoElement::GetVideoWidth(uint32_t *aVideoWidth)
-{
- *aVideoWidth = VideoWidth();
- return NS_OK;
-}
-
-/* readonly attribute unsigned long videoHeight; */
-NS_IMETHODIMP HTMLVideoElement::GetVideoHeight(uint32_t *aVideoHeight)
-{
- *aVideoHeight = VideoHeight();
- return NS_OK;
-}
-
-HTMLVideoElement::HTMLVideoElement(already_AddRefed& aNodeInfo)
+HTMLVideoElement::HTMLVideoElement(already_AddRefed& aNodeInfo)
: HTMLMediaElement(aNodeInfo)
{
}
@@ -149,8 +126,6 @@ nsresult HTMLVideoElement::SetAcceptHeader(nsIHttpChannel* aChannel)
false);
}
-NS_IMPL_URI_ATTR(HTMLVideoElement, Poster, poster)
-
uint32_t HTMLVideoElement::MozParsedFrames() const
{
MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread.");
@@ -160,12 +135,6 @@ uint32_t HTMLVideoElement::MozParsedFrames() const
return mDecoder ? mDecoder->GetFrameStatistics().GetParsedFrames() : 0;
}
-NS_IMETHODIMP HTMLVideoElement::GetMozParsedFrames(uint32_t *aMozParsedFrames)
-{
- *aMozParsedFrames = MozParsedFrames();
- return NS_OK;
-}
-
uint32_t HTMLVideoElement::MozDecodedFrames() const
{
MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread.");
@@ -175,12 +144,6 @@ uint32_t HTMLVideoElement::MozDecodedFrames() const
return mDecoder ? mDecoder->GetFrameStatistics().GetDecodedFrames() : 0;
}
-NS_IMETHODIMP HTMLVideoElement::GetMozDecodedFrames(uint32_t *aMozDecodedFrames)
-{
- *aMozDecodedFrames = MozDecodedFrames();
- return NS_OK;
-}
-
uint32_t HTMLVideoElement::MozPresentedFrames() const
{
MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread.");
@@ -190,12 +153,6 @@ uint32_t HTMLVideoElement::MozPresentedFrames() const
return mDecoder ? mDecoder->GetFrameStatistics().GetPresentedFrames() : 0;
}
-NS_IMETHODIMP HTMLVideoElement::GetMozPresentedFrames(uint32_t *aMozPresentedFrames)
-{
- *aMozPresentedFrames = MozPresentedFrames();
- return NS_OK;
-}
-
uint32_t HTMLVideoElement::MozPaintedFrames()
{
MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread.");
@@ -206,12 +163,6 @@ uint32_t HTMLVideoElement::MozPaintedFrames()
return container ? container->GetPaintCount() : 0;
}
-NS_IMETHODIMP HTMLVideoElement::GetMozPaintedFrames(uint32_t *aMozPaintedFrames)
-{
- *aMozPaintedFrames = MozPaintedFrames();
- return NS_OK;
-}
-
double HTMLVideoElement::MozFrameDelay()
{
MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread.");
@@ -219,23 +170,12 @@ double HTMLVideoElement::MozFrameDelay()
return container ? container->GetFrameDelay() : 0;
}
-NS_IMETHODIMP HTMLVideoElement::GetMozFrameDelay(double *aMozFrameDelay) {
- *aMozFrameDelay = MozFrameDelay();
- return NS_OK;
-}
-
-/* readonly attribute bool mozHasAudio */
bool HTMLVideoElement::MozHasAudio() const
{
MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread.");
return mHasAudio;
}
-NS_IMETHODIMP HTMLVideoElement::GetMozHasAudio(bool *aHasAudio) {
- *aHasAudio = MozHasAudio();
- return NS_OK;
-}
-
JSObject*
HTMLVideoElement::WrapNode(JSContext* aCx)
{
@@ -324,5 +264,6 @@ HTMLVideoElement::Init()
{
Preferences::AddBoolVarCache(&sVideoStatsEnabled, "media.video_stats.enabled");
}
+
} // namespace dom
} // namespace mozilla
diff --git a/content/html/content/src/nsHTMLDNSPrefetch.cpp b/content/html/content/src/nsHTMLDNSPrefetch.cpp
index 6090d9f8c775..a9dc8c15bc4f 100644
--- a/content/html/content/src/nsHTMLDNSPrefetch.cpp
+++ b/content/html/content/src/nsHTMLDNSPrefetch.cpp
@@ -175,7 +175,8 @@ nsHTMLDNSPrefetch::CancelPrefetch(Link *aElement,
return NS_ERROR_NOT_AVAILABLE;
nsAutoString hostname;
- aElement->GetHostname(hostname);
+ ErrorResult rv;
+ aElement->GetHostname(hostname, rv);
return CancelPrefetch(hostname, flags, aReason);
}
diff --git a/content/html/document/src/nsHTMLDocument.h b/content/html/document/src/nsHTMLDocument.h
index 15a5fffb33dd..5a64797f06ab 100644
--- a/content/html/document/src/nsHTMLDocument.h
+++ b/content/html/document/src/nsHTMLDocument.h
@@ -240,7 +240,7 @@ public:
// The XPCOM CaptureEvents works fine for us.
// The XPCOM ReleaseEvents works fine for us.
// We're picking up GetLocation from Document
- already_AddRefed GetLocation() const {
+ already_AddRefed GetLocation() const {
return nsIDocument::GetLocation();
}
diff --git a/content/media/MediaDecoder.cpp b/content/media/MediaDecoder.cpp
index 6da23d43a930..6d57184cb64f 100644
--- a/content/media/MediaDecoder.cpp
+++ b/content/media/MediaDecoder.cpp
@@ -261,13 +261,15 @@ MediaDecoder::DecodedStreamGraphListener::DoNotifyFinished()
}
void
-MediaDecoder::DecodedStreamGraphListener::NotifyFinished(MediaStreamGraph* aGraph)
+MediaDecoder::DecodedStreamGraphListener::NotifyEvent(MediaStreamGraph* aGraph,
+ MediaStreamListener::MediaStreamGraphEvent event)
{
- nsCOMPtr event =
- NS_NewRunnableMethod(this, &DecodedStreamGraphListener::DoNotifyFinished);
- aGraph->DispatchToMainThreadAfterStreamStateUpdate(event.forget());
+ if (event == EVENT_FINISHED) {
+ nsCOMPtr event =
+ NS_NewRunnableMethod(this, &DecodedStreamGraphListener::DoNotifyFinished);
+ aGraph->DispatchToMainThreadAfterStreamStateUpdate(event.forget());
+ }
}
-
void MediaDecoder::DestroyDecodedStream()
{
MOZ_ASSERT(NS_IsMainThread());
diff --git a/content/media/MediaDecoder.h b/content/media/MediaDecoder.h
index 3a5247e5b044..795cadc6a092 100755
--- a/content/media/MediaDecoder.h
+++ b/content/media/MediaDecoder.h
@@ -440,7 +440,8 @@ public:
public:
DecodedStreamGraphListener(MediaStream* aStream, DecodedStreamData* aData);
virtual void NotifyOutput(MediaStreamGraph* aGraph, GraphTime aCurrentTime) MOZ_OVERRIDE;
- virtual void NotifyFinished(MediaStreamGraph* aGraph) MOZ_OVERRIDE;
+ virtual void NotifyEvent(MediaStreamGraph* aGraph,
+ MediaStreamListener::MediaStreamGraphEvent event) MOZ_OVERRIDE;
void DoNotifyFinished();
diff --git a/content/media/MediaStreamGraph.cpp b/content/media/MediaStreamGraph.cpp
index 34a7cb4aa546..d918a7116180 100644
--- a/content/media/MediaStreamGraph.cpp
+++ b/content/media/MediaStreamGraph.cpp
@@ -397,7 +397,7 @@ MediaStreamGraphImpl::UpdateCurrentTime()
GraphTime blockedTime = 0;
GraphTime t = prevCurrentTime;
// include |nextCurrentTime| to ensure NotifyBlockingChanged() is called
- // before NotifyFinished() when |nextCurrentTime == stream end time|
+ // before NotifyEvent(this, EVENT_FINISHED) when |nextCurrentTime == stream end time|
while (t <= nextCurrentTime) {
GraphTime end;
bool blocked = stream->mBlocked.GetAt(t, &end);
@@ -460,7 +460,7 @@ MediaStreamGraphImpl::UpdateCurrentTime()
SetStreamOrderDirty();
for (uint32_t j = 0; j < stream->mListeners.Length(); ++j) {
MediaStreamListener* l = stream->mListeners[j];
- l->NotifyFinished(this);
+ l->NotifyEvent(this, MediaStreamListener::EVENT_FINISHED);
}
}
}
@@ -1933,7 +1933,7 @@ MediaStream::RemoveAllListenersImpl()
{
for (int32_t i = mListeners.Length() - 1; i >= 0; --i) {
nsRefPtr listener = mListeners[i].forget();
- listener->NotifyRemoved(GraphImpl());
+ listener->NotifyEvent(GraphImpl(), MediaStreamListener::EVENT_REMOVED);
}
mListeners.Clear();
}
@@ -2111,7 +2111,7 @@ MediaStream::AddListenerImpl(already_AddRefed aListener)
listener->NotifyBlockingChanged(GraphImpl(),
mNotifiedBlocked ? MediaStreamListener::BLOCKED : MediaStreamListener::UNBLOCKED);
if (mNotifiedFinished) {
- listener->NotifyFinished(GraphImpl());
+ listener->NotifyEvent(GraphImpl(), MediaStreamListener::EVENT_FINISHED);
}
if (mNotifiedHasCurrentData) {
listener->NotifyHasCurrentData(GraphImpl());
@@ -2140,7 +2140,7 @@ MediaStream::RemoveListenerImpl(MediaStreamListener* aListener)
// wouldn't need this if we could do it in the opposite order
nsRefPtr listener(aListener);
mListeners.RemoveElement(aListener);
- listener->NotifyRemoved(GraphImpl());
+ listener->NotifyEvent(GraphImpl(), MediaStreamListener::EVENT_REMOVED);
}
void
@@ -2367,15 +2367,37 @@ SourceMediaStream::NotifyDirectConsumers(TrackData *aTrack,
void
SourceMediaStream::AddDirectListener(MediaStreamDirectListener* aListener)
{
- MutexAutoLock lock(mMutex);
- mDirectListeners.AppendElement(aListener);
+ bool wasEmpty;
+ {
+ MutexAutoLock lock(mMutex);
+ wasEmpty = mDirectListeners.IsEmpty();
+ mDirectListeners.AppendElement(aListener);
+ }
+
+ if (wasEmpty) {
+ for (uint32_t j = 0; j < mListeners.Length(); ++j) {
+ MediaStreamListener* l = mListeners[j];
+ l->NotifyEvent(GraphImpl(), MediaStreamListener::EVENT_HAS_DIRECT_LISTENERS);
+ }
+ }
}
void
SourceMediaStream::RemoveDirectListener(MediaStreamDirectListener* aListener)
{
- MutexAutoLock lock(mMutex);
- mDirectListeners.RemoveElement(aListener);
+ bool isEmpty;
+ {
+ MutexAutoLock lock(mMutex);
+ mDirectListeners.RemoveElement(aListener);
+ isEmpty = mDirectListeners.IsEmpty();
+ }
+
+ if (isEmpty) {
+ for (uint32_t j = 0; j < mListeners.Length(); ++j) {
+ MediaStreamListener* l = mListeners[j];
+ l->NotifyEvent(GraphImpl(), MediaStreamListener::EVENT_HAS_NO_DIRECT_LISTENERS);
+ }
+ }
}
bool
@@ -2455,7 +2477,7 @@ SourceMediaStream::EndAllTrackAndFinish()
data->mCommands |= TRACK_END;
}
FinishWithLockHeld();
- // we will call NotifyFinished() to let GetUserMedia know
+ // we will call NotifyEvent() to let GetUserMedia know
}
TrackTicks
diff --git a/content/media/MediaStreamGraph.h b/content/media/MediaStreamGraph.h
index 90e09b2f3b5a..57156f8bc3f7 100644
--- a/content/media/MediaStreamGraph.h
+++ b/content/media/MediaStreamGraph.h
@@ -111,6 +111,7 @@ public:
CONSUMED,
NOT_CONSUMED
};
+
/**
* Notify that the stream is hooked up and we'd like to start or stop receiving
* data on it. Only fires on SourceMediaStreams.
@@ -157,16 +158,17 @@ public:
*/
virtual void NotifyOutput(MediaStreamGraph* aGraph, GraphTime aCurrentTime) {}
- /**
- * Notify that the stream finished.
- */
- virtual void NotifyFinished(MediaStreamGraph* aGraph) {}
+ enum MediaStreamGraphEvent {
+ EVENT_FINISHED,
+ EVENT_REMOVED,
+ EVENT_HAS_DIRECT_LISTENERS, // transition from no direct listeners
+ EVENT_HAS_NO_DIRECT_LISTENERS, // transition to no direct listeners
+ };
/**
- * Notify that your listener has been removed, either due to RemoveListener(),
- * or due to the stream being destroyed. You will get no further notifications.
+ * Notify that an event has occurred on the Stream
*/
- virtual void NotifyRemoved(MediaStreamGraph* aGraph) {}
+ virtual void NotifyEvent(MediaStreamGraph* aGraph, MediaStreamGraphEvent aEvent) {}
enum {
TRACK_EVENT_CREATED = 0x01,
diff --git a/content/media/encoder/MediaEncoder.cpp b/content/media/encoder/MediaEncoder.cpp
index 919465653c2d..aabc15982162 100644
--- a/content/media/encoder/MediaEncoder.cpp
+++ b/content/media/encoder/MediaEncoder.cpp
@@ -64,17 +64,17 @@ MediaEncoder::NotifyQueuedTrackChanges(MediaStreamGraph* aGraph,
}
void
-MediaEncoder::NotifyRemoved(MediaStreamGraph* aGraph)
+MediaEncoder::NotifyEvent(MediaStreamGraph* aGraph,
+ MediaStreamListener::MediaStreamGraphEvent event)
{
// In case that MediaEncoder does not receive a TRACK_EVENT_ENDED event.
LOG(PR_LOG_DEBUG, ("NotifyRemoved in [MediaEncoder]."));
if (mAudioEncoder) {
- mAudioEncoder->NotifyRemoved(aGraph);
+ mAudioEncoder->NotifyEvent(aGraph, event);
}
if (mVideoEncoder) {
- mVideoEncoder->NotifyRemoved(aGraph);
+ mVideoEncoder->NotifyEvent(aGraph, event);
}
-
}
/* static */
diff --git a/content/media/encoder/MediaEncoder.h b/content/media/encoder/MediaEncoder.h
index 78acdcfff6a1..d67242f8f969 100644
--- a/content/media/encoder/MediaEncoder.h
+++ b/content/media/encoder/MediaEncoder.h
@@ -80,12 +80,13 @@ public :
TrackRate aTrackRate,
TrackTicks aTrackOffset,
uint32_t aTrackEvents,
- const MediaSegment& aQueuedMedia);
+ const MediaSegment& aQueuedMedia) MOZ_OVERRIDE;
/**
* Notified the stream is being removed.
*/
- virtual void NotifyRemoved(MediaStreamGraph* aGraph);
+ virtual void NotifyEvent(MediaStreamGraph* aGraph,
+ MediaStreamListener::MediaStreamGraphEvent event) MOZ_OVERRIDE;
/**
* Creates an encoder with a given MIME type. Returns null if we are unable
diff --git a/content/media/encoder/TrackEncoder.h b/content/media/encoder/TrackEncoder.h
index 7ed2e4f3d568..41921282dbf4 100644
--- a/content/media/encoder/TrackEncoder.h
+++ b/content/media/encoder/TrackEncoder.h
@@ -13,11 +13,10 @@
#include "StreamBuffer.h"
#include "TrackMetadataBase.h"
#include "VideoSegment.h"
+#include "MediaStreamGraph.h"
namespace mozilla {
-class MediaStreamGraph;
-
/**
* Base class of AudioTrackEncoder and VideoTrackEncoder. Lifetimes managed by
* MediaEncoder. Most methods can only be called on the MediaEncoder's thread,
@@ -49,7 +48,13 @@ public:
* Notified by the same callback of MediaEncoder when it has been removed from
* MediaStreamGraph. Called on the MediaStreamGraph thread.
*/
- void NotifyRemoved(MediaStreamGraph* aGraph) { NotifyEndOfStream(); }
+ void NotifyEvent(MediaStreamGraph* aGraph,
+ MediaStreamListener::MediaStreamGraphEvent event)
+ {
+ if (event == MediaStreamListener::MediaStreamGraphEvent::EVENT_REMOVED) {
+ NotifyEndOfStream();
+ }
+ }
/**
* Creates and sets up meta data for a specific codec, called on the worker
diff --git a/content/media/gmp/GMPParent.cpp b/content/media/gmp/GMPParent.cpp
index 2e3a5d228f46..12969ff4c4a8 100644
--- a/content/media/gmp/GMPParent.cpp
+++ b/content/media/gmp/GMPParent.cpp
@@ -13,6 +13,7 @@
#include "nsThreadUtils.h"
#include "nsIRunnable.h"
#include "mozIGeckoMediaPluginService.h"
+#include "mozilla/unused.h"
namespace mozilla {
namespace gmp {
@@ -126,7 +127,8 @@ GMPParent::VideoDecoderDestroyed(GMPVideoDecoderParent* aDecoder)
{
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
- MOZ_ALWAYS_TRUE(mVideoDecoders.RemoveElement(aDecoder));
+ // If the constructor fails, we'll get called before it's added
+ unused << NS_WARN_IF(!mVideoDecoders.RemoveElement(aDecoder));
// Recv__delete__ is on the stack, don't potentially destroy the top-level actor
// until after this has completed.
@@ -139,7 +141,8 @@ GMPParent::VideoEncoderDestroyed(GMPVideoEncoderParent* aEncoder)
{
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
- MOZ_ALWAYS_TRUE(mVideoEncoders.RemoveElement(aEncoder));
+ // If the constructor fails, we'll get called before it's added
+ unused << NS_WARN_IF(!mVideoEncoders.RemoveElement(aEncoder));
// Recv__delete__ is on the stack, don't potentially destroy the top-level actor
// until after this has completed.
diff --git a/content/media/omx/MediaCodecProxy.cpp b/content/media/omx/MediaCodecProxy.cpp
new file mode 100644
index 000000000000..82e73bc671d9
--- /dev/null
+++ b/content/media/omx/MediaCodecProxy.cpp
@@ -0,0 +1,392 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "MediaCodecProxy.h"
+
+#include
+
+#include
+
+namespace android {
+
+sp
+MediaCodecProxy::CreateByType(sp aLooper,
+ const char *aMime,
+ bool aEncoder,
+ bool aAsync,
+ wp aListener)
+{
+ sp codec = new MediaCodecProxy(aLooper, aMime, aEncoder, aAsync, aListener);
+ if ((!aAsync && codec->allocated()) || codec->requestResource()) {
+ return codec;
+ }
+ return nullptr;
+}
+
+MediaCodecProxy::MediaCodecProxy(sp aLooper,
+ const char *aMime,
+ bool aEncoder,
+ bool aAsync,
+ wp aListener)
+ : mCodecLooper(aLooper)
+ , mCodecMime(aMime)
+ , mCodecEncoder(aEncoder)
+ , mListener(aListener)
+{
+ MOZ_ASSERT(mCodecLooper != nullptr, "ALooper should not be nullptr.");
+ if (aAsync) {
+ mResourceHandler = new MediaResourceHandler(this);
+ } else {
+ allocateCodec();
+ }
+}
+
+MediaCodecProxy::~MediaCodecProxy()
+{
+ releaseCodec();
+
+ // Complete all pending Binder ipc transactions
+ IPCThreadState::self()->flushCommands();
+
+ cancelResource();
+}
+
+bool
+MediaCodecProxy::requestResource()
+{
+ if (mResourceHandler == nullptr) {
+ return false;
+ }
+
+ if (strncasecmp(mCodecMime.get(), "video/", 6) == 0) {
+ mResourceHandler->requestResource(mCodecEncoder
+ ? IMediaResourceManagerService::HW_VIDEO_ENCODER
+ : IMediaResourceManagerService::HW_VIDEO_DECODER);
+ } else if (strncasecmp(mCodecMime.get(), "audio/", 6) == 0) {
+ mResourceHandler->requestResource(mCodecEncoder
+ ? IMediaResourceManagerService::HW_AUDIO_ENCODER
+ : IMediaResourceManagerService::HW_AUDIO_DECODER);
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+void
+MediaCodecProxy::cancelResource()
+{
+ if (mResourceHandler == nullptr) {
+ return;
+ }
+
+ mResourceHandler->cancelResource();
+}
+
+bool
+MediaCodecProxy::allocateCodec()
+{
+ if (mCodecLooper == nullptr) {
+ return false;
+ }
+
+ // Write Lock for mCodec
+ RWLock::AutoWLock awl(mCodecLock);
+
+ // Create MediaCodec
+ mCodec = MediaCodec::CreateByType(mCodecLooper, mCodecMime.get(), mCodecEncoder);
+ if (mCodec == nullptr) {
+ return false;
+ }
+
+ return true;
+}
+
+void
+MediaCodecProxy::releaseCodec()
+{
+ wp codec;
+
+ {
+ // Write Lock for mCodec
+ RWLock::AutoWLock awl(mCodecLock);
+
+ codec = mCodec;
+
+ // Release MediaCodec
+ if (mCodec != nullptr) {
+ mCodec->release();
+ mCodec = nullptr;
+ }
+ }
+
+ while (codec.promote() != nullptr) {
+ // this value come from stagefright's AwesomePlayer.
+ usleep(1000);
+ }
+}
+
+bool
+MediaCodecProxy::allocated() const
+{
+ // Read Lock for mCodec
+ RWLock::AutoRLock arl(mCodecLock);
+
+ return mCodec != nullptr;
+}
+
+status_t
+MediaCodecProxy::configure(const sp &aFormat,
+ const sp &aNativeWindow,
+ const sp &aCrypto,
+ uint32_t aFlags)
+{
+ // Read Lock for mCodec
+ RWLock::AutoRLock arl(mCodecLock);
+
+ if (mCodec == nullptr) {
+ return NO_INIT;
+ }
+ return mCodec->configure(aFormat, aNativeWindow, aCrypto, aFlags);
+}
+
+status_t
+MediaCodecProxy::start()
+{
+ // Read Lock for mCodec
+ RWLock::AutoRLock arl(mCodecLock);
+
+ if (mCodec == nullptr) {
+ return NO_INIT;
+ }
+ return mCodec->start();
+}
+
+status_t
+MediaCodecProxy::stop()
+{
+ // Read Lock for mCodec
+ RWLock::AutoRLock arl(mCodecLock);
+
+ if (mCodec == nullptr) {
+ return NO_INIT;
+ }
+ return mCodec->stop();
+}
+
+status_t
+MediaCodecProxy::release()
+{
+ // Read Lock for mCodec
+ RWLock::AutoRLock arl(mCodecLock);
+
+ if (mCodec == nullptr) {
+ return NO_INIT;
+ }
+ return mCodec->release();
+}
+
+status_t
+MediaCodecProxy::flush()
+{
+ // Read Lock for mCodec
+ RWLock::AutoRLock arl(mCodecLock);
+
+ if (mCodec == nullptr) {
+ return NO_INIT;
+ }
+ return mCodec->flush();
+}
+
+status_t
+MediaCodecProxy::queueInputBuffer(size_t aIndex,
+ size_t aOffset,
+ size_t aSize,
+ int64_t aPresentationTimeUs,
+ uint32_t aFlags,
+ AString *aErrorDetailMessage)
+{
+ // Read Lock for mCodec
+ RWLock::AutoRLock arl(mCodecLock);
+
+ if (mCodec == nullptr) {
+ return NO_INIT;
+ }
+ return mCodec->queueInputBuffer(aIndex, aOffset, aSize,
+ aPresentationTimeUs, aFlags, aErrorDetailMessage);
+}
+
+status_t
+MediaCodecProxy::queueSecureInputBuffer(size_t aIndex,
+ size_t aOffset,
+ const CryptoPlugin::SubSample *aSubSamples,
+ size_t aNumSubSamples,
+ const uint8_t aKey[16],
+ const uint8_t aIV[16],
+ CryptoPlugin::Mode aMode,
+ int64_t aPresentationTimeUs,
+ uint32_t aFlags,
+ AString *aErrorDetailMessage)
+{
+ // Read Lock for mCodec
+ RWLock::AutoRLock arl(mCodecLock);
+
+ if (mCodec == nullptr) {
+ return NO_INIT;
+ }
+ return mCodec->queueSecureInputBuffer(aIndex, aOffset,
+ aSubSamples, aNumSubSamples, aKey, aIV, aMode,
+ aPresentationTimeUs, aFlags, aErrorDetailMessage);
+}
+
+status_t
+MediaCodecProxy::dequeueInputBuffer(size_t *aIndex,
+ int64_t aTimeoutUs)
+{
+ // Read Lock for mCodec
+ RWLock::AutoRLock arl(mCodecLock);
+
+ if (mCodec == nullptr) {
+ return NO_INIT;
+ }
+ return mCodec->dequeueInputBuffer(aIndex, aTimeoutUs);
+}
+
+status_t
+MediaCodecProxy::dequeueOutputBuffer(size_t *aIndex,
+ size_t *aOffset,
+ size_t *aSize,
+ int64_t *aPresentationTimeUs,
+ uint32_t *aFlags,
+ int64_t aTimeoutUs)
+{
+ // Read Lock for mCodec
+ RWLock::AutoRLock arl(mCodecLock);
+
+ if (mCodec == nullptr) {
+ return NO_INIT;
+ }
+ return mCodec->dequeueOutputBuffer(aIndex, aOffset, aSize,
+ aPresentationTimeUs, aFlags, aTimeoutUs);
+}
+
+status_t
+MediaCodecProxy::renderOutputBufferAndRelease(size_t aIndex)
+{
+ // Read Lock for mCodec
+ RWLock::AutoRLock arl(mCodecLock);
+
+ if (mCodec == nullptr) {
+ return NO_INIT;
+ }
+ return mCodec->renderOutputBufferAndRelease(aIndex);
+}
+
+status_t
+MediaCodecProxy::releaseOutputBuffer(size_t aIndex)
+{
+ // Read Lock for mCodec
+ RWLock::AutoRLock arl(mCodecLock);
+
+ if (mCodec == nullptr) {
+ return NO_INIT;
+ }
+ return mCodec->releaseOutputBuffer(aIndex);
+}
+
+status_t
+MediaCodecProxy::signalEndOfInputStream()
+{
+ // Read Lock for mCodec
+ RWLock::AutoRLock arl(mCodecLock);
+
+ if (mCodec == nullptr) {
+ return NO_INIT;
+ }
+ return mCodec->signalEndOfInputStream();
+}
+
+status_t
+MediaCodecProxy::getOutputFormat(sp *aFormat) const
+{
+ // Read Lock for mCodec
+ RWLock::AutoRLock arl(mCodecLock);
+
+ if (mCodec == nullptr) {
+ return NO_INIT;
+ }
+ return mCodec->getOutputFormat(aFormat);
+}
+
+status_t
+MediaCodecProxy::getInputBuffers(Vector> *aBuffers) const
+{
+ // Read Lock for mCodec
+ RWLock::AutoRLock arl(mCodecLock);
+
+ if (mCodec == nullptr) {
+ return NO_INIT;
+ }
+ return mCodec->getInputBuffers(aBuffers);
+}
+
+status_t
+MediaCodecProxy::getOutputBuffers(Vector> *aBuffers) const
+{
+ // Read Lock for mCodec
+ RWLock::AutoRLock arl(mCodecLock);
+
+ if (mCodec == nullptr) {
+ return NO_INIT;
+ }
+ return mCodec->getOutputBuffers(aBuffers);
+}
+
+void
+MediaCodecProxy::requestActivityNotification(const sp &aNotify)
+{
+ // Read Lock for mCodec
+ RWLock::AutoRLock arl(mCodecLock);
+
+ if (mCodec == nullptr) {
+ return;
+ }
+ mCodec->requestActivityNotification(aNotify);
+}
+
+// Called on a Binder thread
+void
+MediaCodecProxy::resourceReserved()
+{
+ // Create MediaCodec
+ releaseCodec();
+ if (!allocateCodec()) {
+ cancelResource();
+ return;
+ }
+
+ // Notification
+ sp listener = mListener.promote();
+ if (listener != nullptr) {
+ listener->codecReserved();
+ }
+}
+
+// Called on a Binder thread
+void
+MediaCodecProxy::resourceCanceled()
+{
+ // Release MediaCodec
+ releaseCodec();
+
+ // Notification
+ sp listener = mListener.promote();
+ if (listener != nullptr) {
+ listener->codecCanceled();
+ }
+}
+
+} // namespace android
diff --git a/content/media/omx/MediaCodecProxy.h b/content/media/omx/MediaCodecProxy.h
new file mode 100644
index 000000000000..3b4435b24664
--- /dev/null
+++ b/content/media/omx/MediaCodecProxy.h
@@ -0,0 +1,156 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MEDIA_CODEC_PROXY_H
+#define MEDIA_CODEC_PROXY_H
+
+#include
+
+#include
+#include
+
+#include "MediaResourceHandler.h"
+
+namespace android {
+
+class MediaCodecProxy : public MediaResourceHandler::ResourceListener
+{
+public:
+ /* Codec resource notification listener.
+ * All functions are called on the Binder thread.
+ */
+ struct CodecResourceListener : public virtual RefBase {
+ /* The codec resource is reserved and can be granted.
+ * The client can allocate the requested resource.
+ */
+ virtual void codecReserved() = 0;
+ /* The codec resource is not reserved any more.
+ * The client should release the resource as soon as possible if the
+ * resource is still being held.
+ */
+ virtual void codecCanceled() = 0;
+ };
+
+ // Check whether MediaCodec has been allocated.
+ bool allocated() const;
+
+ // Static MediaCodec methods
+ // Only support MediaCodec::CreateByType()
+ static sp CreateByType(sp aLooper,
+ const char *aMime,
+ bool aEncoder,
+ bool aAsync=false,
+ wp aListener=nullptr);
+
+ // MediaCodec methods
+ status_t configure(const sp &aFormat,
+ const sp &aNativeWindow,
+ const sp &aCrypto,
+ uint32_t aFlags);
+
+ status_t start();
+
+ status_t stop();
+
+ status_t release();
+
+ status_t flush();
+
+ status_t queueInputBuffer(size_t aIndex,
+ size_t aOffset,
+ size_t aSize,
+ int64_t aPresentationTimeUs,
+ uint32_t aFlags,
+ AString *aErrorDetailMessage=nullptr);
+
+ status_t queueSecureInputBuffer(size_t aIndex,
+ size_t aOffset,
+ const CryptoPlugin::SubSample *aSubSamples,
+ size_t aNumSubSamples,
+ const uint8_t aKey[16],
+ const uint8_t aIV[16],
+ CryptoPlugin::Mode aMode,
+ int64_t aPresentationTimeUs,
+ uint32_t aFlags,
+ AString *aErrorDetailMessage=nullptr);
+
+ status_t dequeueInputBuffer(size_t *aIndex,
+ int64_t aTimeoutUs=INT64_C(0));
+
+ status_t dequeueOutputBuffer(size_t *aIndex,
+ size_t *aOffset,
+ size_t *aSize,
+ int64_t *aPresentationTimeUs,
+ uint32_t *aFlags,
+ int64_t aTimeoutUs=INT64_C(0));
+
+ status_t renderOutputBufferAndRelease(size_t aIndex);
+
+ status_t releaseOutputBuffer(size_t aIndex);
+
+ status_t signalEndOfInputStream();
+
+ status_t getOutputFormat(sp *aFormat) const;
+
+ status_t getInputBuffers(Vector> *aBuffers) const;
+
+ status_t getOutputBuffers(Vector> *aBuffers) const;
+
+ // Notification will be posted once there "is something to do", i.e.
+ // an input/output buffer has become available, a format change is
+ // pending, an error is pending.
+ void requestActivityNotification(const sp &aNotify);
+
+protected:
+ virtual ~MediaCodecProxy();
+
+ // MediaResourceHandler::EventListener::resourceReserved()
+ virtual void resourceReserved();
+ // MediaResourceHandler::EventListener::resourceCanceled()
+ virtual void resourceCanceled();
+
+private:
+ // Forbidden
+ MediaCodecProxy() MOZ_DELETE;
+ MediaCodecProxy(const MediaCodecProxy &) MOZ_DELETE;
+ const MediaCodecProxy &operator=(const MediaCodecProxy &) MOZ_DELETE;
+
+ // Constructor for MediaCodecProxy::CreateByType
+ MediaCodecProxy(sp aLooper,
+ const char *aMime,
+ bool aEncoder,
+ bool aAsync,
+ wp aListener);
+
+ // Request Resource
+ bool requestResource();
+ // Cancel Resource
+ void cancelResource();
+
+ // Allocate Codec Resource
+ bool allocateCodec();
+ // Release Codec Resource
+ void releaseCodec();
+
+ // MediaCodec Parameter
+ sp mCodecLooper;
+ nsCString mCodecMime;
+ bool mCodecEncoder;
+
+ // Codec Resource Notification Listener
+ wp mListener;
+
+ // Media Resource Management
+ sp mResourceHandler;
+
+ // MediaCodec instance
+ mutable RWLock mCodecLock;
+ sp mCodec;
+};
+
+} // namespace android
+
+#endif // MEDIA_CODEC_PROXY_H
diff --git a/content/media/omx/mediaresourcemanager/IMediaResourceManagerService.h b/content/media/omx/mediaresourcemanager/IMediaResourceManagerService.h
index 24dc190975b5..3bd8d1bbf5b0 100644
--- a/content/media/omx/mediaresourcemanager/IMediaResourceManagerService.h
+++ b/content/media/omx/mediaresourcemanager/IMediaResourceManagerService.h
@@ -27,6 +27,7 @@ public:
HW_VIDEO_DECODER = 0,
HW_AUDIO_DECODER, // Not supported currently.
HW_VIDEO_ENCODER,
+ HW_AUDIO_ENCODER, // Not supported currently.
HW_CAMERA, // Not supported currently.
NUM_OF_RESOURCE_TYPES,
INVALID_RESOURCE_TYPE = -1
diff --git a/content/media/omx/mediaresourcemanager/MediaResourceHandler.cpp b/content/media/omx/mediaresourcemanager/MediaResourceHandler.cpp
new file mode 100644
index 000000000000..26c5c2ee44b8
--- /dev/null
+++ b/content/media/omx/mediaresourcemanager/MediaResourceHandler.cpp
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "MediaResourceHandler.h"
+
+#include "mozilla/NullPtr.h"
+
+namespace android {
+
+MediaResourceHandler::MediaResourceHandler(const wp &aListener)
+ : mListener(aListener)
+ , mState(MediaResourceManagerClient::CLIENT_STATE_WAIT_FOR_RESOURCE)
+ , mType(IMediaResourceManagerService::INVALID_RESOURCE_TYPE)
+{
+}
+
+MediaResourceHandler::~MediaResourceHandler()
+{
+ cancelResource();
+}
+
+bool
+MediaResourceHandler::requestResource(IMediaResourceManagerService::ResourceType aType)
+{
+ Mutex::Autolock al(mLock);
+
+ if (mClient != nullptr && mService != nullptr) {
+ return false;
+ }
+
+ sp client = new MediaResourceManagerClient(this);
+ sp service = client->getMediaResourceManagerService();
+
+ if (service == nullptr) {
+ return false;
+ }
+
+ if (service->requestMediaResource(client, (int)aType, true) != OK) {
+ return false;
+ }
+
+ mClient = client;
+ mService = service;
+ mType = aType;
+
+ return true;
+}
+
+void
+MediaResourceHandler::cancelResource()
+{
+ Mutex::Autolock al(mLock);
+
+ if (mClient != nullptr && mService != nullptr) {
+ mService->cancelClient(mClient, (int)mType);
+ }
+
+ mClient = nullptr;
+ mService = nullptr;
+}
+
+// Called on a Binder thread
+void
+MediaResourceHandler::statusChanged(int aEvent)
+{
+ sp listener;
+
+ Mutex::Autolock autoLock(mLock);
+
+ MediaResourceManagerClient::State state = (MediaResourceManagerClient::State)aEvent;
+ if (state == mState) {
+ return;
+ }
+
+ mState = state;
+
+ listener = mListener.promote();
+ if (listener == nullptr) {
+ return;
+ }
+
+ if (mState == MediaResourceManagerClient::CLIENT_STATE_RESOURCE_ASSIGNED) {
+ listener->resourceReserved();
+ } else {
+ listener->resourceCanceled();
+ }
+}
+
+} // namespace android
diff --git a/content/media/omx/mediaresourcemanager/MediaResourceHandler.h b/content/media/omx/mediaresourcemanager/MediaResourceHandler.h
new file mode 100644
index 000000000000..04268f7e7504
--- /dev/null
+++ b/content/media/omx/mediaresourcemanager/MediaResourceHandler.h
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MEDIA_RESOURCE_HANDLER_H
+#define MEDIA_RESOURCE_HANDLER_H
+
+#include
+
+#include
+
+#include "MediaResourceManagerClient.h"
+
+namespace android {
+
+class MediaResourceHandler : public MediaResourceManagerClient::EventListener
+{
+public:
+ /* Resource notification listener.
+ * All functions are called on the Binder thread.
+ */
+ struct ResourceListener : public virtual RefBase {
+ /* The resource is reserved and can be granted.
+ * The client can allocate the requested resource.
+ */
+ virtual void resourceReserved() = 0;
+ /* The resource is not reserved any more.
+ * The client should release the resource as soon as possible if the
+ * resource is still being held.
+ */
+ virtual void resourceCanceled() = 0;
+ };
+
+ MediaResourceHandler(const wp &aListener);
+
+ virtual ~MediaResourceHandler();
+
+ // Request Resource
+ bool requestResource(IMediaResourceManagerService::ResourceType aType);
+ // Cancel Resource
+ void cancelResource();
+
+protected:
+ // MediaResourceManagerClient::EventListener::statusChanged()
+ virtual void statusChanged(int event);
+
+private:
+ // Forbidden
+ MediaResourceHandler() MOZ_DELETE;
+ MediaResourceHandler(const MediaResourceHandler &) MOZ_DELETE;
+ const MediaResourceHandler &operator=(const MediaResourceHandler &) MOZ_DELETE;
+
+ // Resource Notification Listener
+ wp mListener;
+
+ // Resource Management
+ Mutex mLock;
+ MediaResourceManagerClient::State mState;
+ sp mClient;
+ sp mService;
+ IMediaResourceManagerService::ResourceType mType;
+};
+
+} // namespace android
+
+#endif // MEDIA_RESOURCE_HANDLER_H
diff --git a/content/media/omx/mediaresourcemanager/moz.build b/content/media/omx/mediaresourcemanager/moz.build
index 024ccf809cb0..e9d6841e9918 100644
--- a/content/media/omx/mediaresourcemanager/moz.build
+++ b/content/media/omx/mediaresourcemanager/moz.build
@@ -16,6 +16,7 @@ SOURCES += [
'IMediaResourceManagerClient.cpp',
'IMediaResourceManagerDeathNotifier.cpp',
'IMediaResourceManagerService.cpp',
+ 'MediaResourceHandler.cpp',
'MediaResourceManagerClient.cpp',
'MediaResourceManagerService.cpp',
]
diff --git a/content/media/omx/moz.build b/content/media/omx/moz.build
index c577820d49f7..2dd24ba7ea82 100755
--- a/content/media/omx/moz.build
+++ b/content/media/omx/moz.build
@@ -47,6 +47,14 @@ if 'rtsp' in CONFIG['NECKO_PROTOCOLS']:
'RtspOmxReader.cpp',
]
+if int(CONFIG['ANDROID_VERSION']) >= 16:
+ EXPORTS += [
+ 'MediaCodecProxy.h',
+ ]
+ SOURCES += [
+ 'MediaCodecProxy.cpp',
+ ]
+
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'gklayout'
diff --git a/content/media/webrtc/MediaEngine.h b/content/media/webrtc/MediaEngine.h
index b03ca2f4ce31..241c6b4dfabe 100644
--- a/content/media/webrtc/MediaEngine.h
+++ b/content/media/webrtc/MediaEngine.h
@@ -86,6 +86,9 @@ public:
* immediately after. */
virtual nsresult Start(SourceMediaStream*, TrackID) = 0;
+ /* tell the source if there are any direct listeners attached */
+ virtual void SetDirectListeners(bool) = 0;
+
/* Take a snapshot from this source. In the case of video this is a single
* image, and for audio, it is a snippet lasting aDuration milliseconds. The
* duration argument is ignored for a MediaEngineVideoSource.
diff --git a/content/media/webrtc/MediaEngineDefault.h b/content/media/webrtc/MediaEngineDefault.h
index e64895ae2259..0cfd70e8a15f 100644
--- a/content/media/webrtc/MediaEngineDefault.h
+++ b/content/media/webrtc/MediaEngineDefault.h
@@ -45,6 +45,7 @@ public:
virtual nsresult Deallocate();
virtual nsresult Start(SourceMediaStream*, TrackID);
virtual nsresult Stop(SourceMediaStream*, TrackID);
+ virtual void SetDirectListeners(bool aHasDirectListeners) {};
virtual nsresult Snapshot(uint32_t aDuration, nsIDOMFile** aFile);
virtual nsresult Config(bool aEchoOn, uint32_t aEcho,
bool aAgcOn, uint32_t aAGC,
@@ -100,6 +101,7 @@ public:
virtual nsresult Deallocate();
virtual nsresult Start(SourceMediaStream*, TrackID);
virtual nsresult Stop(SourceMediaStream*, TrackID);
+ virtual void SetDirectListeners(bool aHasDirectListeners) {};
virtual nsresult Snapshot(uint32_t aDuration, nsIDOMFile** aFile);
virtual nsresult Config(bool aEchoOn, uint32_t aEcho,
bool aAgcOn, uint32_t aAGC,
diff --git a/content/media/webrtc/MediaEngineTabVideoSource.h b/content/media/webrtc/MediaEngineTabVideoSource.h
index 94de33193c1d..4cab38cf3a53 100644
--- a/content/media/webrtc/MediaEngineTabVideoSource.h
+++ b/content/media/webrtc/MediaEngineTabVideoSource.h
@@ -24,6 +24,7 @@ class MediaEngineTabVideoSource : public MediaEngineVideoSource, nsIDOMEventList
const mozilla::MediaEnginePrefs&);
virtual nsresult Deallocate();
virtual nsresult Start(mozilla::SourceMediaStream*, mozilla::TrackID);
+ virtual void SetDirectListeners(bool aHasDirectListeners) {};
virtual nsresult Snapshot(uint32_t, nsIDOMFile**);
virtual void NotifyPull(mozilla::MediaStreamGraph*, mozilla::SourceMediaStream*, mozilla::TrackID, mozilla::StreamTime, mozilla::TrackTicks&);
virtual nsresult Stop(mozilla::SourceMediaStream*, mozilla::TrackID);
diff --git a/content/media/webrtc/MediaEngineWebRTC.h b/content/media/webrtc/MediaEngineWebRTC.h
index a323de9cd24d..79e1fae12c36 100644
--- a/content/media/webrtc/MediaEngineWebRTC.h
+++ b/content/media/webrtc/MediaEngineWebRTC.h
@@ -104,6 +104,7 @@ public:
, mMonitor("WebRTCCamera.Monitor")
, mWidth(0)
, mHeight(0)
+ , mHasDirectListeners(false)
, mInitDone(false)
, mInSnapshotMode(false)
, mSnapshotPath(nullptr)
@@ -131,6 +132,7 @@ public:
, mMonitor("WebRTCCamera.Monitor")
, mWidth(0)
, mHeight(0)
+ , mHasDirectListeners(false)
, mInitDone(false)
, mInSnapshotMode(false)
, mSnapshotPath(nullptr) {
@@ -147,6 +149,7 @@ public:
virtual nsresult Deallocate();
virtual nsresult Start(SourceMediaStream*, TrackID);
virtual nsresult Stop(SourceMediaStream*, TrackID);
+ virtual void SetDirectListeners(bool aHasListeners);
virtual nsresult Snapshot(uint32_t aDuration, nsIDOMFile** aFile);
virtual nsresult Config(bool aEchoOn, uint32_t aEcho,
bool aAgcOn, uint32_t aAGC,
@@ -245,6 +248,7 @@ private:
int mWidth, mHeight;
nsRefPtr mImage;
nsRefPtr mImageContainer;
+ bool mHasDirectListeners;
nsTArray mSources; // When this goes empty, we shut down HW
@@ -297,6 +301,7 @@ public:
virtual nsresult Deallocate();
virtual nsresult Start(SourceMediaStream*, TrackID);
virtual nsresult Stop(SourceMediaStream*, TrackID);
+ virtual void SetDirectListeners(bool aHasDirectListeners) {};
virtual nsresult Snapshot(uint32_t aDuration, nsIDOMFile** aFile);
virtual nsresult Config(bool aEchoOn, uint32_t aEcho,
bool aAgcOn, uint32_t aAGC,
diff --git a/content/media/webrtc/MediaEngineWebRTCVideo.cpp b/content/media/webrtc/MediaEngineWebRTCVideo.cpp
index bc343459f6c3..353572301e23 100644
--- a/content/media/webrtc/MediaEngineWebRTCVideo.cpp
+++ b/content/media/webrtc/MediaEngineWebRTCVideo.cpp
@@ -584,6 +584,13 @@ MediaEngineWebRTCVideoSource::Stop(SourceMediaStream *aSource, TrackID aID)
return NS_OK;
}
+void
+MediaEngineWebRTCVideoSource::SetDirectListeners(bool aHasDirectListeners)
+{
+ LOG((__FUNCTION__));
+ mHasDirectListeners = aHasDirectListeners;
+}
+
nsresult
MediaEngineWebRTCVideoSource::Snapshot(uint32_t aDuration, nsIDOMFile** aFile)
{
@@ -734,16 +741,19 @@ GetRotateAmount(ScreenOrientation aScreen, int aCameraMountAngle, bool aBackCame
}
// undefine to remove on-the-fly rotation support
-// #define DYNAMIC_GUM_ROTATION
+#define DYNAMIC_GUM_ROTATION
void
MediaEngineWebRTCVideoSource::Notify(const hal::ScreenConfiguration& aConfiguration) {
#ifdef DYNAMIC_GUM_ROTATION
- MonitorAutoLock enter(mMonitor);
- mRotation = GetRotateAmount(aConfiguration.orientation(), mCameraAngle, mBackCamera);
+ if (mHasDirectListeners) {
+ // aka hooked to PeerConnection
+ MonitorAutoLock enter(mMonitor);
+ mRotation = GetRotateAmount(aConfiguration.orientation(), mCameraAngle, mBackCamera);
- LOG(("*** New orientation: %d (Camera %d Back %d MountAngle: %d)",
- mRotation, mCaptureIndex, mBackCamera, mCameraAngle));
+ LOG(("*** New orientation: %d (Camera %d Back %d MountAngle: %d)",
+ mRotation, mCaptureIndex, mBackCamera, mCameraAngle));
+ }
#endif
}
diff --git a/content/media/webspeech/recognition/SpeechStreamListener.cpp b/content/media/webspeech/recognition/SpeechStreamListener.cpp
index 1f2aba605e77..d8f77c3bb9e4 100644
--- a/content/media/webspeech/recognition/SpeechStreamListener.cpp
+++ b/content/media/webspeech/recognition/SpeechStreamListener.cpp
@@ -84,7 +84,8 @@ SpeechStreamListener::ConvertAndDispatchAudioChunk(int aDuration, float aVolume,
}
void
-SpeechStreamListener::NotifyFinished(MediaStreamGraph* aGraph)
+SpeechStreamListener::NotifyEvent(MediaStreamGraph* aGraph,
+ MediaStreamListener::MediaStreamGraphEvent event)
{
// TODO dispatch SpeechEnd event so services can be informed
}
diff --git a/content/media/webspeech/recognition/SpeechStreamListener.h b/content/media/webspeech/recognition/SpeechStreamListener.h
index e6550a1ef1fa..ca6a11fcda67 100644
--- a/content/media/webspeech/recognition/SpeechStreamListener.h
+++ b/content/media/webspeech/recognition/SpeechStreamListener.h
@@ -30,7 +30,8 @@ public:
uint32_t aTrackEvents,
const MediaSegment& aQueuedMedia) MOZ_OVERRIDE;
- void NotifyFinished(MediaStreamGraph* aGraph) MOZ_OVERRIDE;
+ void NotifyEvent(MediaStreamGraph* aGraph,
+ MediaStreamListener::MediaStreamGraphEvent event) MOZ_OVERRIDE;
private:
template
diff --git a/content/media/webspeech/synth/nsSpeechTask.cpp b/content/media/webspeech/synth/nsSpeechTask.cpp
index e75a7df38825..2a2b5e6477e4 100644
--- a/content/media/webspeech/synth/nsSpeechTask.cpp
+++ b/content/media/webspeech/synth/nsSpeechTask.cpp
@@ -49,11 +49,23 @@ public:
}
}
- virtual void NotifyFinished(MediaStreamGraph* aGraph)
+ virtual void NotifyEvent(MediaStreamGraph* aGraph,
+ MediaStreamListener::MediaStreamGraphEvent event) MOZ_OVERRIDE
{
- nsCOMPtr event =
- NS_NewRunnableMethod(this, &SynthStreamListener::DoNotifyFinished);
- aGraph->DispatchToMainThreadAfterStreamStateUpdate(event.forget());
+ switch (event) {
+ case EVENT_FINISHED:
+ {
+ nsCOMPtr runnable =
+ NS_NewRunnableMethod(this, &SynthStreamListener::DoNotifyFinished);
+ aGraph->DispatchToMainThreadAfterStreamStateUpdate(runnable.forget());
+ }
+ break;
+ case EVENT_REMOVED:
+ mSpeechTask = nullptr;
+ break;
+ default:
+ break;
+ }
}
virtual void NotifyBlockingChanged(MediaStreamGraph* aGraph, Blocking aBlocked)
@@ -66,11 +78,6 @@ public:
}
}
- virtual void NotifyRemoved(MediaStreamGraph* aGraph)
- {
- mSpeechTask = nullptr;
- }
-
private:
// Raw pointer; if we exist, the stream exists,
// and 'mSpeechTask' exclusively owns it and therefor exists as well.
diff --git a/content/svg/content/src/SVGEllipseElement.cpp b/content/svg/content/src/SVGEllipseElement.cpp
index 512193af87c3..488f62345771 100644
--- a/content/svg/content/src/SVGEllipseElement.cpp
+++ b/content/svg/content/src/SVGEllipseElement.cpp
@@ -103,8 +103,7 @@ SVGEllipseElement::ConstructPath(gfxContext *aCtx)
RefPtr builder = dt->CreatePathBuilder(fillRule);
RefPtr path = BuildPath(builder);
if (path) {
- nsRefPtr gfxpath = new gfxPath(path);
- aCtx->SetPath(gfxpath);
+ aCtx->SetPath(path);
}
}
diff --git a/docshell/base/nsIContentViewer.idl b/docshell/base/nsIContentViewer.idl
index 2f7999c258fa..7f3d7c549144 100644
--- a/docshell/base/nsIContentViewer.idl
+++ b/docshell/base/nsIContentViewer.idl
@@ -27,7 +27,7 @@ class nsDOMNavigationTiming;
[ptr] native nsViewPtr(nsView);
[ptr] native nsDOMNavigationTimingPtr(nsDOMNavigationTiming);
-[scriptable, builtinclass, uuid(0cb321bd-5b38-4586-8fcd-d43b366886fb)]
+[scriptable, builtinclass, uuid(f92298b8-4fe3-40d1-aad7-44e704fffd0d)]
interface nsIContentViewer : nsISupports
{
@@ -176,8 +176,10 @@ interface nsIContentViewer : nsISupports
/**
* Returns whether this content viewer is in a hidden state.
+ *
+ * @note Only Gecko internal code should set the attribute!
*/
- readonly attribute boolean isHidden;
+ attribute boolean isHidden;
[noscript] readonly attribute nsIPresShellPtr presShell;
[noscript] readonly attribute nsPresContextPtr presContext;
diff --git a/dom/apps/tests/file_packaged_app.sjs b/dom/apps/tests/file_packaged_app.sjs
index 9e0e44842ea6..90ff6cb133cc 100644
--- a/dom/apps/tests/file_packaged_app.sjs
+++ b/dom/apps/tests/file_packaged_app.sjs
@@ -20,12 +20,23 @@ var gDevUrl = "http://dev.url";
function handleRequest(request, response) {
var query = getQuery(request);
- response.setHeader("Access-Control-Allow-Origin", "*", false);
-
var packageSize = ("packageSize" in query) ? query.packageSize : 0;
var appName = ("appName" in query) ? query.appName : gAppName;
var devName = ("devName" in query) ? query.devName : gDevName;
var devUrl = ("devUrl" in query) ? query.devUrl : gDevUrl;
+ // allowCancel just means deliver the file slowly so we have time to cancel it
+ var allowCancel = "allowCancel" in query;
+ var getPackage = "getPackage" in query;
+ var alreadyDeferred = Number(getState("alreadyDeferred"));
+
+ if (allowCancel && getPackage && !alreadyDeferred) {
+ // Only do this for the actual package delivery.
+ response.processAsync();
+ // And to avoid timer problems, only do this once.
+ setState("alreadyDeferred", "1");
+ }
+
+ response.setHeader("Access-Control-Allow-Origin", "*", false);
// If this is a version update, update state, prepare the manifest,
// the application package and return.
@@ -36,7 +47,8 @@ function handleRequest(request, response) {
var packageName = "test_packaged_app_" + packageVersion + ".zip";
setState("packageName", packageName);
- var packagePath = "/" + gBasePath + "file_packaged_app.sjs?getPackage=" +
+ var packagePath = "/" + gBasePath + "file_packaged_app.sjs?" +
+ (allowCancel?"allowCancel&": "") + "getPackage=" +
packageName;
setState("packagePath", packagePath);
@@ -84,11 +96,19 @@ function handleRequest(request, response) {
response.setHeader("Etag", etag, false);
// Serve the application package corresponding to the requested app version.
- if ("getPackage" in query) {
+ if (getPackage) {
var resource = readFile(packageName, true);
response.setHeader("Content-Type",
"Content-Type: application/java-archive", false);
- response.write(resource);
+ if (allowCancel && !alreadyDeferred) {
+ var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+ timer.initWithCallback(function (aTimer) {
+ response.write(resource);
+ response.finish();
+ }, 3000, Ci.nsITimer.TYPE_ONE_SHOT);
+ } else {
+ response.write(resource);
+ }
return;
}
diff --git a/dom/apps/tests/test_packaged_app_common.js b/dom/apps/tests/test_packaged_app_common.js
index 9a0bddbff4c3..abcdeacf6008 100644
--- a/dom/apps/tests/test_packaged_app_common.js
+++ b/dom/apps/tests/test_packaged_app_common.js
@@ -57,13 +57,17 @@ var PackagedTestHelper = (function PackagedTestHelper() {
finish();
}
- function setAppVersion(aVersion, aCb, aDontUpdatePackage) {
+ function setAppVersion(aVersion, aCb, aDontUpdatePackage, aAllowCancel) {
var xhr = new XMLHttpRequest();
var dontUpdate = "";
+ var allowCancel = "";
if (aDontUpdatePackage) {
dontUpdate = "&dontUpdatePackage=1";
}
- var url = gSJS + "?setVersion=" + aVersion + dontUpdate;
+ if (aAllowCancel) {
+ allowCancel= "&allowCancel=1";
+ }
+ var url = gSJS + "?setVersion=" + aVersion + dontUpdate + allowCancel;
xhr.addEventListener("load", function() {
is(xhr.responseText, "OK", "setAppVersion OK");
aCb();
diff --git a/dom/apps/tests/test_packaged_app_install.html b/dom/apps/tests/test_packaged_app_install.html
index e3f40b7967f1..2b6bc91a7cb8 100644
--- a/dom/apps/tests/test_packaged_app_install.html
+++ b/dom/apps/tests/test_packaged_app_install.html
@@ -34,7 +34,7 @@ function checkAppInstallError(aMiniManifestURL, aExpectedError) {
req.onerror = function(evt) {
var error = evt.target.error.name;
if (error == aExpectedError) {
- ok(true, "Got expected " + aExpectedError);
+ info("Got expected " + aExpectedError);
PackagedTestHelper.next();
} else {
ok(false, "Got unexpected " + error);
@@ -46,7 +46,7 @@ function checkAppInstallError(aMiniManifestURL, aExpectedError) {
function checkUninstallApp(aApp) {
var req = navigator.mozApps.mgmt.uninstall(aApp);
req.onsuccess = function() {
- ok(true, "App uninstalled");
+ info("App uninstalled");
aApp.ondownloadsuccess = null;
aApp.ondownloaderror = null;
aApp.onprogress = null;
@@ -83,11 +83,11 @@ var steps = [
// Set up
SpecialPowers.setAllAppsLaunchable(true);
SpecialPowers.addPermission("webapps-manage", true, document);
- ok(true, "Set up");
+ info("Set up");
PackagedTestHelper.next();
},
function() {
- ok(true, "autoConfirmAppInstall");
+ info("autoConfirmAppInstall");
SpecialPowers.autoConfirmAppInstall(PackagedTestHelper.next);
},
function() {
@@ -96,17 +96,17 @@ var steps = [
function() {
// Bug 927699 - navigator.mozApps.install(url) lets NS_ERROR_FAILURE onto
// the web.
- ok(true, "== TEST == INVALID_URL");
+ info("== TEST == INVALID_URL");
checkAppInstallError("", "INVALID_URL");
},
function() {
// Test network error.
- ok(true, "== TEST == Network error");
+ info("== TEST == Network error");
checkAppInstallError("http://notvalidurl", "NETWORK_ERROR");
},
function() {
// Test wrong mini-manifest content type.
- ok(true, "== TEST == Not valid mini-manifest content type");
+ info("== TEST == Not valid mini-manifest content type");
var miniManifestURL = PackagedTestHelper.gSJS +
"?getManifest=true" +
"&noManifestContentType=true";
@@ -114,7 +114,7 @@ var steps = [
},
function() {
// Test mini-manifest 'size' value is not number. Bug 839435.
- ok(true, "== TEST == Size value is not a number");
+ info("== TEST == Size value is not a number");
var miniManifestURL = PackagedTestHelper.gSJS +
"?getManifest=true" +
"&packageSize=\"NotANumber\"";
@@ -122,7 +122,7 @@ var steps = [
},
function() {
// Test mini-manifest negative 'size' value. Bug 839435.
- ok(true, "== TEST == Negative size value");
+ info("== TEST == Negative size value");
var miniManifestURL = PackagedTestHelper.gSJS +
"?getManifest=true" +
"&packageSize=-1";
@@ -130,7 +130,7 @@ var steps = [
},
function() {
// Test wrong package path
- ok(true, "== TEST == Installing app with wrong package path");
+ info("== TEST == Installing app with wrong package path");
var miniManifestURL = PackagedTestHelper.gSJS +
"?getManifest=true" +
"&wrongPackagePath=true";
@@ -138,7 +138,7 @@ var steps = [
},
function() {
// Test no manifest in zip file.
- ok(true, "== TEST == No manifest in the zip file");
+ info("== TEST == No manifest in the zip file");
var miniManifestURL = PackagedTestHelper.gSJS + "?getManifest=true";
PackagedTestHelper.checkAppDownloadError(miniManifestURL,
"MISSING_MANIFEST", 0, true, true,
@@ -150,7 +150,7 @@ var steps = [
function() {
// Test mini-manifest app name is different from the webapp manifest name.
// Bug 844243.
- ok(true, "== TEST == Mini-manifest app name is different from webapp " +
+ info("== TEST == Mini-manifest app name is different from webapp " +
"manifest name");
var miniManifestURL = PackagedTestHelper.gSJS +
"?getManifest=true" +
@@ -187,11 +187,11 @@ var steps = [
PackagedTestHelper.setAppVersion(2, PackagedTestHelper.next);
},
function() {
- ok(true, "== TEST == Install packaged app");
+ info("== TEST == Install packaged app");
var miniManifestURL = PackagedTestHelper.gSJS +
"?getManifest=true";
navigator.mozApps.mgmt.oninstall = function(evt) {
- ok(true, "Got oninstall event");
+ info("Got oninstall event");
PackagedTestHelper.gApp = evt.application;
PackagedTestHelper.gApp.ondownloaderror = function() {
ok(false, "Download error " +
@@ -199,7 +199,7 @@ var steps = [
PackagedTestHelper.finish();
};
PackagedTestHelper.gApp.ondownloadsuccess = function() {
- ok(true, "App downloaded");
+ info("App downloaded");
var expected = {
name: PackagedTestHelper.gAppName,
manifestURL: miniManifestURL,
@@ -220,11 +220,85 @@ var steps = [
var request = navigator.mozApps.installPackage(miniManifestURL);
request.onerror = PackagedTestHelper.mozAppsError;
request.onsuccess = function() {
- ok(true, "Application installed");
+ info("Application installed");
};
},
function() {
- ok(true, "all done!\n");
+ PackagedTestHelper.setAppVersion(3, PackagedTestHelper.next, false, true);
+ },
+ function() {
+ info("== TEST == Install packaged app with a cancel/resume");
+ var miniManifestURL = PackagedTestHelper.gSJS +
+ "?getManifest=true&allowCancel";
+ navigator.mozApps.mgmt.oninstall = function(evt) {
+ info("Got oninstall event");
+ PackagedTestHelper.gApp = evt.application;
+
+ PackagedTestHelper.gApp.onprogress = function() {
+ // Let's try cancelling and resuming the download later on.
+ PackagedTestHelper.gApp.cancelDownload();
+ // And only do this once.
+ PackagedTestHelper.gApp.onprogress = null;
+ };
+
+ var alreadyCancelled = false;
+ PackagedTestHelper.gApp.ondownloaderror = function() {
+ ok(!alreadyCancelled, "The download should be cancelled only once!");
+ is(PackagedTestHelper.gApp.downloadError.name, "DOWNLOAD_CANCELED",
+ "Download error " + PackagedTestHelper.gApp.downloadError.name);
+ if (!alreadyCancelled) {
+ PackagedTestHelper.gApp.download();
+ alreadyCancelled = true;
+ }
+ };
+
+ PackagedTestHelper.gApp.ondownloadsuccess = function() {
+ info("App downloaded");
+ // We could try also applying the download we just made.
+ var expected = {
+ name: PackagedTestHelper.gAppName,
+ manifestURL: miniManifestURL,
+ installOrigin: PackagedTestHelper.gInstallOrigin,
+ progress: 0,
+ installState: "pending",
+ downloadAvailable: false,
+ downloading: false,
+ downloadSize: 0,
+ size: 0,
+ readyToApplyDownload: true
+ };
+ PackagedTestHelper.checkAppState(PackagedTestHelper.gApp, 3, expected,
+ true, false, function() {});
+ };
+
+ PackagedTestHelper.gApp.ondownloadapplied = function() {
+ info("App download applied.");
+ var expected = {
+ name: PackagedTestHelper.gAppName,
+ manifestURL: miniManifestURL,
+ installOrigin: PackagedTestHelper.gInstallOrigin,
+ progress: 0,
+ installState: "installed",
+ downloadAvailable: false,
+ downloading: false,
+ downloadSize: 0,
+ size: 0,
+ readyToApplyDownload: false
+ };
+ PackagedTestHelper.checkAppState(PackagedTestHelper.gApp, 3, expected,
+ true, false, PackagedTestHelper.next);
+ }
+
+ };
+
+ var request = navigator.mozApps.installPackage(miniManifestURL);
+ request.onerror = PackagedTestHelper.mozAppsError;
+ request.onsuccess = function() {
+ info("Application installed");
+ };
+ },
+ function() {
+ info("all done!\n");
PackagedTestHelper.finish();
}
];
diff --git a/dom/base/URL.cpp b/dom/base/URL.cpp
index d002dd64e030..80fe487d8471 100644
--- a/dom/base/URL.cpp
+++ b/dom/base/URL.cpp
@@ -204,7 +204,7 @@ URL::RevokeObjectURL(const GlobalObject& aGlobal, const nsAString& aURL)
}
void
-URL::GetHref(nsString& aHref) const
+URL::GetHref(nsString& aHref, ErrorResult& aRv) const
{
aHref.Truncate();
@@ -240,13 +240,13 @@ URL::SetHref(const nsAString& aHref, ErrorResult& aRv)
}
void
-URL::GetOrigin(nsString& aOrigin) const
+URL::GetOrigin(nsString& aOrigin, ErrorResult& aRv) const
{
nsContentUtils::GetUTFNonNullOrigin(mURI, aOrigin);
}
void
-URL::GetProtocol(nsString& aProtocol) const
+URL::GetProtocol(nsString& aProtocol, ErrorResult& aRv) const
{
nsCString protocol;
if (NS_SUCCEEDED(mURI->GetScheme(protocol))) {
@@ -258,7 +258,7 @@ URL::GetProtocol(nsString& aProtocol) const
}
void
-URL::SetProtocol(const nsAString& aProtocol)
+URL::SetProtocol(const nsAString& aProtocol, ErrorResult& aRv)
{
nsAString::const_iterator start, end;
aProtocol.BeginReading(start);
@@ -305,37 +305,37 @@ URL::SetProtocol(const nsAString& aProtocol)
}
void
-URL::GetUsername(nsString& aUsername) const
+URL::GetUsername(nsString& aUsername, ErrorResult& aRv) const
{
URL_GETTER(aUsername, GetUsername);
}
void
-URL::SetUsername(const nsAString& aUsername)
+URL::SetUsername(const nsAString& aUsername, ErrorResult& aRv)
{
mURI->SetUsername(NS_ConvertUTF16toUTF8(aUsername));
}
void
-URL::GetPassword(nsString& aPassword) const
+URL::GetPassword(nsString& aPassword, ErrorResult& aRv) const
{
URL_GETTER(aPassword, GetPassword);
}
void
-URL::SetPassword(const nsAString& aPassword)
+URL::SetPassword(const nsAString& aPassword, ErrorResult& aRv)
{
mURI->SetPassword(NS_ConvertUTF16toUTF8(aPassword));
}
void
-URL::GetHost(nsString& aHost) const
+URL::GetHost(nsString& aHost, ErrorResult& aRv) const
{
URL_GETTER(aHost, GetHostPort);
}
void
-URL::SetHost(const nsAString& aHost)
+URL::SetHost(const nsAString& aHost, ErrorResult& aRv)
{
mURI->SetHostPort(NS_ConvertUTF16toUTF8(aHost));
}
@@ -370,7 +370,7 @@ URL::UpdateURLSearchParams()
}
void
-URL::GetHostname(nsString& aHostname) const
+URL::GetHostname(nsString& aHostname, ErrorResult& aRv) const
{
aHostname.Truncate();
nsAutoCString tmp;
@@ -387,7 +387,7 @@ URL::GetHostname(nsString& aHostname) const
}
void
-URL::SetHostname(const nsAString& aHostname)
+URL::SetHostname(const nsAString& aHostname, ErrorResult& aRv)
{
// nsStandardURL returns NS_ERROR_UNEXPECTED for an empty hostname
// The return code is silently ignored
@@ -395,7 +395,7 @@ URL::SetHostname(const nsAString& aHostname)
}
void
-URL::GetPort(nsString& aPort) const
+URL::GetPort(nsString& aPort, ErrorResult& aRv) const
{
aPort.Truncate();
@@ -409,7 +409,7 @@ URL::GetPort(nsString& aPort) const
}
void
-URL::SetPort(const nsAString& aPort)
+URL::SetPort(const nsAString& aPort, ErrorResult& aRv)
{
nsresult rv;
nsAutoString portStr(aPort);
@@ -427,7 +427,7 @@ URL::SetPort(const nsAString& aPort)
}
void
-URL::GetPathname(nsString& aPathname) const
+URL::GetPathname(nsString& aPathname, ErrorResult& aRv) const
{
aPathname.Truncate();
@@ -446,7 +446,7 @@ URL::GetPathname(nsString& aPathname) const
}
void
-URL::SetPathname(const nsAString& aPathname)
+URL::SetPathname(const nsAString& aPathname, ErrorResult& aRv)
{
nsCOMPtr url(do_QueryInterface(mURI));
if (!url) {
@@ -458,7 +458,7 @@ URL::SetPathname(const nsAString& aPathname)
}
void
-URL::GetSearch(nsString& aSearch) const
+URL::GetSearch(nsString& aSearch, ErrorResult& aRv) const
{
aSearch.Truncate();
@@ -477,7 +477,7 @@ URL::GetSearch(nsString& aSearch) const
}
void
-URL::SetSearch(const nsAString& aSearch)
+URL::SetSearch(const nsAString& aSearch, ErrorResult& aRv)
{
SetSearchInternal(aSearch);
UpdateURLSearchParams();
@@ -519,7 +519,7 @@ URL::SetSearchParams(URLSearchParams& aSearchParams)
}
void
-URL::GetHash(nsString& aHash) const
+URL::GetHash(nsString& aHash, ErrorResult& aRv) const
{
aHash.Truncate();
@@ -533,7 +533,7 @@ URL::GetHash(nsString& aHash) const
}
void
-URL::SetHash(const nsAString& aHash)
+URL::SetHash(const nsAString& aHash, ErrorResult& aRv)
{
mURI->SetRef(NS_ConvertUTF16toUTF8(aHash));
}
diff --git a/dom/base/URL.h b/dom/base/URL.h
index 75bb13c93d67..1ed7b85dcbcb 100644
--- a/dom/base/URL.h
+++ b/dom/base/URL.h
@@ -69,55 +69,55 @@ public:
static void RevokeObjectURL(const GlobalObject& aGlobal,
const nsAString& aURL);
- void GetHref(nsString& aHref) const;
+ void GetHref(nsString& aHref, ErrorResult& aRv) const;
void SetHref(const nsAString& aHref, ErrorResult& aRv);
- void GetOrigin(nsString& aOrigin) const;
+ void GetOrigin(nsString& aOrigin, ErrorResult& aRv) const;
- void GetProtocol(nsString& aProtocol) const;
+ void GetProtocol(nsString& aProtocol, ErrorResult& aRv) const;
- void SetProtocol(const nsAString& aProtocol);
+ void SetProtocol(const nsAString& aProtocol, ErrorResult& aRv);
- void GetUsername(nsString& aUsername) const;
+ void GetUsername(nsString& aUsername, ErrorResult& aRv) const;
- void SetUsername(const nsAString& aUsername);
+ void SetUsername(const nsAString& aUsername, ErrorResult& aRv);
- void GetPassword(nsString& aPassword) const;
+ void GetPassword(nsString& aPassword, ErrorResult& aRv) const;
- void SetPassword(const nsAString& aPassword);
+ void SetPassword(const nsAString& aPassword, ErrorResult& aRv);
- void GetHost(nsString& aHost) const;
+ void GetHost(nsString& aHost, ErrorResult& aRv) const;
- void SetHost(const nsAString& aHost);
+ void SetHost(const nsAString& aHost, ErrorResult& aRv);
- void GetHostname(nsString& aHostname) const;
+ void GetHostname(nsString& aHostname, ErrorResult& aRv) const;
- void SetHostname(const nsAString& aHostname);
+ void SetHostname(const nsAString& aHostname, ErrorResult& aRv);
- void GetPort(nsString& aPort) const;
+ void GetPort(nsString& aPort, ErrorResult& aRv) const;
- void SetPort(const nsAString& aPort);
+ void SetPort(const nsAString& aPort, ErrorResult& aRv);
- void GetPathname(nsString& aPathname) const;
+ void GetPathname(nsString& aPathname, ErrorResult& aRv) const;
- void SetPathname(const nsAString& aPathname);
+ void SetPathname(const nsAString& aPathname, ErrorResult& aRv);
- void GetSearch(nsString& aRetval) const;
+ void GetSearch(nsString& aRetval, ErrorResult& aRv) const;
- void SetSearch(const nsAString& aArg);
+ void SetSearch(const nsAString& aArg, ErrorResult& aRv);
URLSearchParams* SearchParams();
void SetSearchParams(URLSearchParams& aSearchParams);
- void GetHash(nsString& aRetval) const;
+ void GetHash(nsString& aRetval, ErrorResult& aRv) const;
- void SetHash(const nsAString& aArg);
+ void SetHash(const nsAString& aArg, ErrorResult& aRv);
- void Stringify(nsString& aRetval) const
+ void Stringify(nsString& aRetval, ErrorResult& aRv) const
{
- GetHref(aRetval);
+ GetHref(aRetval, aRv);
}
// URLSearchParamsObserver
diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp
index a93d8e7b2e8a..f12f6c2fa4eb 100644
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -9649,14 +9649,14 @@ nsGlobalWindow::GetPrivateRoot()
}
-nsIDOMLocation*
+nsLocation*
nsGlobalWindow::GetLocation(ErrorResult& aError)
{
FORWARD_TO_INNER_OR_THROW(GetLocation, (aError), aError, nullptr);
nsIDocShell *docShell = GetDocShell();
if (!mLocation && docShell) {
- mLocation = new nsLocation(docShell);
+ mLocation = new nsLocation(this, docShell);
}
return mLocation;
}
diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h
index 4e70b9d7926f..3fac9cd869b3 100644
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -827,7 +827,7 @@ public:
}
void GetName(nsAString& aName, mozilla::ErrorResult& aError);
void SetName(const nsAString& aName, mozilla::ErrorResult& aError);
- nsIDOMLocation* GetLocation(mozilla::ErrorResult& aError);
+ nsLocation* GetLocation(mozilla::ErrorResult& aError);
nsHistory* GetHistory(mozilla::ErrorResult& aError);
mozilla::dom::BarProp* GetLocationbar(mozilla::ErrorResult& aError);
mozilla::dom::BarProp* GetMenubar(mozilla::ErrorResult& aError);
diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp
index 2144e0d80082..109eb5e2c97e 100644
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -3079,16 +3079,6 @@ mozilla::dom::ShutdownJSEnvironment()
sDidShutdown = true;
}
-class nsJSArgArray;
-
-namespace mozilla {
-template<>
-struct HasDangerousPublicDestructor
-{
- static const bool value = true;
-};
-}
-
// A fast-array class for JS. This class supports both nsIJSScriptArray and
// nsIArray. If it is JS itself providing and consuming this class, all work
// can be done via nsIJSScriptArray, and avoid the conversion of elements
@@ -3099,7 +3089,7 @@ class nsJSArgArray MOZ_FINAL : public nsIJSArgArray {
public:
nsJSArgArray(JSContext *aContext, uint32_t argc, JS::Value *argv,
nsresult *prv);
- ~nsJSArgArray();
+
// nsISupports
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsJSArgArray,
@@ -3114,6 +3104,7 @@ public:
void ReleaseJSObjects();
protected:
+ ~nsJSArgArray();
JSContext *mContext;
JS::Heap *mArgv;
uint32_t mArgc;
@@ -3243,13 +3234,11 @@ nsresult NS_CreateJSArgv(JSContext *aContext, uint32_t argc, void *argv,
nsIJSArgArray **aArray)
{
nsresult rv;
- nsJSArgArray *ret = new nsJSArgArray(aContext, argc,
- static_cast(argv), &rv);
- if (ret == nullptr)
- return NS_ERROR_OUT_OF_MEMORY;
+ nsCOMPtr ret = new nsJSArgArray(aContext, argc,
+ static_cast(argv), &rv);
if (NS_FAILED(rv)) {
- delete ret;
return rv;
}
- return ret->QueryInterface(NS_GET_IID(nsIArray), (void **)aArray);
+ ret.forget(aArray);
+ return NS_OK;
}
diff --git a/dom/base/nsJSTimeoutHandler.cpp b/dom/base/nsJSTimeoutHandler.cpp
index ed387b011cbb..ed38513f36d9 100644
--- a/dom/base/nsJSTimeoutHandler.cpp
+++ b/dom/base/nsJSTimeoutHandler.cpp
@@ -349,8 +349,8 @@ nsJSScriptTimeoutHandler::Init(nsGlobalWindow *aWindow, bool *aIsInterval,
return error.ErrorCode();
}
- mExpr.Append(JS_GetFlatStringChars(expr),
- JS_GetStringLength(JS_FORGET_STRING_FLATNESS(expr)));
+ MOZ_ASSERT(mExpr.IsEmpty());
+ AssignJSFlatString(mExpr, expr);
// Get the calling location.
const char *filename;
diff --git a/dom/base/nsJSUtils.h b/dom/base/nsJSUtils.h
index d78151a21d0c..d9c78a566cfa 100644
--- a/dom/base/nsJSUtils.h
+++ b/dom/base/nsJSUtils.h
@@ -157,6 +157,18 @@ AssignJSString(JSContext *cx, T &dest, JSString *s)
return true;
}
+inline void
+AssignJSFlatString(nsAString &dest, JSFlatString *s)
+{
+ size_t len = js::GetFlatStringLength(s);
+ static_assert(js::MaxStringLength < (1 << 28),
+ "Shouldn't overflow here or in SetCapacity");
+ dest.SetCapacity(len + 1);
+ js::CopyFlatStringChars(dest.BeginWriting(), s, len);
+ dest.BeginWriting()[len] = '\0';
+ dest.SetLength(len);
+}
+
class nsAutoJSString : public nsAutoString
{
public:
diff --git a/dom/base/nsLocation.cpp b/dom/base/nsLocation.cpp
index c939e98c169e..4727e4bdb040 100644
--- a/dom/base/nsLocation.cpp
+++ b/dom/base/nsLocation.cpp
@@ -32,6 +32,10 @@
#include "nsCycleCollectionParticipant.h"
#include "nsNullPrincipal.h"
#include "ScriptSettings.h"
+#include "mozilla/dom/LocationBinding.h"
+
+using namespace mozilla;
+using namespace mozilla::dom;
static nsresult
GetDocumentCharacterSetForURI(const nsAString& aHref, nsACString& aCharset)
@@ -52,13 +56,14 @@ GetDocumentCharacterSetForURI(const nsAString& aHref, nsACString& aCharset)
return NS_OK;
}
-nsLocation::nsLocation(nsIDocShell *aDocShell)
+nsLocation::nsLocation(nsPIDOMWindow* aWindow, nsIDocShell *aDocShell)
+ : mInnerWindow(aWindow)
{
MOZ_ASSERT(aDocShell);
+ MOZ_ASSERT(mInnerWindow->IsInnerWindow());
+ SetIsDOMBinding();
mDocShell = do_GetWeakReference(aDocShell);
- nsCOMPtr outer = aDocShell->GetWindow();
- mOuter = do_GetWeakReference(outer);
}
nsLocation::~nsLocation()
@@ -75,7 +80,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsLocation)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Location)
NS_INTERFACE_MAP_END
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsLocation)
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsLocation, mInnerWindow)
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsLocation)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsLocation)
@@ -729,6 +734,102 @@ nsLocation::SetProtocol(const nsAString& aProtocol)
return SetURI(uri);
}
+void
+nsLocation::GetUsername(nsAString& aUsername, ErrorResult& aError)
+{
+ if (!CallerSubsumes()) {
+ aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
+ return;
+ }
+
+ aUsername.Truncate();
+ nsCOMPtr uri;
+ nsresult result = GetURI(getter_AddRefs(uri));
+ if (uri) {
+ nsAutoCString username;
+ result = uri->GetUsername(username);
+ if (NS_SUCCEEDED(result)) {
+ CopyUTF8toUTF16(username, aUsername);
+ }
+ }
+}
+
+void
+nsLocation::SetUsername(const nsAString& aUsername, ErrorResult& aError)
+{
+ if (!CallerSubsumes()) {
+ aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
+ return;
+ }
+
+ nsCOMPtr uri;
+ nsresult rv = GetWritableURI(getter_AddRefs(uri));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ aError.Throw(rv);
+ return;
+ }
+
+ if (!uri) {
+ return;
+ }
+
+ rv = uri->SetUsername(NS_ConvertUTF16toUTF8(aUsername));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ aError.Throw(rv);
+ return;
+ }
+
+ rv = SetURI(uri);
+}
+
+void
+nsLocation::GetPassword(nsAString& aPassword, ErrorResult& aError)
+{
+ if (!CallerSubsumes()) {
+ aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
+ return;
+ }
+
+ aPassword.Truncate();
+ nsCOMPtr uri;
+ nsresult result = GetURI(getter_AddRefs(uri));
+ if (uri) {
+ nsAutoCString password;
+ result = uri->GetPassword(password);
+ if (NS_SUCCEEDED(result)) {
+ CopyUTF8toUTF16(password, aPassword);
+ }
+ }
+}
+
+void
+nsLocation::SetPassword(const nsAString& aPassword, ErrorResult& aError)
+{
+ if (!CallerSubsumes()) {
+ aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
+ return;
+ }
+
+ nsCOMPtr uri;
+ nsresult rv = GetWritableURI(getter_AddRefs(uri));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ aError.Throw(rv);
+ return;
+ }
+
+ if (!uri) {
+ return;
+ }
+
+ rv = uri->SetPassword(NS_ConvertUTF16toUTF8(aPassword));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ aError.Throw(rv);
+ return;
+ }
+
+ rv = SetURI(uri);
+}
+
NS_IMETHODIMP
nsLocation::GetSearch(nsAString& aSearch)
{
@@ -918,8 +1019,12 @@ nsLocation::GetSourceBaseURL(JSContext* cx, nsIURI** sourceURL)
bool
nsLocation::CallerSubsumes()
{
- // Get the principal associated with the location object.
- nsCOMPtr outer = do_QueryReferent(mOuter);
+ // Get the principal associated with the location object. Note that this is
+ // the principal of the page which will actually be navigated, not the
+ // principal of the Location object itself. This is why we need this check
+ // even though we only allow limited cross-origin access to Location objects
+ // in general.
+ nsCOMPtr outer = mInnerWindow->GetOuterWindow();
if (MOZ_UNLIKELY(!outer))
return false;
nsCOMPtr sop = do_QueryInterface(outer);
@@ -928,3 +1033,9 @@ nsLocation::CallerSubsumes()
NS_ENSURE_SUCCESS(rv, false);
return subsumes;
}
+
+JSObject*
+nsLocation::WrapObject(JSContext* aCx)
+{
+ return LocationBinding::Wrap(aCx, this);
+}
diff --git a/dom/base/nsLocation.h b/dom/base/nsLocation.h
index f688f5737931..f3fc3b4d73e6 100644
--- a/dom/base/nsLocation.h
+++ b/dom/base/nsLocation.h
@@ -13,6 +13,8 @@
#include "nsWrapperCache.h"
#include "nsCycleCollectionParticipant.h"
#include "js/TypeDecls.h"
+#include "mozilla/ErrorResult.h"
+#include "nsPIDOMWindow.h"
class nsIURI;
class nsIDocShell;
@@ -22,11 +24,13 @@ class nsIDocShellLoadInfo;
// nsLocation: Script "location" object
//*****************************************************************************
-class nsLocation : public nsIDOMLocation
- , public nsWrapperCache
+class nsLocation MOZ_FINAL : public nsIDOMLocation
+ , public nsWrapperCache
{
+ typedef mozilla::ErrorResult ErrorResult;
+
public:
- nsLocation(nsIDocShell *aDocShell);
+ nsLocation(nsPIDOMWindow* aWindow, nsIDocShell *aDocShell);
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsLocation)
@@ -37,6 +41,101 @@ public:
// nsIDOMLocation
NS_DECL_NSIDOMLOCATION
+ // WebIDL API:
+ void Assign(const nsAString& aUrl, ErrorResult& aError)
+ {
+ aError = Assign(aUrl);
+ }
+ void Replace(const nsAString& aUrl, ErrorResult& aError)
+ {
+ aError = Replace(aUrl);
+ }
+ void Reload(bool aForceget, ErrorResult& aError)
+ {
+ aError = Reload(aForceget);
+ }
+ void GetHref(nsAString& aHref, ErrorResult& aError)
+ {
+ aError = GetHref(aHref);
+ }
+ void SetHref(const nsAString& aHref, ErrorResult& aError)
+ {
+ aError = SetHref(aHref);
+ }
+ void GetOrigin(nsAString& aOrigin, ErrorResult& aError)
+ {
+ aError = GetOrigin(aOrigin);
+ }
+ void GetProtocol(nsAString& aProtocol, ErrorResult& aError)
+ {
+ aError = GetProtocol(aProtocol);
+ }
+ void SetProtocol(const nsAString& aProtocol, ErrorResult& aError)
+ {
+ aError = SetProtocol(aProtocol);
+ }
+ void GetUsername(nsAString& aUsername, ErrorResult& aError);
+ void SetUsername(const nsAString& aUsername, ErrorResult& aError);
+ void GetPassword(nsAString& aPassword, ErrorResult& aError);
+ void SetPassword(const nsAString& aPassword, ErrorResult& aError);
+ void GetHost(nsAString& aHost, ErrorResult& aError)
+ {
+ aError = GetHost(aHost);
+ }
+ void SetHost(const nsAString& aHost, ErrorResult& aError)
+ {
+ aError = SetHost(aHost);
+ }
+ void GetHostname(nsAString& aHostname, ErrorResult& aError)
+ {
+ aError = GetHostname(aHostname);
+ }
+ void SetHostname(const nsAString& aHostname, ErrorResult& aError)
+ {
+ aError = SetHostname(aHostname);
+ }
+ void GetPort(nsAString& aPort, ErrorResult& aError)
+ {
+ aError = GetPort(aPort);
+ }
+ void SetPort(const nsAString& aPort, ErrorResult& aError)
+ {
+ aError = SetPort(aPort);
+ }
+ void GetPathname(nsAString& aPathname, ErrorResult& aError)
+ {
+ aError = GetPathname(aPathname);
+ }
+ void SetPathname(const nsAString& aPathname, ErrorResult& aError)
+ {
+ aError = SetPathname(aPathname);
+ }
+ void GetSearch(nsAString& aSeach, ErrorResult& aError)
+ {
+ aError = GetSearch(aSeach);
+ }
+ void SetSearch(const nsAString& aSeach, ErrorResult& aError)
+ {
+ aError = SetSearch(aSeach);
+ }
+ void GetHash(nsAString& aHash, ErrorResult& aError)
+ {
+ aError = GetHash(aHash);
+ }
+ void SetHash(const nsAString& aHash, ErrorResult& aError)
+ {
+ aError = SetHash(aHash);
+ }
+ void Stringify(nsAString& aRetval, ErrorResult& aError)
+ {
+ GetHref(aRetval, aError);
+ }
+ nsPIDOMWindow* GetParentObject() const
+ {
+ return mInnerWindow;
+ }
+ virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
+
protected:
virtual ~nsLocation();
@@ -56,8 +155,8 @@ protected:
bool CallerSubsumes();
nsString mCachedHash;
+ nsCOMPtr mInnerWindow;
nsWeakPtr mDocShell;
- nsWeakPtr mOuter;
};
#endif // nsLocation_h__
diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp
index 7153836c3244..275e43d1a133 100644
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -86,10 +86,13 @@ ThrowInvalidThis(JSContext* aCx, const JS::CallArgs& aArgs,
MOZ_ASSERT(func);
JS::Rooted funcName(aCx, JS_GetFunctionDisplayId(func));
MOZ_ASSERT(funcName);
+ nsAutoJSString funcNameStr;
+ if (!funcNameStr.init(aCx, funcName)) {
+ return false;
+ }
JS_ReportErrorNumberUC(aCx, GetErrorMessage, nullptr,
static_cast(aErrorNumber),
- JS_GetStringCharsZ(aCx, funcName),
- ifaceName.get());
+ funcNameStr.get(), ifaceName.get());
return false;
}
@@ -909,6 +912,14 @@ GetInterfaceImpl(JSContext* aCx, nsIInterfaceRequestor* aRequestor,
}
}
+bool
+UnforgeableValueOf(JSContext* cx, unsigned argc, JS::Value* vp)
+{
+ JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ args.rval().set(args.thisv());
+ return true;
+}
+
bool
ThrowingConstructor(JSContext* cx, unsigned argc, JS::Value* vp)
{
@@ -1053,18 +1064,91 @@ XrayResolveAttribute(JSContext* cx, JS::Handle wrapper,
return true;
}
+static bool
+XrayResolveMethod(JSContext* cx, JS::Handle wrapper,
+ JS::Handle obj, JS::Handle id,
+ const Prefable* methods,
+ jsid* methodIds,
+ const JSFunctionSpec* methodsSpecs,
+ JS::MutableHandle desc)
+{
+ const Prefable* method;
+ for (method = methods; method->specs; ++method) {
+ if (method->isEnabled(cx, obj)) {
+ // Set i to be the index into our full list of ids/specs that we're
+ // looking at now.
+ size_t i = method->specs - methodsSpecs;
+ for ( ; methodIds[i] != JSID_VOID; ++i) {
+ if (id == methodIds[i]) {
+ const JSFunctionSpec& methodSpec = methodsSpecs[i];
+ JSFunction *fun;
+ if (methodSpec.selfHostedName) {
+ fun = JS::GetSelfHostedFunction(cx, methodSpec.selfHostedName, id, methodSpec.nargs);
+ if (!fun) {
+ return false;
+ }
+ MOZ_ASSERT(!methodSpec.call.op, "Bad FunctionSpec declaration: non-null native");
+ MOZ_ASSERT(!methodSpec.call.info, "Bad FunctionSpec declaration: non-null jitinfo");
+ } else {
+ fun = JS_NewFunctionById(cx, methodSpec.call.op, methodSpec.nargs, 0, wrapper, id);
+ if (!fun) {
+ return false;
+ }
+ SET_JITINFO(fun, methodSpec.call.info);
+ }
+ JSObject *funobj = JS_GetFunctionObject(fun);
+ desc.value().setObject(*funobj);
+ desc.setAttributes(methodSpec.flags);
+ desc.object().set(wrapper);
+ desc.setSetter(nullptr);
+ desc.setGetter(nullptr);
+ return true;
+ }
+ }
+ }
+ }
+ return true;
+}
+
/* static */ bool
XrayResolveUnforgeableProperty(JSContext* cx, JS::Handle wrapper,
JS::Handle obj, JS::Handle id,
JS::MutableHandle desc,
const NativeProperties* nativeProperties)
{
- return !nativeProperties || !nativeProperties->unforgeableAttributes ||
- XrayResolveAttribute(cx, wrapper, obj, id,
+ if (!nativeProperties) {
+ return true;
+ }
+
+ if (nativeProperties->unforgeableAttributes) {
+ if (!XrayResolveAttribute(cx, wrapper, obj, id,
nativeProperties->unforgeableAttributes,
nativeProperties->unforgeableAttributeIds,
nativeProperties->unforgeableAttributeSpecs,
- desc);
+ desc)) {
+ return false;
+ }
+
+ if (desc.object()) {
+ return true;
+ }
+ }
+
+ if (nativeProperties->unforgeableMethods) {
+ if (!XrayResolveMethod(cx, wrapper, obj, id,
+ nativeProperties->unforgeableMethods,
+ nativeProperties->unforgeableMethodIds,
+ nativeProperties->unforgeableMethodSpecs,
+ desc)) {
+ return false;
+ }
+
+ if (desc.object()) {
+ return true;
+ }
+ }
+
+ return true;
}
static bool
@@ -1086,40 +1170,12 @@ XrayResolveProperty(JSContext* cx, JS::Handle wrapper,
methodsSpecs = nativeProperties->methodsSpecs;
}
if (methods) {
- const Prefable* method;
- for (method = methods; method->specs; ++method) {
- if (method->isEnabled(cx, obj)) {
- // Set i to be the index into our full list of ids/specs that we're
- // looking at now.
- size_t i = method->specs - methodsSpecs;
- for ( ; methodIds[i] != JSID_VOID; ++i) {
- if (id == methodIds[i]) {
- const JSFunctionSpec& methodSpec = methodsSpecs[i];
- JSFunction *fun;
- if (methodSpec.selfHostedName) {
- fun = JS::GetSelfHostedFunction(cx, methodSpec.selfHostedName, id, methodSpec.nargs);
- if (!fun) {
- return false;
- }
- MOZ_ASSERT(!methodSpec.call.op, "Bad FunctionSpec declaration: non-null native");
- MOZ_ASSERT(!methodSpec.call.info, "Bad FunctionSpec declaration: non-null jitinfo");
- } else {
- fun = JS_NewFunctionById(cx, methodSpec.call.op, methodSpec.nargs, 0, wrapper, id);
- if (!fun) {
- return false;
- }
- SET_JITINFO(fun, methodSpec.call.info);
- }
- JSObject *funobj = JS_GetFunctionObject(fun);
- desc.value().setObject(*funobj);
- desc.setAttributes(methodSpec.flags);
- desc.object().set(wrapper);
- desc.setSetter(nullptr);
- desc.setGetter(nullptr);
- return true;
- }
- }
- }
+ if (!XrayResolveMethod(cx, wrapper, obj, id, methods, methodIds,
+ methodsSpecs, desc)) {
+ return false;
+ }
+ if (desc.object()) {
+ return true;
}
}
diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h
index 30ec98c95bb7..492358459ab9 100644
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -1700,6 +1700,9 @@ GetInterface(JSContext* aCx, T* aThis, nsIJSID* aIID,
GetInterfaceImpl(aCx, aThis, aThis, aIID, aRetval, aError);
}
+bool
+UnforgeableValueOf(JSContext* cx, unsigned argc, JS::Value* vp);
+
bool
ThrowingConstructor(JSContext* cx, unsigned argc, JS::Value* vp);
diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf
index dcabf2bacae3..d337e31a32e4 100644
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -742,11 +742,7 @@ DOMInterfaces = {
},
'Location': {
- # NOTE: Before you turn on codegen for Location, make sure all the
- # Unforgeable stuff is dealt with.
- 'nativeType': 'nsIDOMLocation',
- 'skipGen': True,
- 'register': False
+ 'nativeType': 'nsLocation',
},
'MediaList': {
diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py
index 3755edd20153..a43af48895ad 100644
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -489,10 +489,22 @@ def PrototypeIDAndDepth(descriptor):
return (prototypeID, depth)
+def MemberIsUnforgeable(member, descriptor):
+ # Note: "or" and "and" return either their LHS or RHS, not
+ # necessarily booleans. Make sure to return a boolean from this
+ # method, because callers will compare its return value to
+ # booleans.
+ return bool((member.isAttr() or member.isMethod()) and
+ not member.isStatic() and
+ (member.isUnforgeable() or
+ descriptor.interface.getExtendedAttribute("Unforgeable")))
+
+
def UseHolderForUnforgeable(descriptor):
return (descriptor.concrete and
descriptor.proxy and
- any(m for m in descriptor.interface.members if (m.isAttr() or m.isMethod()) and m.isUnforgeable()))
+ any(m for m in descriptor.interface.members
+ if MemberIsUnforgeable(m, descriptor)))
def CallOnUnforgeableHolder(descriptor, code, isXrayCheck=None,
@@ -1999,7 +2011,7 @@ class MethodDefiner(PropertyDefiner):
if descriptor.interface.hasInterfacePrototypeObject() or static:
methods = [m for m in descriptor.interface.members if
m.isMethod() and m.isStatic() == static and
- m.isUnforgeable() == unforgeable and
+ MemberIsUnforgeable(m, descriptor) == unforgeable and
not m.isIdentifierLess()]
else:
methods = []
@@ -2072,7 +2084,8 @@ class MethodDefiner(PropertyDefiner):
if not static:
stringifier = descriptor.operations['Stringifier']
- if stringifier:
+ if (stringifier and
+ unforgeable == MemberIsUnforgeable(stringifier, descriptor)):
toStringDesc = {
"name": "toString",
"nativeName": stringifier.identifier.name,
@@ -2097,6 +2110,18 @@ class MethodDefiner(PropertyDefiner):
self.chrome.append(toJSONDesc)
else:
self.regular.append(toJSONDesc)
+ if (unforgeable and
+ descriptor.interface.getExtendedAttribute("Unforgeable")):
+ # Synthesize our valueOf method
+ self.regular.append({
+ "name": 'valueOf',
+ "nativeName": "UnforgeableValueOf",
+ "methodInfo": False,
+ "length": 0,
+ "flags": "JSPROP_ENUMERATE", # readonly/permanent added
+ # automatically.
+ "condition": MemberCondition(None, None)
+ })
elif (descriptor.interface.isJSImplemented() and
descriptor.interface.hasInterfaceObject()):
self.chrome.append({
@@ -2127,7 +2152,7 @@ class MethodDefiner(PropertyDefiner):
return m["condition"]
def flags(m):
- unforgeable = " | JSPROP_PERMANENT" if self.unforgeable else ""
+ unforgeable = " | JSPROP_PERMANENT | JSPROP_READONLY" if self.unforgeable else ""
return m["flags"] + unforgeable
def specData(m):
@@ -2175,6 +2200,23 @@ class MethodDefiner(PropertyDefiner):
condition, specData, doIdArrays)
+def IsCrossOriginWritable(attr, descriptor):
+ """
+ Return whether the IDLAttribute in question is cross-origin writable on the
+ interface represented by descriptor. This is needed to handle the fact that
+ some, but not all, interfaces implementing URLUtils want a cross-origin
+ writable .href.
+ """
+ crossOriginWritable = attr.getExtendedAttribute("CrossOriginWritable")
+ if not crossOriginWritable:
+ return False
+ if crossOriginWritable == True:
+ return True
+ assert (isinstance(crossOriginWritable, list) and
+ len(crossOriginWritable) == 1)
+ return crossOriginWritable[0] == descriptor.interface.identifier.name
+
+
class AttrDefiner(PropertyDefiner):
def __init__(self, descriptor, name, static, unforgeable=False):
assert not (static and unforgeable)
@@ -2184,7 +2226,7 @@ class AttrDefiner(PropertyDefiner):
if descriptor.interface.hasInterfacePrototypeObject() or static:
attributes = [m for m in descriptor.interface.members if
m.isAttr() and m.isStatic() == static and
- m.isUnforgeable() == unforgeable]
+ MemberIsUnforgeable(m, descriptor) == unforgeable]
else:
attributes = []
self.chrome = [m for m in attributes if isChromeOnly(m)]
@@ -2238,7 +2280,7 @@ class AttrDefiner(PropertyDefiner):
else:
if attr.hasLenientThis():
accessor = "genericLenientSetter"
- elif attr.getExtendedAttribute("CrossOriginWritable"):
+ elif IsCrossOriginWritable(attr, self.descriptor):
accessor = "genericCrossOriginSetter"
elif self.descriptor.needsSpecialGenericOps():
accessor = "genericSetter"
@@ -2786,6 +2828,11 @@ def InitUnforgeablePropertiesOnObject(descriptor, obj, properties, failureReturn
"""
unforgeables = []
+ if failureReturnValue:
+ failureReturnValue = " " + failureReturnValue
+ else:
+ failureReturnValue = ""
+
defineUnforgeableAttrs = fill(
"""
if (!DefineUnforgeableAttributes(aCx, ${obj}, %s)) {
@@ -2793,7 +2840,7 @@ def InitUnforgeablePropertiesOnObject(descriptor, obj, properties, failureReturn
}
""",
obj=obj,
- rv=" " + failureReturnValue if failureReturnValue else "")
+ rv=failureReturnValue)
defineUnforgeableMethods = fill(
"""
if (!DefineUnforgeableMethods(aCx, ${obj}, %s)) {
@@ -2801,7 +2848,7 @@ def InitUnforgeablePropertiesOnObject(descriptor, obj, properties, failureReturn
}
""",
obj=obj,
- rv=" " + failureReturnValue if failureReturnValue else "")
+ rv=failureReturnValue)
unforgeableMembers = [
(defineUnforgeableAttrs, properties.unforgeableAttrs),
@@ -2815,6 +2862,19 @@ def InitUnforgeablePropertiesOnObject(descriptor, obj, properties, failureReturn
CGIfWrapper(CGGeneric(template % array.variableName(True)),
"nsContentUtils::ThreadsafeIsCallerChrome()"))
+ if descriptor.interface.getExtendedAttribute("Unforgeable"):
+ # We do our undefined toJSON here, not as a regular property
+ # because we don't have a concept of value props anywhere.
+ unforgeables.append(CGGeneric(fill(
+ """
+ if (!JS_DefineProperty(aCx, ${obj}, "toJSON", JS::UndefinedHandleValue,
+ JSPROP_READONLY | JSPROP_ENUMERATE | JSPROP_PERMANENT)) {
+ return${rv};
+ }
+ """,
+ obj=obj,
+ rv=failureReturnValue)))
+
return CGList(unforgeables)
@@ -10353,13 +10413,13 @@ class CGDescriptor(CGThing):
cgThings.append(CGSpecializedSetter(descriptor, m))
if m.hasLenientThis():
hasLenientSetter = True
- elif m.getExtendedAttribute("CrossOriginWritable"):
+ elif IsCrossOriginWritable(m, descriptor):
crossOriginSetters.add(m.identifier.name)
elif descriptor.needsSpecialGenericOps():
hasSetter = True
elif m.getExtendedAttribute("PutForwards"):
cgThings.append(CGSpecializedForwardingSetter(descriptor, m))
- if m.getExtendedAttribute("CrossOriginWritable"):
+ if IsCrossOriginWritable(m, descriptor):
crossOriginSetters.add(m.identifier.name)
elif descriptor.needsSpecialGenericOps():
hasSetter = True
diff --git a/dom/bindings/Exceptions.cpp b/dom/bindings/Exceptions.cpp
index 59efe286aa95..e9166199763f 100644
--- a/dom/bindings/Exceptions.cpp
+++ b/dom/bindings/Exceptions.cpp
@@ -394,9 +394,7 @@ NS_IMETHODIMP JSStackFrame::GetName(nsAString& aFunction)
if (!mFunnameInitialized) {
JS::FrameDescription& desc = mStackDescription->FrameAt(mIndex);
if (JSFlatString *name = desc.funDisplayName()) {
- mFunname.Assign(JS_GetFlatStringChars(name),
- // XXXbz Can't JS_GetStringLength on JSFlatString!
- JS_GetStringLength(JS_FORGET_STRING_FLATNESS(name)));
+ AssignJSFlatString(mFunname, name);
}
mFunnameInitialized = true;
}
diff --git a/dom/bindings/parser/WebIDL.py b/dom/bindings/parser/WebIDL.py
index edeebf05fd3a..4c239e36eb72 100644
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -669,8 +669,36 @@ class IDLInterface(IDLObjectWithScope):
for ancestorConsequential in ancestor.getConsequentialInterfaces():
ancestorConsequential.interfacesBasedOnSelf.add(self)
+ # Deal with interfaces marked [Unforgeable], now that we have our full
+ # member list, except unforgeables pulled in from parents. We want to
+ # do this before we set "originatingInterface" on our unforgeable
+ # members.
+ if self.getExtendedAttribute("Unforgeable"):
+ # Check that the interface already has all the things the
+ # spec would otherwise require us to synthesize and is
+ # missing the ones we plan to synthesize.
+ if not any(m.isMethod() and m.isStringifier() for m in self.members):
+ raise WebIDLError("Unforgeable interface %s does not have a "
+ "stringifier" % self.identifier.name,
+ [self.location])
+
+ for m in self.members:
+ if ((m.isMethod() and m.isJsonifier()) or
+ m.identifier.name == "toJSON"):
+ raise WebIDLError("Unforgeable interface %s has a "
+ "jsonifier so we won't be able to add "
+ "one ourselves" % self.identifier.name,
+ [self.location, m.location])
+
+ if m.identifier.name == "valueOf" and not m.isStatic():
+ raise WebIDLError("Unforgeable interface %s has a valueOf "
+ "member so we won't be able to add one "
+ "ourselves" % self.identifier.name,
+ [self.location, m.location])
+
for member in self.members:
- if (member.isAttr() and member.isUnforgeable() and
+ if ((member.isAttr() or member.isMethod()) and
+ member.isUnforgeable() and
not hasattr(member, "originatingInterface")):
member.originatingInterface = self
@@ -693,16 +721,16 @@ class IDLInterface(IDLObjectWithScope):
# worry about anything other than our parent, because it has already
# imported its ancestors unforgeable attributes into its member
# list.
- for unforgeableAttr in (attr for attr in self.parent.members if
- attr.isAttr() and not attr.isStatic() and
- attr.isUnforgeable()):
+ for unforgeableMember in (member for member in self.parent.members if
+ (member.isAttr() or member.isMethod()) and
+ member.isUnforgeable()):
shadows = [ m for m in self.members if
(m.isAttr() or m.isMethod()) and
not m.isStatic() and
- m.identifier.name == unforgeableAttr.identifier.name ]
+ m.identifier.name == unforgeableMember.identifier.name ]
if len(shadows) != 0:
- locs = [unforgeableAttr.location] + [ s.location for s
- in shadows ]
+ locs = [unforgeableMember.location] + [ s.location for s
+ in shadows ]
raise WebIDLError("Interface %s shadows [Unforgeable] "
"members of %s" %
(self.identifier.name,
@@ -711,10 +739,10 @@ class IDLInterface(IDLObjectWithScope):
# And now just stick it in our members, since we won't be
# inheriting this down the proto chain. If we really cared we
# could try to do something where we set up the unforgeable
- # attributes of ancestor interfaces, with their corresponding
- # getters, on our interface, but that gets pretty complicated
- # and seems unnecessary.
- self.members.append(unforgeableAttr)
+ # attributes/methods of ancestor interfaces, with their
+ # corresponding getters, on our interface, but that gets pretty
+ # complicated and seems unnecessary.
+ self.members.append(unforgeableMember)
# Ensure that there's at most one of each {named,indexed}
# {getter,setter,creator,deleter}, at most one stringifier,
@@ -785,6 +813,26 @@ class IDLInterface(IDLObjectWithScope):
parent = parent.parent
def validate(self):
+ # We don't support consequential unforgeable interfaces. Need to check
+ # this here, becaue in finish() an interface might not know yet that
+ # it's consequential.
+ if self.getExtendedAttribute("Unforgeable") and self.isConsequential():
+ raise WebIDLError(
+ "%s is an unforgeable consequential interface" %
+ self.identifier.name,
+ [self.location] +
+ list(i.location for i in
+ (self.interfacesBasedOnSelf - { self }) ))
+
+ # We also don't support inheriting from unforgeable interfaces.
+ if self.getExtendedAttribute("Unforgeable") and self.hasChildInterfaces():
+ raise WebIDLError("%s is an unforgeable ancestor interface" %
+ self.identifier.name,
+ [self.location] +
+ list(i.location for i in
+ self.interfacesBasedOnSelf if i.parent == self))
+
+
for member in self.members:
member.validate()
@@ -992,6 +1040,7 @@ class IDLInterface(IDLObjectWithScope):
elif (identifier == "NeedNewResolve" or
identifier == "OverrideBuiltins" or
identifier == "ChromeOnly" or
+ identifier == "Unforgeable" or
identifier == "LegacyEventInit"):
# Known extended attributes that do not take values
if not attr.noArguments():
@@ -2889,9 +2938,6 @@ class IDLAttribute(IDLInterfaceMember):
[attr.location, self.location])
self.lenientThis = True
elif identifier == "Unforgeable":
- if not self.readonly:
- raise WebIDLError("[Unforgeable] is only allowed on readonly "
- "attributes", [attr.location, self.location])
if self.isStatic():
raise WebIDLError("[Unforgeable] is only allowed on non-static "
"attributes", [attr.location, self.location])
@@ -2951,7 +2997,7 @@ class IDLAttribute(IDLInterfaceMember):
[attr.location, self.location])
elif (identifier == "CrossOriginReadable" or
identifier == "CrossOriginWritable"):
- if not attr.noArguments():
+ if not attr.noArguments() and identifier == "CrossOriginReadable":
raise WebIDLError("[%s] must take no arguments" % identifier,
[attr.location])
if self.isStatic():
@@ -3545,15 +3591,19 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
raise WebIDLError("[LenientFloat] used on an operation with no "
"restricted float type arguments",
[attr.location, self.location])
+ elif (identifier == "Pure" or
+ identifier == "CrossOriginCallable" or
+ identifier == "WebGLHandlesContextLoss"):
+ # Known no-argument attributes.
+ if not attr.noArguments():
+ raise WebIDLError("[%s] must take no arguments" % identifier,
+ [attr.location])
elif (identifier == "Throws" or
identifier == "NewObject" or
identifier == "ChromeOnly" or
identifier == "Pref" or
identifier == "Func" or
identifier == "AvailableIn" or
- identifier == "Pure" or
- identifier == "CrossOriginCallable" or
- identifier == "WebGLHandlesContextLoss" or
identifier == "CheckPermissions"):
# Known attributes that we don't need to do anything with here
pass
diff --git a/dom/bindings/parser/tests/test_unforgeable.py b/dom/bindings/parser/tests/test_unforgeable.py
index e512bde215bc..3787e8c6af1e 100644
--- a/dom/bindings/parser/tests/test_unforgeable.py
+++ b/dom/bindings/parser/tests/test_unforgeable.py
@@ -79,6 +79,25 @@ def WebIDLTest(parser, harness):
"Should have thrown when shadowing unforgeable attribute on "
"parent with operation.")
+ parser = parser.reset();
+ threw = False
+ try:
+ parser.parse("""
+ interface Child : Parent {
+ void foo();
+ };
+ interface Parent {
+ [Unforgeable] void foo();
+ };
+ """)
+
+ results = parser.finish()
+ except:
+ threw = True
+ harness.ok(threw,
+ "Should have thrown when shadowing unforgeable operation on "
+ "parent with operation.")
+
parser = parser.reset();
threw = False
try:
@@ -98,6 +117,25 @@ def WebIDLTest(parser, harness):
"Should have thrown when shadowing unforgeable attribute on "
"parent with attribute.")
+ parser = parser.reset();
+ threw = False
+ try:
+ parser.parse("""
+ interface Child : Parent {
+ attribute short foo;
+ };
+ interface Parent {
+ [Unforgeable] void foo();
+ };
+ """)
+
+ results = parser.finish()
+ except Exception,x:
+ threw = True
+ harness.ok(threw,
+ "Should have thrown when shadowing unforgeable operation on "
+ "parent with attribute.")
+
parser = parser.reset();
parser.parse("""
interface Child : Parent {
@@ -166,16 +204,38 @@ def WebIDLTest(parser, harness):
threw = False
try:
parser.parse("""
- interface iface {
- [Unforgeable] attribute long foo;
+ interface Child : Parent {
};
+ interface Parent : GrandParent {};
+ interface GrandParent {};
+ interface Consequential {
+ [Unforgeable] void foo();
+ };
+ GrandParent implements Consequential;
+ interface ChildConsequential {
+ void foo();
+ };
+ Child implements ChildConsequential;
""")
results = parser.finish()
except:
threw = True
- harness.ok(threw, "Should have thrown for writable [Unforgeable] attribute.")
+ harness.ok(threw,
+ "Should have thrown when our consequential interface shadows unforgeable operation "
+ "of ancestor's consequential interface.")
+
+ parser = parser.reset();
+ parser.parse("""
+ interface iface {
+ [Unforgeable] attribute long foo;
+ };
+ """)
+
+ results = parser.finish()
+ harness.check(len(results), 1,
+ "Should allow writable [Unforgeable] attribute.")
parser = parser.reset();
threw = False
diff --git a/dom/browser-element/BrowserElementChildPreload.js b/dom/browser-element/BrowserElementChildPreload.js
index 393d8d63ba2e..82da8310faf1 100644
--- a/dom/browser-element/BrowserElementChildPreload.js
+++ b/dom/browser-element/BrowserElementChildPreload.js
@@ -186,10 +186,21 @@ BrowserElementChild.prototype = {
/* wantsUntrusted = */ false);
addEventListener('DOMMetaAdded',
- this._metaAddedHandler.bind(this),
+ this._metaChangedHandler.bind(this),
/* useCapture = */ true,
/* wantsUntrusted = */ false);
+ addEventListener('DOMMetaChanged',
+ this._metaChangedHandler.bind(this),
+ /* useCapture = */ true,
+ /* wantsUntrusted = */ false);
+
+ addEventListener('DOMMetaRemoved',
+ this._metaChangedHandler.bind(this),
+ /* useCapture = */ true,
+ /* wantsUntrusted = */ false);
+
+
// This listens to unload events from our message manager, but /not/ from
// the |content| window. That's because the window's unload event doesn't
// bubble, and we're not using a capturing listener. If we'd used
@@ -513,7 +524,7 @@ BrowserElementChild.prototype = {
}, this);
},
- _metaAddedHandler: function(e) {
+ _metaChangedHandler: function(e) {
let win = e.target.ownerDocument.defaultView;
// Ignore metas which don't come from the top-level
//
+
+
+
+
+
+