merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2014-07-14 14:34:36 +02:00
commit 90fb1d9bfd
386 changed files with 8552 additions and 3985 deletions

View File

@ -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()])

View File

@ -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<nsIDOMLocation> GetLocation() const;
already_AddRefed<nsLocation> GetLocation() const;
void GetReferrer(nsAString& aReferrer) const;
void GetLastModified(nsAString& aLastModified) const;
void GetReadyState(nsAString& aReadyState) const;

View File

@ -128,7 +128,7 @@ Link::GetURI() const
}
void
Link::SetProtocol(const nsAString &aProtocol)
Link::SetProtocol(const nsAString &aProtocol, ErrorResult& aError)
{
nsCOMPtr<nsIURI> 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<nsIURI> 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<nsIURI> 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<nsIURI> 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<nsIURI> 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<nsIURI> uri(GetURIToMutate());
nsCOMPtr<nsIURL> 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<nsIURI> 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<nsIURI> 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<nsIURI> 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();

View File

@ -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.

View File

@ -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<nsIDOMLocation>
already_AddRefed<nsLocation>
nsIDocument::GetLocation() const
{
nsCOMPtr<nsIDOMWindow> w = do_QueryInterface(mScriptGlobalObject);
@ -6557,7 +6558,7 @@ nsIDocument::GetLocation() const
nsCOMPtr<nsIDOMLocation> loc;
w->GetLocation(getter_AddRefs(loc));
return loc.forget();
return loc.forget().downcast<nsLocation>();
}
Element*

View File

@ -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<bool>);
#endif
}
// finally, add the region to the list
RegionInfo info;
info.mId = options.mId;
@ -3468,7 +3469,7 @@ CanvasRenderingContext2D::DrawDirectlyToCanvas(
nsRefPtr<gfxContext> context = new gfxContext(tempTarget);
context->SetMatrix(contextMatrix);
// FLAG_CLAMP is added for increased performance
uint32_t modifiedFlags = image.mDrawingFlags | imgIContainer::FLAG_CLAMP;

View File

@ -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<JSObject*> result,
mozilla::ErrorResult& error) const;
JS::MutableHandle<JSObject*> result,
mozilla::ErrorResult& error) const;
void SetMozCurrentTransform(JSContext* cx,
JS::Handle<JSObject*> currentTransform,
mozilla::ErrorResult& error);
void GetMozCurrentTransformInverse(JSContext* cx,
JS::MutableHandle<JSObject*> result,
mozilla::ErrorResult& error) const;
JS::MutableHandle<JSObject*> result,
mozilla::ErrorResult& error) const;
void SetMozCurrentTransformInverse(JSContext* cx,
JS::Handle<JSObject*> currentTransform,
mozilla::ErrorResult& error);
void GetFillRule(nsAString& fillRule);
void SetFillRule(const nsAString& fillRule);
void GetMozDash(JSContext* cx, JS::MutableHandle<JS::Value> 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<mozilla::gfx::DrawTarget> mTarget;
RefPtr<gfx::SurfaceStream> mStream;
RefPtr<gl::SurfaceStream> 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);
}

View File

@ -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);
}
}

View File

@ -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<mozilla::dom::NodeInfo>& aNodeInfo);
typedef mozilla::dom::NodeInfo NodeInfo;
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
HTMLAudioElement(already_AddRefed<NodeInfo>& 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; }

View File

@ -72,6 +72,7 @@ class AudioTrackList;
class VideoTrackList;
class HTMLMediaElement : public nsGenericHTMLElement,
public nsIDOMHTMLMediaElement,
public nsIObserver,
public MediaDecoderOwner,
public nsIAudioChannelAgentCallback

View File

@ -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<mozilla::dom::NodeInfo>& aNodeInfo);
typedef mozilla::dom::NodeInfo NodeInfo;
HTMLVideoElement(already_AddRefed<NodeInfo>& 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);

View File

@ -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; \
}

View File

@ -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:

View File

@ -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; \
}

View File

@ -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:

View File

@ -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<mozilla::dom::NodeInfo>& aNodeInfo)
HTMLAudioElement::HTMLAudioElement(already_AddRefed<NodeInfo>& aNodeInfo)
: HTMLMediaElement(aNodeInfo)
{
}
@ -44,7 +40,6 @@ HTMLAudioElement::~HTMLAudioElement()
{
}
already_AddRefed<HTMLAudioElement>
HTMLAudioElement::Audio(const GlobalObject& aGlobal,
const Optional<nsAString>& aSrc,

View File

@ -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<DOMMediaStream>
HTMLMediaElement::GetMozSrcObject() const
{
@ -1820,8 +1826,7 @@ HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded)
// holistically.
uint8_t hints = 0;
if (Preferences::GetBool("media.capturestream_hints.enabled")) {
nsCOMPtr<nsIDOMHTMLVideoElement> 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<nsIRunnable> event =
NS_NewRunnableMethod(this, &StreamListener::DoNotifyFinished);
aGraph->DispatchToMainThreadAfterStreamStateUpdate(event.forget());
if (event == EVENT_FINISHED) {
nsCOMPtr<nsIRunnable> 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<nsIDOMHTMLVideoElement> 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<nsIDOMHTMLVideoElement> 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<int32_t>(mAudioChannel),
this, true);

View File

@ -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,

View File

@ -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;

View File

@ -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<mozilla::dom::NodeInfo>& aNodeInfo)
HTMLVideoElement::HTMLVideoElement(already_AddRefed<NodeInfo>& 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

View File

@ -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);
}

View File

@ -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<nsIDOMLocation> GetLocation() const {
already_AddRefed<nsLocation> GetLocation() const {
return nsIDocument::GetLocation();
}

View File

@ -261,13 +261,15 @@ MediaDecoder::DecodedStreamGraphListener::DoNotifyFinished()
}
void
MediaDecoder::DecodedStreamGraphListener::NotifyFinished(MediaStreamGraph* aGraph)
MediaDecoder::DecodedStreamGraphListener::NotifyEvent(MediaStreamGraph* aGraph,
MediaStreamListener::MediaStreamGraphEvent event)
{
nsCOMPtr<nsIRunnable> event =
NS_NewRunnableMethod(this, &DecodedStreamGraphListener::DoNotifyFinished);
aGraph->DispatchToMainThreadAfterStreamStateUpdate(event.forget());
if (event == EVENT_FINISHED) {
nsCOMPtr<nsIRunnable> event =
NS_NewRunnableMethod(this, &DecodedStreamGraphListener::DoNotifyFinished);
aGraph->DispatchToMainThreadAfterStreamStateUpdate(event.forget());
}
}
void MediaDecoder::DestroyDecodedStream()
{
MOZ_ASSERT(NS_IsMainThread());

View File

@ -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();

View File

@ -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<MediaStreamListener> listener = mListeners[i].forget();
listener->NotifyRemoved(GraphImpl());
listener->NotifyEvent(GraphImpl(), MediaStreamListener::EVENT_REMOVED);
}
mListeners.Clear();
}
@ -2111,7 +2111,7 @@ MediaStream::AddListenerImpl(already_AddRefed<MediaStreamListener> 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<MediaStreamListener> 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

View File

@ -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,

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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 <string.h>
#include <binder/IPCThreadState.h>
namespace android {
sp<MediaCodecProxy>
MediaCodecProxy::CreateByType(sp<ALooper> aLooper,
const char *aMime,
bool aEncoder,
bool aAsync,
wp<CodecResourceListener> aListener)
{
sp<MediaCodecProxy> codec = new MediaCodecProxy(aLooper, aMime, aEncoder, aAsync, aListener);
if ((!aAsync && codec->allocated()) || codec->requestResource()) {
return codec;
}
return nullptr;
}
MediaCodecProxy::MediaCodecProxy(sp<ALooper> aLooper,
const char *aMime,
bool aEncoder,
bool aAsync,
wp<CodecResourceListener> 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<MediaCodec> 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<AMessage> &aFormat,
const sp<Surface> &aNativeWindow,
const sp<ICrypto> &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<AMessage> *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<sp<ABuffer>> *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<sp<ABuffer>> *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<AMessage> &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<CodecResourceListener> listener = mListener.promote();
if (listener != nullptr) {
listener->codecReserved();
}
}
// Called on a Binder thread
void
MediaCodecProxy::resourceCanceled()
{
// Release MediaCodec
releaseCodec();
// Notification
sp<CodecResourceListener> listener = mListener.promote();
if (listener != nullptr) {
listener->codecCanceled();
}
}
} // namespace android

View File

@ -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 <nsString.h>
#include <stagefright/MediaCodec.h>
#include <utils/threads.h>
#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<MediaCodecProxy> CreateByType(sp<ALooper> aLooper,
const char *aMime,
bool aEncoder,
bool aAsync=false,
wp<CodecResourceListener> aListener=nullptr);
// MediaCodec methods
status_t configure(const sp<AMessage> &aFormat,
const sp<Surface> &aNativeWindow,
const sp<ICrypto> &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<AMessage> *aFormat) const;
status_t getInputBuffers(Vector<sp<ABuffer>> *aBuffers) const;
status_t getOutputBuffers(Vector<sp<ABuffer>> *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<AMessage> &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> aLooper,
const char *aMime,
bool aEncoder,
bool aAsync,
wp<CodecResourceListener> aListener);
// Request Resource
bool requestResource();
// Cancel Resource
void cancelResource();
// Allocate Codec Resource
bool allocateCodec();
// Release Codec Resource
void releaseCodec();
// MediaCodec Parameter
sp<ALooper> mCodecLooper;
nsCString mCodecMime;
bool mCodecEncoder;
// Codec Resource Notification Listener
wp<CodecResourceListener> mListener;
// Media Resource Management
sp<MediaResourceHandler> mResourceHandler;
// MediaCodec instance
mutable RWLock mCodecLock;
sp<MediaCodec> mCodec;
};
} // namespace android
#endif // MEDIA_CODEC_PROXY_H

View File

@ -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

View File

@ -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<ResourceListener> &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<MediaResourceManagerClient> client = new MediaResourceManagerClient(this);
sp<IMediaResourceManagerService> 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<ResourceListener> 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

View File

@ -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 <utils/threads.h>
#include <mozilla/Attributes.h>
#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<ResourceListener> &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<ResourceListener> mListener;
// Resource Management
Mutex mLock;
MediaResourceManagerClient::State mState;
sp<IMediaResourceManagerClient> mClient;
sp<IMediaResourceManagerService> mService;
IMediaResourceManagerService::ResourceType mType;
};
} // namespace android
#endif // MEDIA_RESOURCE_HANDLER_H

View File

@ -16,6 +16,7 @@ SOURCES += [
'IMediaResourceManagerClient.cpp',
'IMediaResourceManagerDeathNotifier.cpp',
'IMediaResourceManagerService.cpp',
'MediaResourceHandler.cpp',
'MediaResourceManagerClient.cpp',
'MediaResourceManagerService.cpp',
]

View File

@ -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'

View File

@ -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.

View File

@ -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,

View File

@ -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);

View File

@ -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<layers::Image> mImage;
nsRefPtr<layers::ImageContainer> mImageContainer;
bool mHasDirectListeners;
nsTArray<SourceMediaStream *> 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,

View File

@ -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
}

View File

@ -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
}

View File

@ -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<typename SampleFormatType>

View File

@ -49,11 +49,23 @@ public:
}
}
virtual void NotifyFinished(MediaStreamGraph* aGraph)
virtual void NotifyEvent(MediaStreamGraph* aGraph,
MediaStreamListener::MediaStreamGraphEvent event) MOZ_OVERRIDE
{
nsCOMPtr<nsIRunnable> event =
NS_NewRunnableMethod(this, &SynthStreamListener::DoNotifyFinished);
aGraph->DispatchToMainThreadAfterStreamStateUpdate(event.forget());
switch (event) {
case EVENT_FINISHED:
{
nsCOMPtr<nsIRunnable> 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.

View File

@ -103,8 +103,7 @@ SVGEllipseElement::ConstructPath(gfxContext *aCtx)
RefPtr<PathBuilder> builder = dt->CreatePathBuilder(fillRule);
RefPtr<Path> path = BuildPath(builder);
if (path) {
nsRefPtr<gfxPath> gfxpath = new gfxPath(path);
aCtx->SetPath(gfxpath);
aCtx->SetPath(path);
}
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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();

View File

@ -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();
}
];

View File

@ -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<nsIURL> 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));
}

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -3079,16 +3079,6 @@ mozilla::dom::ShutdownJSEnvironment()
sDidShutdown = true;
}
class nsJSArgArray;
namespace mozilla {
template<>
struct HasDangerousPublicDestructor<nsJSArgArray>
{
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<JS::Value> *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<JS::Value *>(argv), &rv);
if (ret == nullptr)
return NS_ERROR_OUT_OF_MEMORY;
nsCOMPtr<nsIJSArgArray> ret = new nsJSArgArray(aContext, argc,
static_cast<JS::Value *>(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;
}

View File

@ -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;

View File

@ -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:

View File

@ -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<nsIDOMWindow> 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<nsIURI> 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<nsIURI> 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<nsIURI> 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<nsIURI> 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<nsIDOMWindow> 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<nsIDOMWindow> outer = mInnerWindow->GetOuterWindow();
if (MOZ_UNLIKELY(!outer))
return false;
nsCOMPtr<nsIScriptObjectPrincipal> 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);
}

View File

@ -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<nsPIDOMWindow> mInnerWindow;
nsWeakPtr mDocShell;
nsWeakPtr mOuter;
};
#endif // nsLocation_h__

View File

@ -86,10 +86,13 @@ ThrowInvalidThis(JSContext* aCx, const JS::CallArgs& aArgs,
MOZ_ASSERT(func);
JS::Rooted<JSString*> funcName(aCx, JS_GetFunctionDisplayId(func));
MOZ_ASSERT(funcName);
nsAutoJSString funcNameStr;
if (!funcNameStr.init(aCx, funcName)) {
return false;
}
JS_ReportErrorNumberUC(aCx, GetErrorMessage, nullptr,
static_cast<const unsigned>(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<JSObject*> wrapper,
return true;
}
static bool
XrayResolveMethod(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
const Prefable<const JSFunctionSpec>* methods,
jsid* methodIds,
const JSFunctionSpec* methodsSpecs,
JS::MutableHandle<JSPropertyDescriptor> desc)
{
const Prefable<const JSFunctionSpec>* 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<JSObject*> wrapper,
JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> 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<JSObject*> wrapper,
methodsSpecs = nativeProperties->methodsSpecs;
}
if (methods) {
const Prefable<const JSFunctionSpec>* 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;
}
}

View File

@ -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);

View File

@ -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': {

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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
// <iframe mozbrowser> window.
@ -526,41 +537,67 @@ BrowserElementChild.prototype = {
return;
}
debug('Got metaAdded: (' + e.target.name + ') ' + e.target.content);
if (e.target.name == 'application-name') {
let meta = { name: e.target.name,
content: e.target.content };
debug('Got metaChanged: (' + e.target.name + ') ' + e.target.content);
let lang;
let elm;
let handlers = {
'theme-color': this._themeColorChangedHandler,
'application-name': this._applicationNameChangedHandler
};
for (elm = e.target;
!lang && elm && elm.nodeType == e.target.ELEMENT_NODE;
elm = elm.parentNode) {
if (elm.hasAttribute('lang')) {
lang = elm.getAttribute('lang');
continue;
}
if (elm.hasAttributeNS('http://www.w3.org/XML/1998/namespace', 'lang')) {
lang = elm.getAttributeNS('http://www.w3.org/XML/1998/namespace', 'lang');
continue;
}
}
// No lang has been detected.
if (!lang && elm.nodeType == e.target.DOCUMENT_NODE) {
lang = elm.contentLanguage;
}
if (lang) {
meta.lang = lang;
}
sendAsyncMsg('metachange', meta);
let handler = handlers[e.target.name];
if (handler) {
handler(e.type, e.target);
}
},
_applicationNameChangedHandler: function(eventType, target) {
if (eventType !== 'DOMMetaAdded') {
// Bug 1037448 - Decide what to do when <meta name="application-name">
// changes
return;
}
let meta = { name: 'application-name',
content: target.content };
let lang;
let elm;
for (elm = target;
!lang && elm && elm.nodeType == target.ELEMENT_NODE;
elm = elm.parentNode) {
if (elm.hasAttribute('lang')) {
lang = elm.getAttribute('lang');
continue;
}
if (elm.hasAttributeNS('http://www.w3.org/XML/1998/namespace', 'lang')) {
lang = elm.getAttributeNS('http://www.w3.org/XML/1998/namespace', 'lang');
continue;
}
}
// No lang has been detected.
if (!lang && elm.nodeType == target.DOCUMENT_NODE) {
lang = elm.contentLanguage;
}
if (lang) {
meta.lang = lang;
}
sendAsyncMsg('metachange', meta);
},
_themeColorChangedHandler: function(eventType, target) {
let meta = {
name: 'theme-color',
content: target.content,
type: eventType.replace('DOMMeta', '').toLowerCase()
};
sendAsyncMsg('metachange', meta);
},
_addMozAfterPaintHandler: function(callback) {
function onMozAfterPaint() {
let uri = docShell.QueryInterface(Ci.nsIWebNavigation).currentURI;

View File

@ -0,0 +1,71 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that the onmozbrowsermetachange event for theme-color works.
"use strict";
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
function runTest() {
function loadFrameScript(script) {
SpecialPowers.getBrowserFrameMessageManager(iframe1)
.loadFrameScript("data:," + script,
/* allowDelayedLoad = */ false);
}
let iframe1 = document.createElement('iframe');
SpecialPowers.wrap(iframe1).mozbrowser = true;
iframe1.src = "http://test/tests/dom/browser-element/mochitest/file_browserElement_ThemeColor.html";
iframe1.addEventListener('mozbrowsermetachange', tests);
document.body.appendChild(iframe1);
let numMetaChanges = 0;
function tests(e) {
let detail = e.detail;
switch (numMetaChanges++) {
case 0: {
is(detail.name, 'theme-color', 'name matches');
is(detail.content, 'pink', 'content matches');
is(detail.type, 'added', 'type matches');
let script =
"var meta = content.document.head.querySelector('meta');" +
"meta.content = 'green';";
loadFrameScript(script);
break;
}
case 1: {
is(detail.name, 'theme-color', 'name matches');
is(detail.content, 'green', 'content matches');
is(detail.type, 'changed', 'type matches');
let script =
"var meta = content.document.head.querySelector('meta');" +
"meta.parentNode.removeChild(meta);";
loadFrameScript(script);
break;
}
case 2: {
is(detail.name, 'theme-color', 'name matches');
is(detail.content, 'green', 'content matches');
is(detail.type, 'removed', 'type matches');
SimpleTest.finish();
break;
}
default: {
ok(false, 'Too many metachange events.');
break;
}
}
};
}
window.addEventListener('testready', runTest);

View File

@ -0,0 +1,8 @@
<html>
<head>
<meta name="theme-color" content="pink">
</head>
<body>
</body>
</html>

View File

@ -8,6 +8,7 @@ support-files =
browserElement_OpenMixedProcess.js
file_browserElement_OpenMixedProcess.html
[test_browserElement_oop_ThemeColor.html]
[test_browserElement_inproc_ErrorSecurity.html]
skip-if = toolkit=='gonk'
[test_browserElement_inproc_OpenMixedProcess.html]

View File

@ -11,6 +11,7 @@ support-files =
browserElement_Auth.js
browserElement_BackForward.js
browserElement_BadScreenshot.js
browserElement_ThemeColor.js
browserElement_BrowserWindowNamespace.js
browserElement_BrowserWindowResize.js
browserElement_Close.js
@ -68,6 +69,7 @@ support-files =
file_browserElement_AlertInFrame_Inner.html
file_browserElement_AppFramePermission.html
file_browserElement_AppWindowNamespace.html
file_browserElement_ThemeColor.html
file_browserElement_BrowserWindowNamespace.html
file_browserElement_CloseApp.html
file_browserElement_CloseFromOpener.html
@ -113,6 +115,7 @@ support-files =
[test_browserElement_NoPref.html]
[test_browserElement_NoPermission.html]
[test_browserElement_inproc_Alert.html]
[test_browserElement_inproc_ThemeColor.html]
skip-if = buildapp == 'b2g'
[test_browserElement_inproc_AlertInFrame.html]
[test_browserElement_inproc_AppFramePermission.html]

View File

@ -0,0 +1,19 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1013913
-->
<head>
<title>Test for Bug 1013913</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1013913">Mozilla Bug 1013913</a>
<script type="application/javascript;version=1.7" src="browserElement_ThemeColor.js">
</script>
</body>
</html>

View File

@ -0,0 +1,19 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1013913
-->
<head>
<title>Test for Bug 1013913</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1013913">Mozilla Bug 1013913</a>
<script type="application/javascript;version=1.7" src="browserElement_ThemeColor.js">
</script>
</body>
</html>

View File

@ -103,7 +103,7 @@ CameraPreviewMediaStream::RemoveListener(MediaStreamListener* aListener)
MediaStreamGraph* gm = MediaStreamGraph::GetInstance();
nsRefPtr<MediaStreamListener> listener(aListener);
mListeners.RemoveElement(aListener);
listener->NotifyRemoved(gm);
listener->NotifyEvent(gm, MediaStreamListener::EVENT_REMOVED);
}
void

View File

@ -7,18 +7,17 @@
#ifndef mozilla_dom_AesKeyAlgorithm_h
#define mozilla_dom_AesKeyAlgorithm_h
#include "mozilla/dom/KeyAlgorithm.h"
#include "mozilla/dom/BasicSymmetricKeyAlgorithm.h"
#include "js/TypeDecls.h"
namespace mozilla {
namespace dom {
class AesKeyAlgorithm MOZ_FINAL : public KeyAlgorithm
class AesKeyAlgorithm MOZ_FINAL : public BasicSymmetricKeyAlgorithm
{
public:
AesKeyAlgorithm(nsIGlobalObject* aGlobal, const nsString& aName, uint16_t aLength)
: KeyAlgorithm(aGlobal, aName)
, mLength(aLength)
: BasicSymmetricKeyAlgorithm(aGlobal, aName, aLength)
{}
~AesKeyAlgorithm()
@ -26,17 +25,9 @@ public:
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
uint16_t Length() const
{
return mLength;
}
virtual bool WriteStructuredClone(JSStructuredCloneWriter* aWriter) const MOZ_OVERRIDE;
static KeyAlgorithm* Create(nsIGlobalObject* aGlobal,
JSStructuredCloneReader* aReader);
protected:
uint16_t mLength;
};
} // namespace dom

View File

@ -0,0 +1,38 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_BasicSymmetricKeyAlgorithm_h
#define mozilla_dom_BasicSymmetricKeyAlgorithm_h
#include "mozilla/dom/KeyAlgorithm.h"
namespace mozilla {
namespace dom {
class BasicSymmetricKeyAlgorithm : public KeyAlgorithm
{
public:
BasicSymmetricKeyAlgorithm(nsIGlobalObject* aGlobal, const nsString& aName, uint16_t aLength)
: KeyAlgorithm(aGlobal, aName)
, mLength(aLength)
{}
~BasicSymmetricKeyAlgorithm()
{}
uint16_t Length() const
{
return mLength;
}
protected:
uint16_t mLength;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_BasicSymmetricKeyAlgorithm_h

View File

@ -32,27 +32,8 @@ KeyAlgorithm::KeyAlgorithm(nsIGlobalObject* aGlobal, const nsString& aName)
SetIsDOMBinding();
// Set mechanism based on algorithm name
if (mName.EqualsLiteral(WEBCRYPTO_ALG_AES_CBC)) {
mMechanism = CKM_AES_CBC_PAD;
} else if (mName.EqualsLiteral(WEBCRYPTO_ALG_AES_CTR)) {
mMechanism = CKM_AES_CTR;
} else if (mName.EqualsLiteral(WEBCRYPTO_ALG_AES_GCM)) {
mMechanism = CKM_AES_GCM;
} else if (mName.EqualsLiteral(WEBCRYPTO_ALG_SHA1)) {
mMechanism = CKM_SHA_1;
} else if (mName.EqualsLiteral(WEBCRYPTO_ALG_SHA256)) {
mMechanism = CKM_SHA256;
} else if (mName.EqualsLiteral(WEBCRYPTO_ALG_SHA384)) {
mMechanism = CKM_SHA384;
} else if (mName.EqualsLiteral(WEBCRYPTO_ALG_SHA512)) {
mMechanism = CKM_SHA512;
} else if (mName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1)) {
mMechanism = CKM_RSA_PKCS;
} else if (mName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
mMechanism = CKM_RSA_PKCS;
} else {
mMechanism = UNKNOWN_CK_MECHANISM;
}
mMechanism = MapAlgorithmNameToMechanism(aName);
// HMAC not handled here, since it requires extra info
}

View File

@ -21,6 +21,7 @@
#define WEBCRYPTO_ALG_SHA384 "SHA-384"
#define WEBCRYPTO_ALG_SHA512 "SHA-512"
#define WEBCRYPTO_ALG_HMAC "HMAC"
#define WEBCRYPTO_ALG_PBKDF2 "PBKDF2"
#define WEBCRYPTO_ALG_RSAES_PKCS1 "RSAES-PKCS1-v1_5"
#define WEBCRYPTO_ALG_RSASSA_PKCS1 "RSASSA-PKCS1-v1_5"
@ -119,6 +120,37 @@ WriteBuffer(JSStructuredCloneWriter* aWriter, const CryptoBuffer& aBuffer)
return ret;
}
inline CK_MECHANISM_TYPE
MapAlgorithmNameToMechanism(const nsString& aName)
{
CK_MECHANISM_TYPE mechanism(UNKNOWN_CK_MECHANISM);
// Set mechanism based on algorithm name
if (aName.EqualsLiteral(WEBCRYPTO_ALG_AES_CBC)) {
mechanism = CKM_AES_CBC_PAD;
} else if (aName.EqualsLiteral(WEBCRYPTO_ALG_AES_CTR)) {
mechanism = CKM_AES_CTR;
} else if (aName.EqualsLiteral(WEBCRYPTO_ALG_AES_GCM)) {
mechanism = CKM_AES_GCM;
} else if (aName.EqualsLiteral(WEBCRYPTO_ALG_SHA1)) {
mechanism = CKM_SHA_1;
} else if (aName.EqualsLiteral(WEBCRYPTO_ALG_SHA256)) {
mechanism = CKM_SHA256;
} else if (aName.EqualsLiteral(WEBCRYPTO_ALG_SHA384)) {
mechanism = CKM_SHA384;
} else if (aName.EqualsLiteral(WEBCRYPTO_ALG_SHA512)) {
mechanism = CKM_SHA512;
} else if (aName.EqualsLiteral(WEBCRYPTO_ALG_PBKDF2)) {
mechanism = CKM_PKCS5_PBKD2;
} else if (aName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1)) {
mechanism = CKM_RSA_PKCS;
} else if (aName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
mechanism = CKM_RSA_PKCS;
}
return mechanism;
}
} // namespace dom
} // namespace mozilla

View File

@ -148,6 +148,78 @@ Coerce(JSContext* aCx, T& aTarget, const OOS& aAlgorithm)
return NS_OK;
}
inline size_t
MapHashAlgorithmNameToBlockSize(const nsString& aName)
{
if (aName.EqualsLiteral(WEBCRYPTO_ALG_SHA1) ||
aName.EqualsLiteral(WEBCRYPTO_ALG_SHA256)) {
return 512;
}
if (aName.EqualsLiteral(WEBCRYPTO_ALG_SHA384) ||
aName.EqualsLiteral(WEBCRYPTO_ALG_SHA512)) {
return 1024;
}
return 0;
}
inline nsresult
GetKeySizeForAlgorithm(JSContext* aCx, const ObjectOrString& aAlgorithm,
size_t& aLength)
{
aLength = 0;
// Extract algorithm name
nsString algName;
if (NS_FAILED(GetAlgorithmName(aCx, aAlgorithm, algName))) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
// Read AES key length from given algorithm object.
if (algName.EqualsLiteral(WEBCRYPTO_ALG_AES_CBC) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_AES_CTR) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_AES_GCM)) {
RootedDictionary<AesKeyGenParams> params(aCx);
if (NS_FAILED(Coerce(aCx, params, aAlgorithm)) ||
!params.mLength.WasPassed()) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
size_t length = params.mLength.Value();
if (length != 128 && length != 192 && length != 256) {
return NS_ERROR_DOM_DATA_ERR;
}
aLength = length;
return NS_OK;
}
// Determine HMAC key length as the block size of the given hash.
if (algName.EqualsLiteral(WEBCRYPTO_ALG_HMAC)) {
RootedDictionary<HmacImportParams> params(aCx);
if (NS_FAILED(Coerce(aCx, params, aAlgorithm)) ||
!params.mHash.WasPassed()) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
nsString hashName;
if (NS_FAILED(GetAlgorithmName(aCx, params.mHash.Value(), hashName))) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
size_t length = MapHashAlgorithmNameToBlockSize(hashName);
if (length == 0) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
aLength = length;
return NS_OK;
}
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
// Implementation of WebCryptoTask methods
void
@ -828,10 +900,12 @@ public:
mKeyData.Assign(aKeyData.GetAsArrayBufferView());
} else if (aKeyData.IsArrayBuffer()) {
mKeyData.Assign(aKeyData.GetAsArrayBuffer());
} else {
mEarlyRv = NS_ERROR_DOM_DATA_ERR;
return;
}
// We would normally fail here if the key data is not an ArrayBuffer or
// an ArrayBufferView but let's wait for BeforeCrypto() to be called in
// case PBKDF2's deriveKey() operation passed dummy key data. When that
// happens DerivePbkdfKeyTask is responsible for calling SetKeyData()
// itself before this task is actually run.
} else if (aFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_JWK)) {
mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
return;
@ -859,6 +933,11 @@ public:
virtual nsresult BeforeCrypto() MOZ_OVERRIDE
{
// Check that we have valid key data.
if (mKeyData.Length() == 0) {
return NS_ERROR_DOM_DATA_ERR;
}
// Construct an appropriate KeyAlorithm,
// and verify that usages are appropriate
nsRefPtr<KeyAlgorithm> algorithm;
@ -875,6 +954,11 @@ public:
return NS_ERROR_DOM_DATA_ERR;
}
algorithm = new AesKeyAlgorithm(global, mAlgName, length);
} else if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_PBKDF2)) {
if (mKey->HasUsageOtherThan(CryptoKey::DERIVEKEY)) {
return NS_ERROR_DOM_DATA_ERR;
}
algorithm = new BasicSymmetricKeyAlgorithm(global, mAlgName, length);
} else if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_HMAC)) {
if (mKey->HasUsageOtherThan(CryptoKey::SIGN | CryptoKey::VERIFY)) {
return NS_ERROR_DOM_DATA_ERR;
@ -895,6 +979,12 @@ public:
return NS_OK;
}
void SetKeyData(const CryptoBuffer& aKeyData)
{
// An OOM will just result in an error in BeforeCrypto
mKeyData = aKeyData;
}
private:
CryptoBuffer mKeyData;
nsString mHashName;
@ -1129,16 +1219,8 @@ public:
if (algName.EqualsLiteral(WEBCRYPTO_ALG_AES_CBC) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_AES_CTR) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_AES_GCM)) {
RootedDictionary<AesKeyGenParams> params(aCx);
mEarlyRv = Coerce(aCx, params, aAlgorithm);
if (NS_FAILED(mEarlyRv) || !params.mLength.WasPassed()) {
mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
return;
}
mLength = params.mLength.Value();
if (mLength != 128 && mLength != 192 && mLength != 256) {
mEarlyRv = NS_ERROR_DOM_DATA_ERR;
mEarlyRv = GetKeySizeForAlgorithm(aCx, aAlgorithm, mLength);
if (NS_FAILED(mEarlyRv)) {
return;
}
algorithm = new AesKeyAlgorithm(global, algName, mLength);
@ -1167,20 +1249,7 @@ public:
if (params.mLength.WasPassed()) {
mLength = params.mLength.Value();
} else {
nsRefPtr<KeyAlgorithm> hashAlg = new KeyAlgorithm(global, hashName);
switch (hashAlg->Mechanism()) {
case CKM_SHA_1:
case CKM_SHA256:
mLength = 512;
break;
case CKM_SHA384:
case CKM_SHA512:
mLength = 1024;
break;
default:
mLength = 0;
break;
}
mLength = MapHashAlgorithmNameToBlockSize(hashName);
}
if (mLength == 0) {
@ -1421,6 +1490,160 @@ private:
}
};
class DerivePbkdfBitsTask : public ReturnArrayBufferViewTask
{
public:
DerivePbkdfBitsTask(JSContext* aCx,
const ObjectOrString& aAlgorithm, CryptoKey& aKey, uint32_t aLength)
: mSymKey(aKey.GetSymKey())
{
Init(aCx, aAlgorithm, aKey, aLength);
}
DerivePbkdfBitsTask(JSContext* aCx, const ObjectOrString& aAlgorithm,
CryptoKey& aKey, const ObjectOrString& aTargetAlgorithm)
: mSymKey(aKey.GetSymKey())
{
size_t length;
mEarlyRv = GetKeySizeForAlgorithm(aCx, aTargetAlgorithm, length);
if (NS_SUCCEEDED(mEarlyRv)) {
Init(aCx, aAlgorithm, aKey, length);
}
}
void Init(JSContext* aCx, const ObjectOrString& aAlgorithm, CryptoKey& aKey,
uint32_t aLength)
{
// Check that we got a symmetric key
if (mSymKey.Length() == 0) {
mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
return;
}
RootedDictionary<Pbkdf2Params> params(aCx);
mEarlyRv = Coerce(aCx, params, aAlgorithm);
if (NS_FAILED(mEarlyRv) || !params.mHash.WasPassed() ||
!params.mIterations.WasPassed() || !params.mSalt.WasPassed()) {
mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
return;
}
// length must be a multiple of 8 bigger than zero.
if (aLength == 0 || aLength % 8) {
mEarlyRv = NS_ERROR_DOM_DATA_ERR;
return;
}
// Extract the hash algorithm.
nsString hashName;
mEarlyRv = GetAlgorithmName(aCx, params.mHash.Value(), hashName);
if (NS_FAILED(mEarlyRv)) {
return;
}
// Check the given hash algorithm.
switch (MapAlgorithmNameToMechanism(hashName)) {
case CKM_SHA_1: mHashOidTag = SEC_OID_HMAC_SHA1; break;
case CKM_SHA256: mHashOidTag = SEC_OID_HMAC_SHA256; break;
case CKM_SHA384: mHashOidTag = SEC_OID_HMAC_SHA384; break;
case CKM_SHA512: mHashOidTag = SEC_OID_HMAC_SHA512; break;
default: {
mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
return;
}
}
ATTEMPT_BUFFER_INIT(mSalt, params.mSalt.Value())
mLength = aLength >> 3; // bits to bytes
mIterations = params.mIterations.Value();
}
private:
size_t mLength;
size_t mIterations;
CryptoBuffer mSalt;
CryptoBuffer mSymKey;
SECOidTag mHashOidTag;
virtual nsresult DoCrypto() MOZ_OVERRIDE
{
ScopedSECItem salt;
ATTEMPT_BUFFER_TO_SECITEM(salt, mSalt);
// Always pass in cipherAlg=SEC_OID_HMAC_SHA1 (i.e. PBMAC1) as this
// parameter is unused for key generation. It is currently only used
// for PBKDF2 authentication or key (un)wrapping when specifying an
// encryption algorithm (PBES2).
ScopedSECAlgorithmID alg_id(PK11_CreatePBEV2AlgorithmID(
SEC_OID_PKCS5_PBKDF2, SEC_OID_HMAC_SHA1, mHashOidTag,
mLength, mIterations, salt));
if (!alg_id.get()) {
return NS_ERROR_DOM_OPERATION_ERR;
}
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
if (!slot.get()) {
return NS_ERROR_DOM_OPERATION_ERR;
}
ScopedSECItem keyItem;
ATTEMPT_BUFFER_TO_SECITEM(keyItem, mSymKey);
ScopedPK11SymKey symKey(PK11_PBEKeyGen(slot, alg_id, keyItem, false, nullptr));
if (!symKey.get()) {
return NS_ERROR_DOM_OPERATION_ERR;
}
nsresult rv = MapSECStatus(PK11_ExtractKeyValue(symKey));
if (NS_FAILED(rv)) {
return NS_ERROR_DOM_OPERATION_ERR;
}
// This doesn't leak, because the SECItem* returned by PK11_GetKeyData
// just refers to a buffer managed by symKey. The assignment copies the
// data, so mResult manages one copy, while symKey manages another.
ATTEMPT_BUFFER_ASSIGN(mResult, PK11_GetKeyData(symKey));
return NS_OK;
}
};
class DerivePbkdfKeyTask : public DerivePbkdfBitsTask
{
public:
DerivePbkdfKeyTask(JSContext* aCx,
const ObjectOrString& aAlgorithm, CryptoKey& aBaseKey,
const ObjectOrString& aDerivedKeyType, bool aExtractable,
const Sequence<nsString>& aKeyUsages)
: DerivePbkdfBitsTask(aCx, aAlgorithm, aBaseKey, aDerivedKeyType)
{
if (NS_FAILED(mEarlyRv)) {
return;
}
CryptoOperationData dummy;
NS_NAMED_LITERAL_STRING(format, WEBCRYPTO_KEY_FORMAT_RAW);
mTask = new ImportSymmetricKeyTask(aCx, format, dummy, aDerivedKeyType,
aExtractable, aKeyUsages);
}
protected:
nsRefPtr<ImportSymmetricKeyTask> mTask;
private:
virtual void Resolve() MOZ_OVERRIDE {
mTask->SetKeyData(mResult);
mTask->DispatchWithPromise(mResultPromise);
}
virtual void Cleanup() MOZ_OVERRIDE
{
mTask = nullptr;
}
};
// Task creation methods for WebCryptoTask
@ -1520,6 +1743,7 @@ WebCryptoTask::ImportKeyTask(JSContext* aCx,
if (algName.EqualsLiteral(WEBCRYPTO_ALG_AES_CBC) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_AES_CTR) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_AES_GCM) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_PBKDF2) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_HMAC)) {
return new ImportSymmetricKeyTask(aCx, aFormat, aKeyData, aAlgorithm,
aExtractable, aKeyUsages);
@ -1582,6 +1806,18 @@ WebCryptoTask::DeriveKeyTask(JSContext* aCx,
const Sequence<nsString>& aKeyUsages)
{
Telemetry::Accumulate(Telemetry::WEBCRYPTO_METHOD, TM_DERIVEKEY);
nsString algName;
nsresult rv = GetAlgorithmName(aCx, aAlgorithm, algName);
if (NS_FAILED(rv)) {
return new FailureTask(rv);
}
if (algName.EqualsASCII(WEBCRYPTO_ALG_PBKDF2)) {
return new DerivePbkdfKeyTask(aCx, aAlgorithm, aBaseKey, aDerivedKeyType,
aExtractable, aKeyUsages);
}
return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
}
@ -1592,6 +1828,17 @@ WebCryptoTask::DeriveBitsTask(JSContext* aCx,
uint32_t aLength)
{
Telemetry::Accumulate(Telemetry::WEBCRYPTO_METHOD, TM_DERIVEBITS);
nsString algName;
nsresult rv = GetAlgorithmName(aCx, aAlgorithm, algName);
if (NS_FAILED(rv)) {
return new FailureTask(rv);
}
if (algName.EqualsASCII(WEBCRYPTO_ALG_PBKDF2)) {
return new DerivePbkdfBitsTask(aCx, aAlgorithm, aKey, aLength);
}
return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
}

View File

@ -8,6 +8,7 @@ TEST_DIRS += ['test']
EXPORTS.mozilla.dom += [
'AesKeyAlgorithm.h',
'BasicSymmetricKeyAlgorithm.h',
'CryptoBuffer.h',
'CryptoKey.h',
'CryptoKeyPair.h',

View File

@ -310,4 +310,29 @@ tv = {
"bcf51540afd0174db4033188556675b1d763360af46feeca5b60f882829ee7b2"
),
},
// RFC 6070 <http://tools.ietf.org/html/rfc6070>
pbkdf2_sha1: {
password: new TextEncoder("utf-8").encode("passwordPASSWORDpassword"),
salt: new TextEncoder("utf-8").encode("saltSALTsaltSALTsaltSALTsaltSALTsalt"),
iterations: 4096,
length: 25 * 8,
derived: util.hex2abv(
"3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038"
)
},
// https://stackoverflow.com/questions/5130513/pbkdf2-hmac-sha2-test-vectors
pbkdf2_sha256: {
password: new TextEncoder("utf-8").encode("passwordPASSWORDpassword"),
salt: new TextEncoder("utf-8").encode("saltSALTsaltSALTsaltSALTsaltSALTsalt"),
iterations: 4096,
length: 40 * 8,
derived: util.hex2abv(
"348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4e2a1fb8dd53e1" +
"c635518c7dac47e9"
)
},
}

View File

@ -1018,4 +1018,135 @@ TestArray.addTest(
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"Import raw PBKDF2 key",
function() {
var that = this;
var alg = "PBKDF2";
var key = new TextEncoder("utf-8").encode("password");
crypto.subtle.importKey("raw", key, alg, false, ["deriveKey"]).then(
complete(that, hasKeyFields),
error(that)
);
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"Import raw PBKDF2 key and derive bits using HMAC-SHA-1",
function() {
var that = this;
var alg = "PBKDF2";
var key = tv.pbkdf2_sha1.password;
function doDerive(x) {
console.log("deriving");
if (!hasKeyFields(x)) {
throw "Invalid key; missing field(s)";
}
var alg = {
name: "PBKDF2",
hash: "SHA-1",
salt: tv.pbkdf2_sha1.salt,
iterations: tv.pbkdf2_sha1.iterations
};
return crypto.subtle.deriveBits(alg, x, tv.pbkdf2_sha1.length);
}
function fail(x) { console.log("failing"); error(that)(x); }
crypto.subtle.importKey("raw", key, alg, false, ["deriveKey"])
.then( doDerive, fail )
.then( memcmp_complete(that, tv.pbkdf2_sha1.derived), fail );
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"Import raw PBKDF2 key and derive a new key using HMAC-SHA-1",
function() {
var that = this;
var alg = "PBKDF2";
var key = tv.pbkdf2_sha1.password;
function doDerive(x) {
console.log("deriving");
if (!hasKeyFields(x)) {
throw "Invalid key; missing field(s)";
}
var alg = {
name: "PBKDF2",
hash: "SHA-1",
salt: tv.pbkdf2_sha1.salt,
iterations: tv.pbkdf2_sha1.iterations
};
var algDerived = {
name: "HMAC",
hash: {name: "SHA-1"}
};
return crypto.subtle.deriveKey(alg, x, algDerived, false, ["sign", "verify"])
.then(function (x) {
if (!hasKeyFields(x)) {
throw "Invalid key; missing field(s)";
}
if (x.algorithm.length != 512) {
throw "Invalid key; incorrect length";
}
return x;
});
}
function doSignAndVerify(x) {
var data = new Uint8Array(1024);
return crypto.subtle.sign("HMAC", x, data)
.then(function (sig) {
return crypto.subtle.verify("HMAC", x, sig, data);
});
}
function fail(x) { console.log("failing"); error(that)(x); }
crypto.subtle.importKey("raw", key, alg, false, ["deriveKey"])
.then( doDerive, fail )
.then( doSignAndVerify, fail )
.then( complete(that), fail );
}
);
// -----------------------------------------------------------------------------
/*TestArray.addTest(
"Import raw PBKDF2 key and derive bits using HMAC-SHA-256",
function() {
var that = this;
var alg = "PBKDF2";
var key = tv.pbkdf2_sha256.password;
function doDerive(x) {
console.log("deriving");
if (!hasKeyFields(x)) {
throw "Invalid key; missing field(s)";
}
var alg = {
name: "PBKDF2",
hash: "SHA-256",
salt: tv.pbkdf2_sha256.salt,
iterations: tv.pbkdf2_sha256.iterations
};
return crypto.subtle.deriveBits(alg, x, tv.pbkdf2_sha256.length);
}
function fail(x) { console.log("failing"); error(that)(x); }
crypto.subtle.importKey("raw", key, alg, false, ["deriveKey"])
.then( doDerive, fail )
.then( memcmp_complete(that, tv.pbkdf2_sha256.derived), fail );
}
);*/

View File

@ -5,7 +5,7 @@
#include "domstubs.idl"
[uuid(d9539ecb-6665-452c-bae7-4e42f25d23aa)]
[uuid(44ef0b7e-92c0-48a7-a092-5a49f2533792)]
interface nsIServiceWorkerManager : nsISupports
{
// Returns a Promise
@ -14,6 +14,8 @@ interface nsIServiceWorkerManager : nsISupports
// Returns a Promise
nsISupports unregister(in nsIDOMWindow aWindow, in DOMString aScope);
// Testing
DOMString getScopeForUrl(in DOMString path);
};
%{ C++

View File

@ -8,7 +8,6 @@ XPIDL_SOURCES += [
'nsIDOMHTMLAnchorElement.idl',
'nsIDOMHTMLAppletElement.idl',
'nsIDOMHTMLAreaElement.idl',
'nsIDOMHTMLAudioElement.idl',
'nsIDOMHTMLBaseElement.idl',
'nsIDOMHTMLBodyElement.idl',
'nsIDOMHTMLBRElement.idl',
@ -58,7 +57,6 @@ XPIDL_SOURCES += [
'nsIDOMHTMLTextAreaElement.idl',
'nsIDOMHTMLTitleElement.idl',
'nsIDOMHTMLUListElement.idl',
'nsIDOMHTMLVideoElement.idl',
'nsIDOMMediaError.idl',
'nsIDOMMozBrowserFrame.idl',
'nsIDOMTimeRanges.idl',

View File

@ -1,22 +0,0 @@
/* -*- 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 "nsIDOMHTMLMediaElement.idl"
/**
* The nsIDOMHTMLAudioElement interface is the interface to a HTML
* <audio> element.
*
* For more information on this interface, please see
* http://www.whatwg.org/specs/web-apps/current-work/#audio
*
* @status UNDER_DEVELOPMENT
*/
[uuid(75a7f3ca-0761-4b63-863b-6fd6a87ed51c)]
interface nsIDOMHTMLAudioElement : nsIDOMHTMLMediaElement
{
};

View File

@ -27,7 +27,7 @@ interface nsIDOMMediaStream;
#endif
%}
[uuid(1f9393e8-2df0-4072-87b9-c26999b09acc)]
[uuid(0e14e6ad-2074-48b7-a247-e545a3a15131)]
interface nsIDOMHTMLMediaElement : nsISupports
{
// error state
@ -133,4 +133,6 @@ interface nsIDOMHTMLMediaElement : nsISupports
// * onmozinterruptbegin - called when the media element is interrupted
// because of the audiochannel manager.
// * onmozinterruptend - called when the interruption is concluded
[notxpcom] boolean isVideo();
};

View File

@ -1,50 +0,0 @@
/* -*- 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 "nsIDOMHTMLMediaElement.idl"
/**
* The nsIDOMHTMLVideoElement interface is the interface to a HTML
* <video> element.
*
* For more information on this interface, please see
* http://www.whatwg.org/specs/web-apps/current-work/#video
*
* @status UNDER_DEVELOPMENT
*/
[uuid(185a3e8f-56a7-4bda-8dc7-2cff6ed07d1d)]
interface nsIDOMHTMLVideoElement : nsIDOMHTMLMediaElement
{
attribute long width;
attribute long height;
readonly attribute unsigned long videoWidth;
readonly attribute unsigned long videoHeight;
attribute DOMString poster;
// A count of the number of video frames that have demuxed from the media
// resource. If we were playing perfectly, we'd be able to paint this many
// frames.
readonly attribute unsigned long mozParsedFrames;
// A count of the number of frames that have been decoded. We may drop
// frames if the decode is taking too much time.
readonly attribute unsigned long mozDecodedFrames;
// A count of the number of frames that have been presented to the rendering
// pipeline. We may drop frames if they arrive late at the renderer.
readonly attribute unsigned long mozPresentedFrames;
// Number of presented frames which were painted on screen.
readonly attribute unsigned long mozPaintedFrames;
// Time which the last painted video frame was late by, in seconds.
readonly attribute double mozFrameDelay;
// True if the video has an audio track available.
readonly attribute bool mozHasAudio;
};

View File

@ -2037,6 +2037,19 @@ GetUserMediaCallbackMediaStreamListener::NotifyFinished(MediaStreamGraph* aGraph
NS_DispatchToMainThread(new GetUserMediaListenerRemove(mWindowID, this));
}
// Called from the MediaStreamGraph thread
void
GetUserMediaCallbackMediaStreamListener::NotifyDirectListeners(MediaStreamGraph* aGraph,
bool aHasListeners)
{
nsRefPtr<MediaOperationRunnable> runnable;
runnable = new MediaOperationRunnable(MEDIA_DIRECT_LISTENERS,
this, nullptr, nullptr,
mAudioSource, mVideoSource,
aHasListeners, mWindowID, nullptr);
mMediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
}
// Called from the MediaStreamGraph thread
// this can be in response to our own RemoveListener() (via ::Remove()), or
// because the DOM GC'd the DOMLocalMediaStream/etc we're attached to.

View File

@ -175,10 +175,35 @@ public:
}
virtual void
NotifyFinished(MediaStreamGraph* aGraph) MOZ_OVERRIDE;
NotifyEvent(MediaStreamGraph* aGraph,
MediaStreamListener::MediaStreamGraphEvent aEvent) MOZ_OVERRIDE
{
switch (aEvent) {
case EVENT_FINISHED:
NotifyFinished(aGraph);
break;
case EVENT_REMOVED:
NotifyRemoved(aGraph);
break;
case EVENT_HAS_DIRECT_LISTENERS:
NotifyDirectListeners(aGraph, true);
break;
case EVENT_HAS_NO_DIRECT_LISTENERS:
NotifyDirectListeners(aGraph, false);
break;
default:
break;
}
}
virtual void
NotifyRemoved(MediaStreamGraph* aGraph) MOZ_OVERRIDE;
NotifyFinished(MediaStreamGraph* aGraph);
virtual void
NotifyRemoved(MediaStreamGraph* aGraph);
virtual void
NotifyDirectListeners(MediaStreamGraph* aGraph, bool aHasListeners);
private:
// Set at construction
@ -244,7 +269,8 @@ class GetUserMediaNotificationEvent: public nsRunnable
typedef enum {
MEDIA_START,
MEDIA_STOP
MEDIA_STOP,
MEDIA_DIRECT_LISTENERS
} MediaOperation;
class MediaManager;
@ -299,7 +325,7 @@ public:
DOMMediaStream::OnTracksAvailableCallback* aOnTracksAvailableCallback,
MediaEngineSource* aAudioSource,
MediaEngineSource* aVideoSource,
bool aNeedsFinish,
bool aBool,
uint64_t aWindowID,
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError)
: mType(aType)
@ -308,7 +334,7 @@ public:
, mAudioSource(aAudioSource)
, mVideoSource(aVideoSource)
, mListener(aListener)
, mFinish(aNeedsFinish)
, mBool(aBool)
, mWindowID(aWindowID)
, mError(aError)
{}
@ -398,7 +424,7 @@ public:
mVideoSource->Deallocate();
}
// Do this after stopping all tracks with EndTrack()
if (mFinish) {
if (mBool) {
source->Finish();
}
nsIRunnable *event =
@ -413,6 +439,15 @@ public:
}
break;
case MEDIA_DIRECT_LISTENERS:
{
NS_ASSERTION(!NS_IsMainThread(), "Never call on main thread");
if (mVideoSource) {
mVideoSource->SetDirectListeners(mBool);
}
}
break;
default:
MOZ_ASSERT(false,"invalid MediaManager operation");
break;
@ -427,7 +462,7 @@ private:
nsRefPtr<MediaEngineSource> mAudioSource; // threadsafe
nsRefPtr<MediaEngineSource> mVideoSource; // threadsafe
nsRefPtr<GetUserMediaCallbackMediaStreamListener> mListener; // threadsafe
bool mFinish;
bool mBool;
uint64_t mWindowID;
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mError;
};

View File

@ -15,6 +15,7 @@
#include "nsIScriptGlobalObject.h"
#include "nsIScriptContext.h"
#include "nsDOMJSUtils.h"
#include "nsJSUtils.h"
#include "nsCxPusher.h"
#include "nsIDocument.h"
#include "nsIJSRuntimeService.h"
@ -405,13 +406,11 @@ JSValToNPVariant(NPP npp, JSContext *cx, JS::Value val, NPVariant *variant)
}
} else if (val.isString()) {
JSString *jsstr = val.toString();
size_t length;
const jschar *chars = ::JS_GetStringCharsZAndLength(cx, jsstr, &length);
if (!chars) {
return false;
}
nsDependentString str(chars, length);
nsAutoJSString str;
if (!str.init(cx, jsstr)) {
return false;
}
uint32_t len;
char *p = ToNewUTF8String(str, &len);

View File

@ -1303,10 +1303,10 @@ _utf8fromidentifier(NPIdentifier id)
}
JSString *str = NPIdentifierToString(id);
nsAutoString autoStr;
AssignJSFlatString(autoStr, JS_ASSERT_STRING_IS_FLAT(str));
return
ToNewUTF8String(nsDependentString(::JS_GetInternedStringChars(str),
::JS_GetStringLength(str)));
return ToNewUTF8String(autoStr);
}
int32_t

View File

@ -55,6 +55,7 @@ using namespace mozilla;
#include "GLContext.h"
#include "TexturePoolOGL.h"
#include "GLSharedHandleHelpers.h"
#include "SurfaceTypes.h"
using namespace mozilla::gl;
@ -89,7 +90,7 @@ static bool EnsureGLContext()
if (!sPluginContext) {
gfxIntSize dummySize(16, 16);
sPluginContext = GLContextProvider::CreateOffscreen(dummySize,
GLContext::SurfaceCaps::Any());
SurfaceCaps::Any());
}
return sPluginContext != nullptr;

View File

@ -165,7 +165,7 @@ nsPluginInstanceOwner::GetImageContainer()
gfxSize resolution = mObjectFrame->PresContext()->PresShell()->GetCumulativeResolution();
ScreenSize screenSize = (r * LayoutDeviceToScreenScale(resolution.width, resolution.height)).Size();
mInstance->NotifySize(nsIntSize(screenSize.width, screenSize.height));
container = LayerManager::CreateImageContainer();
nsRefPtr<Image> img = container->CreateImage(ImageFormat::SHARED_TEXTURE);
@ -260,7 +260,7 @@ nsPluginInstanceOwner::nsPluginInstanceOwner()
// create nsPluginNativeWindow object, it is derived from NPWindow
// struct and allows to manipulate native window procedure
nsCOMPtr<nsIPluginHost> pluginHostCOM = do_GetService(MOZ_PLUGIN_HOST_CONTRACTID);
mPluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
mPluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
if (mPluginHost)
mPluginHost->NewPluginNativeWindow(&mPluginWindow);
else
@ -429,7 +429,7 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetAttribute(const char* name, const char*
{
NS_ENSURE_ARG_POINTER(name);
NS_ENSURE_ARG_POINTER(result);
nsresult rv = EnsureCachedAttrParamArrays();
NS_ENSURE_SUCCESS(rv, rv);
@ -530,9 +530,9 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL,
NS_IMETHODIMP nsPluginInstanceOwner::ShowStatus(const char *aStatusMsg)
{
nsresult rv = NS_ERROR_FAILURE;
rv = this->ShowStatus(NS_ConvertUTF8toUTF16(aStatusMsg).get());
return rv;
}
@ -558,7 +558,7 @@ NS_IMETHODIMP nsPluginInstanceOwner::ShowStatus(const char16_t *aStatusMsg)
if (NS_FAILED(rv) || !browserChrome) {
return rv;
}
rv = browserChrome->SetStatus(nsIWebBrowserChrome::STATUS_SCRIPT,
rv = browserChrome->SetStatus(nsIWebBrowserChrome::STATUS_SCRIPT,
aStatusMsg);
return rv;
@ -626,7 +626,7 @@ NS_IMETHODIMP nsPluginInstanceOwner::InvalidateRegion(NPRegion invalidRegion)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsPluginInstanceOwner::RedrawPlugin()
{
@ -642,7 +642,7 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetNetscapeWindow(void *value)
NS_WARNING("plugin owner has no owner in getting doc's window handle");
return NS_ERROR_FAILURE;
}
#if defined(XP_WIN)
void** pvalue = (void**)value;
nsViewManager* vm = mObjectFrame->PresContext()->GetPresShell()->GetViewManager();
@ -652,18 +652,18 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetNetscapeWindow(void *value)
// This property is provided to allow a "windowless" plugin to determine the window it is drawing
// in, so it can translate mouse coordinates it receives directly from the operating system
// to coordinates relative to itself.
// The original code (outside this #if) returns the document's window, which is OK if the window the "windowless" plugin
// is drawing into has the same origin as the document's window, but this is not the case for "windowless" plugins inside of scrolling DIVs etc
// To make sure "windowless" plugins always get the right origin for translating mouse coordinates, this code
// determines the window handle of the mozilla window containing the "windowless" plugin.
// Given that this HWND may not be that of the document's window, there is a slight risk
// of confusing a plugin that is using this HWND for illicit purposes, but since the documentation
// does not suggest this HWND IS that of the document window, rather that of the window
// the plugin is drawn in, this seems like a safe fix.
// we only attempt to get the nearest window if this really is a "windowless" plugin so as not
// to change any behaviour for the much more common windowed plugins,
// though why this method would even be being called for a windowed plugin escapes me.
@ -676,13 +676,13 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetNetscapeWindow(void *value)
//
// fixing both the caret and ability to interact issues for a windowless control in a non document aligned windw
// does not seem to be possible without a change to the flash plugin
nsIWidget* win = mObjectFrame->GetNearestWidget();
if (win) {
nsView *view = nsView::GetViewFor(win);
NS_ASSERTION(view, "No view for widget");
nsPoint offset = view->GetOffsetTo(nullptr);
if (offset.x || offset.y) {
// in the case the two windows are offset from eachother, we do go ahead and return the correct enclosing window
// so that mouse co-ordinates are not messed up.
@ -1180,7 +1180,7 @@ void nsPluginInstanceOwner::CARefresh(nsITimer *aTimer, void *aClosure) {
r.left = 0;
r.top = 0;
r.right = window->width;
r.bottom = window->height;
r.bottom = window->height;
instanceOwner->InvalidateRect(&r);
}
}
@ -1220,7 +1220,7 @@ void nsPluginInstanceOwner::AddToCARefreshTimer() {
if (sCARefreshListeners->Length() == 1) {
*sCATimer = do_CreateInstance("@mozilla.org/timer;1");
(*sCATimer)->InitWithFuncCallback(CARefresh, nullptr,
(*sCATimer)->InitWithFuncCallback(CARefresh, nullptr,
DEFAULT_REFRESH_RATE, nsITimer::TYPE_REPEATING_SLACK);
}
}
@ -1321,13 +1321,13 @@ void nsPluginInstanceOwner::RenderCoreAnimation(CGContextRef aCGContext,
void* nsPluginInstanceOwner::GetPluginPortCopy()
{
if (GetDrawingModel() == NPDrawingModelCoreGraphics ||
if (GetDrawingModel() == NPDrawingModelCoreGraphics ||
GetDrawingModel() == NPDrawingModelCoreAnimation ||
GetDrawingModel() == NPDrawingModelInvalidatingCoreAnimation)
return &mCGPluginPortCopy;
return nullptr;
}
// Currently (on OS X in Cocoa widgets) any changes made as a result of
// calling GetPluginPortFromWidget() are immediately reflected in the NPWindow
// structure that has been passed to the plugin via SetWindow(). This is
@ -1446,7 +1446,7 @@ bool nsPluginInstanceOwner::AddPluginView(const LayoutDeviceRect& aRect /* = Lay
{
if (!mJavaView) {
mJavaView = mInstance->GetJavaSurface();
if (!mJavaView)
return false;
@ -1537,7 +1537,7 @@ void nsPluginInstanceOwner::ExitFullScreen() {
RemovePluginView();
mFullScreen = false;
int32_t model = mInstance->GetANPDrawingModel();
if (model == kSurface_ANPDrawingModel) {
@ -1581,7 +1581,7 @@ nsresult nsPluginInstanceOwner::DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent)
event.data.lifecycle.action = kLoseFocus_ANPLifecycleAction;
}
else {
NS_ASSERTION(false, "nsPluginInstanceOwner::DispatchFocusToPlugin, wierd eventType");
NS_ASSERTION(false, "nsPluginInstanceOwner::DispatchFocusToPlugin, wierd eventType");
}
mInstance->HandleEvent(&event, nullptr);
}
@ -1603,11 +1603,11 @@ nsresult nsPluginInstanceOwner::DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent)
if (nsEventStatus_eConsumeNoDefault == rv) {
aFocusEvent->PreventDefault();
aFocusEvent->StopPropagation();
}
}
}
return NS_OK;
}
}
nsresult nsPluginInstanceOwner::ProcessKeyPress(nsIDOMEvent* aKeyEvent)
{
@ -1643,12 +1643,12 @@ nsresult nsPluginInstanceOwner::DispatchKeyToPlugin(nsIDOMEvent* aKeyEvent)
if (nsEventStatus_eConsumeNoDefault == rv) {
aKeyEvent->PreventDefault();
aKeyEvent->StopPropagation();
}
}
}
}
return NS_OK;
}
}
nsresult
nsPluginInstanceOwner::ProcessMouseDown(nsIDOMEvent* aMouseEvent)
@ -1663,7 +1663,7 @@ nsPluginInstanceOwner::ProcessMouseDown(nsIDOMEvent* aMouseEvent)
// otherwise, we might not get key events
if (mObjectFrame && mPluginWindow &&
mPluginWindow->type == NPWindowTypeDrawable) {
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm) {
nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(mContent);
@ -1680,7 +1680,7 @@ nsPluginInstanceOwner::ProcessMouseDown(nsIDOMEvent* aMouseEvent)
return aMouseEvent->PreventDefault(); // consume event
}
}
return NS_OK;
}
@ -2115,7 +2115,7 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const WidgetGUIEvent& anEvent)
break;
//XXX case NS_MOUSE_SCROLL_EVENT: not received.
case NS_KEY_EVENT:
if (anEvent.pluginEvent)
{
@ -2163,7 +2163,7 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const WidgetGUIEvent& anEvent)
}
break;
default:
default:
switch (anEvent.message)
{
case NS_FOCUS_CONTENT:
@ -2283,7 +2283,7 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const WidgetGUIEvent& anEvent)
}
rv = nsEventStatus_eConsumeNoDefault;
#endif
return rv;
}
@ -2354,7 +2354,7 @@ void nsPluginInstanceOwner::Paint(const gfxRect& aDirtyRect, CGContextRef cgCont
if (!mInstance || !mObjectFrame)
return;
gfxRect dirtyRectCopy = aDirtyRect;
gfxRect dirtyRectCopy = aDirtyRect;
double scaleFactor = 1.0;
GetContentsScaleFactor(&scaleFactor);
if (scaleFactor != 1.0) {
@ -2375,7 +2375,7 @@ void nsPluginInstanceOwner::DoCocoaEventDrawRect(const gfxRect& aDrawRect, CGCon
{
if (!mInstance || !mObjectFrame)
return;
// The context given here is only valid during the HandleEvent call.
NPCocoaEvent updateEvent;
InitializeNPCocoaEvent(&updateEvent);
@ -2432,7 +2432,7 @@ void nsPluginInstanceOwner::Paint(gfxContext* aContext,
aFrameRect.width != pluginSurface->Width() ||
aFrameRect.height != pluginSurface->Height()) {
pluginSurface = new gfxImageSurface(gfxIntSize(aFrameRect.width, aFrameRect.height),
pluginSurface = new gfxImageSurface(gfxIntSize(aFrameRect.width, aFrameRect.height),
gfxImageFormat::ARGB32);
if (!pluginSurface)
return;
@ -2440,26 +2440,26 @@ void nsPluginInstanceOwner::Paint(gfxContext* aContext,
// Clears buffer. I think this is needed.
gfxUtils::ClearThebesSurface(pluginSurface);
ANPEvent event;
event.inSize = sizeof(ANPEvent);
event.eventType = 4;
event.data.draw.model = 1;
event.data.draw.clip.top = 0;
event.data.draw.clip.left = 0;
event.data.draw.clip.bottom = aFrameRect.width;
event.data.draw.clip.right = aFrameRect.height;
event.data.draw.data.bitmap.format = kRGBA_8888_ANPBitmapFormat;
event.data.draw.data.bitmap.width = aFrameRect.width;
event.data.draw.data.bitmap.height = aFrameRect.height;
event.data.draw.data.bitmap.baseAddr = pluginSurface->Data();
event.data.draw.data.bitmap.rowBytes = aFrameRect.width * 4;
if (!mInstance)
return;
mInstance->HandleEvent(&event, nullptr);
aContext->SetOperator(gfxContext::OPERATOR_SOURCE);
@ -2543,7 +2543,7 @@ void nsPluginInstanceOwner::Paint(gfxContext* aContext,
nsresult
nsPluginInstanceOwner::Renderer::DrawWithXlib(cairo_surface_t* xsurface,
nsIntPoint offset,
nsIntRect *clipRects,
nsIntRect *clipRects,
uint32_t numClipRects)
{
Screen *screen = cairo_xlib_surface_get_screen(xsurface);
@ -2612,7 +2612,7 @@ nsPluginInstanceOwner::Renderer::DrawWithXlib(cairo_surface_t* xsurface,
doupdatewindow = true;
}
NPSetWindowCallbackStruct* ws_info =
NPSetWindowCallbackStruct* ws_info =
static_cast<NPSetWindowCallbackStruct*>(mWindow->ws_info);
#ifdef MOZ_X11
if (ws_info->visual != visual || ws_info->colormap != colormap) {
@ -2725,7 +2725,7 @@ nsresult nsPluginInstanceOwner::Init(nsIContent* aContent)
mContent->AddEventListener(NS_LITERAL_STRING("draggesture"), this, true);
mContent->AddEventListener(NS_LITERAL_STRING("dragend"), this, true);
return NS_OK;
return NS_OK;
}
void* nsPluginInstanceOwner::GetPluginPortFromWidget()
@ -2740,7 +2740,7 @@ void* nsPluginInstanceOwner::GetPluginPortFromWidget()
else
#endif
#ifdef XP_MACOSX
if (GetDrawingModel() == NPDrawingModelCoreGraphics ||
if (GetDrawingModel() == NPDrawingModelCoreGraphics ||
GetDrawingModel() == NPDrawingModelCoreAnimation ||
GetDrawingModel() == NPDrawingModelInvalidatingCoreAnimation)
result = mWidget->GetNativeData(NS_NATIVE_PLUGIN_PORT_CG);
@ -2766,13 +2766,13 @@ NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void)
NS_ENSURE_TRUE(mPluginWindow, NS_ERROR_NULL_POINTER);
nsresult rv = NS_ERROR_FAILURE;
// Can't call this twice!
if (mWidget) {
NS_WARNING("Trying to create a plugin widget twice!");
return NS_ERROR_FAILURE;
}
bool windowless = false;
mInstance->IsWindowless(&windowless);
if (!windowless
@ -2844,10 +2844,10 @@ NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void)
mPluginWindow->window = nullptr;
#ifdef MOZ_X11
// Fill in the display field.
NPSetWindowCallbackStruct* ws_info =
NPSetWindowCallbackStruct* ws_info =
static_cast<NPSetWindowCallbackStruct*>(mPluginWindow->ws_info);
ws_info->display = DefaultXDisplay();
nsAutoCString description;
GetPluginDescription(description);
NS_NAMED_LITERAL_CSTRING(flash10Head, "Shockwave Flash 10.");
@ -2860,7 +2860,7 @@ NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void)
mPluginWindow->window = GetPluginPortFromWidget();
// tell the plugin window about the widget
mPluginWindow->SetPluginWidget(mWidget);
// tell the widget about the current plugin instance owner.
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
if (pluginWidget) {

View File

@ -583,7 +583,7 @@ PluginInstanceParent::RecvShow(const NPRect& updatedRect,
NS_WARNING("Got bad IOSurfaceDescriptor in RecvShow");
return false;
}
if (mFrontIOSurface)
*prevSurface = IOSurfaceDescriptor(mFrontIOSurface->GetIOSurfaceID(),
mFrontIOSurface->GetContentsScaleFactor());
@ -624,7 +624,7 @@ PluginInstanceParent::RecvShow(const NPRect& updatedRect,
// scribbling on it again, or worse, destroys it.
mFrontSurface->Finish();
FinishX(DefaultXDisplay());
} else
} else
#endif
{
mFrontSurface->Flush();
@ -697,7 +697,7 @@ PluginInstanceParent::GetImageContainer(ImageContainer** aContainer)
{
#ifdef XP_MACOSX
MacIOSurface* ioSurface = nullptr;
if (mFrontIOSurface) {
ioSurface = mFrontIOSurface;
} else if (mIOSurface) {
@ -1001,7 +1001,7 @@ PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow)
window.contentsScaleFactor = floatScaleFactor;
if (mShWidth != window.width * scaleFactor || mShHeight != window.height * scaleFactor) {
if (mDrawingModel == NPDrawingModelCoreAnimation ||
if (mDrawingModel == NPDrawingModelCoreAnimation ||
mDrawingModel == NPDrawingModelInvalidatingCoreAnimation) {
mIOSurface = MacIOSurface::CreateIOSurface(window.width, window.height,
floatScaleFactor);
@ -1018,7 +1018,7 @@ PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow)
SharedMemory::TYPE_BASIC, &mShSurface)) {
PLUGIN_LOG_DEBUG(("Shared memory could not be allocated."));
return NPERR_GENERIC_ERROR;
}
}
}
}
mShWidth = window.width * scaleFactor;
@ -1280,9 +1280,9 @@ PluginInstanceParent::NPP_HandleEvent(void* event)
NS_ERROR("No IOSurface allocated.");
return false;
}
if (!CallNPP_HandleEvent_IOSurface(npremoteevent,
mIOSurface->GetIOSurfaceID(),
&handled))
if (!CallNPP_HandleEvent_IOSurface(npremoteevent,
mIOSurface->GetIOSurfaceID(),
&handled))
return false; // no good way to handle errors here...
CGContextRef cgContext = npevent->data.draw.context;
@ -1294,7 +1294,7 @@ PluginInstanceParent::NPP_HandleEvent(void* event)
return false;
}
if (cgContext) {
nsCARenderer::DrawSurfaceToCGContext(cgContext, mIOSurface,
nsCARenderer::DrawSurfaceToCGContext(cgContext, mIOSurface,
mShColorSpace,
npevent->data.draw.x,
npevent->data.draw.y,
@ -1312,7 +1312,7 @@ PluginInstanceParent::NPP_HandleEvent(void* event)
return false;
}
if (cgContext) {
nsCARenderer::DrawSurfaceToCGContext(cgContext, mFrontIOSurface,
nsCARenderer::DrawSurfaceToCGContext(cgContext, mFrontIOSurface,
mShColorSpace,
npevent->data.draw.x,
npevent->data.draw.y,
@ -1330,8 +1330,8 @@ PluginInstanceParent::NPP_HandleEvent(void* event)
return false;
}
if (!CallNPP_HandleEvent_Shmem(npremoteevent, mShSurface,
&handled, &mShSurface))
if (!CallNPP_HandleEvent_Shmem(npremoteevent, mShSurface,
&handled, &mShSurface))
return false; // no good way to handle errors here...
if (!mShSurface.IsReadable()) {
@ -1348,11 +1348,11 @@ PluginInstanceParent::NPP_HandleEvent(void* event)
if (!mShColorSpace) {
PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace."));
return false;
}
CGContextRef shContext = ::CGBitmapContextCreate(shContextByte,
mShWidth, mShHeight, 8,
mShWidth*4, mShColorSpace,
kCGImageAlphaPremultipliedFirst |
}
CGContextRef shContext = ::CGBitmapContextCreate(shContextByte,
mShWidth, mShHeight, 8,
mShWidth*4, mShColorSpace,
kCGImageAlphaPremultipliedFirst |
kCGBitmapByteOrder32Host);
if (!shContext) {
PLUGIN_LOG_DEBUG(("Could not allocate CGBitmapContext."));
@ -1362,9 +1362,9 @@ PluginInstanceParent::NPP_HandleEvent(void* event)
CGImageRef shImage = ::CGBitmapContextCreateImage(shContext);
if (shImage) {
CGContextRef cgContext = npevent->data.draw.context;
::CGContextDrawImage(cgContext,
CGRectMake(0,0,mShWidth,mShHeight),
::CGContextDrawImage(cgContext,
CGRectMake(0,0,mShWidth,mShHeight),
shImage);
::CGImageRelease(shImage);
} else {
@ -1723,7 +1723,7 @@ PluginInstanceParent::AnswerNPN_InitAsyncSurface(const gfxIntSize& size,
ID3D10Device1 *device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
nsRefPtr<ID3D10Texture2D> texture;
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, size.width, size.height, 1, 1);
desc.MiscFlags = D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX;
desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
@ -1744,7 +1744,7 @@ PluginInstanceParent::AnswerNPN_InitAsyncSurface(const gfxIntSize& size,
*result = false;
return true;
}
surfData->size() = size;
surfData->data() = sharedHandle;
surfData->format() = format;
@ -1798,7 +1798,7 @@ PluginInstanceParent::RecvReleaseDXGISharedSurface(const DXGISharedSurfaceHandle
focus from dom -> child:
Focus manager calls on widget to set the focus on the window.
We pick up the resulting wm_setfocus event here, and forward
that over ipc to the child which calls set focus on itself.
that over ipc to the child which calls set focus on itself.
focus from child -> focus manager:
Child picks up the local wm_setfocus and sends it via ipc over
@ -1854,7 +1854,7 @@ PluginInstanceParent::SubclassPluginWindow(HWND aWnd)
if (!mPluginHWND) {
mPluginHWND = aWnd;
mPluginWndProc =
mPluginWndProc =
(WNDPROC)::SetWindowLongPtrA(mPluginHWND, GWLP_WNDPROC,
reinterpret_cast<LONG_PTR>(PluginWindowHookProc));
DebugOnly<bool> bRes = ::SetPropW(mPluginHWND, kPluginInstanceParentProperty, this);
@ -1886,13 +1886,13 @@ PluginInstanceParent::UnsubclassPluginWindow()
*
* windowless, offscreen:
*
* WM_WINDOWPOSCHANGED: origin is relative to container
* WM_WINDOWPOSCHANGED: origin is relative to container
* setwindow: origin is 0,0
* WM_PAINT: origin is 0,0
*
* windowless, native:
*
* WM_WINDOWPOSCHANGED: origin is relative to container
* WM_WINDOWPOSCHANGED: origin is relative to container
* setwindow: origin is relative to container
* WM_PAINT: origin is relative to container
*

View File

@ -26,13 +26,13 @@ try {
/* Check that we can touch various properties */
isnot(e.lineNumber, undefined, "Unexpected line number"); //This line number is dependent on the implementation of the SpecialPowers API
is(e.name, "NS_ERROR_MALFORMED_URI", "Unexpected exception name");
isnot(e.message, "", "Should have a message");
ise(e.message, "", "Should not have a message for this case");
isnot(e.result, 0, "Should have a result");
is(e.result, SpecialPowers.Cr.NS_ERROR_MALFORMED_URI);
}
is(threw, true, "Not enough arguments to a call should throw");
is(threw, true, "We need a different testcase for XPConnect exceptions?");
</script>
</pre>
</body>

View File

@ -50,7 +50,9 @@ try {
this.__defineGetter__.call(window.location, 'href', function(){});
ok(false, "shouldn't be able to override location.href");
} catch (e) {
ok(/shadow/.exec(e.message), "Should be caught by the anti-shadow mechanism.");
ok(/shadow/.exec(e.message) ||
/can't redefine non-configurable/.exec(e.message),
"Should be caught by the anti-shadow mechanism.");
}
// Try deleting the property.
@ -61,17 +63,16 @@ delete Object.getPrototypeOf(window.location).href;
ok(typeof window.location.href !== 'undefined',
"shouldn't be able to delete the property off of the prototype");
try {
this.__defineGetter__.call(Object.getPrototypeOf(window.location), 'href', function(){});
ok(false, "shouldn't be able to use the prototype");
} catch (e) {
}
this.__defineGetter__.call(Object.getPrototypeOf(window.location), 'href', function(){});
ok(true, "should be able to define things on the prototype");
try {
this.__defineSetter__.call(window.location, 'href', function(){});
ok(false, "overrode a setter for location.href?");
} catch (e) {
ok(/shadow/.exec(e.message), "Should be caught by the anti-shadow mechanism.");
ok(/shadow/.exec(e.message) ||
/can't redefine non-configurable/.exec(e.message),
"Should be caught by the anti-shadow mechanism.");
}
try {

View File

@ -1,6 +1,10 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
function runAll(steps) {
SimpleTest.waitForExplicitFinish();
@ -46,3 +50,44 @@ function confirmNextInstall() {
}
popupPanel.addEventListener("popupshown", onPopupShown, false);
}
// We need to mock the Alerts service, otherwise the alert that is shown
// at the end of an installation makes the test leak the app's icon.
const CID = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator).generateUUID();
const ALERTS_SERVICE_CONTRACT_ID = "@mozilla.org/alerts-service;1";
const ALERTS_SERVICE_CID = Components.ID(Cc[ALERTS_SERVICE_CONTRACT_ID].number);
var AlertsService = {
classID: Components.ID(CID),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory,
Ci.nsIAlertsService]),
createInstance: function(aOuter, aIID) {
if (aOuter) {
throw Cr.NS_ERROR_NO_AGGREGATION;
}
return this.QueryInterface(aIID);
},
init: function() {
Components.manager.nsIComponentRegistrar.registerFactory(this.classID,
"", ALERTS_SERVICE_CONTRACT_ID, this);
},
restore: function() {
Components.manager.nsIComponentRegistrar.registerFactory(ALERTS_SERVICE_CID,
"", ALERTS_SERVICE_CONTRACT_ID, null);
},
showAlertNotification: function() {
},
};
AlertsService.init();
SimpleTest.registerCleanupFunction(() => {
AlertsService.restore();
});

View File

@ -17,9 +17,6 @@
</body>
<script>
const Ci = Components.interfaces;
const Cu = Components.utils;
SimpleTest.waitForExplicitFinish();
SpecialPowers.setAllAppsLaunchable(true);

View File

@ -18,7 +18,6 @@
<script type="application/javascript;version=1.8">
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/Webapps.jsm");
// We use a different origin than other webapps test files because we compare

View File

@ -11,11 +11,15 @@
* and create derivative works of this document.
*/
// No support for [Unforgeable] on interfaces yet
//[Unforgeable]
[Unforgeable]
interface Location {
[Throws]
void assign(DOMString url);
[Throws, CrossOriginCallable]
void replace(DOMString url);
void reload();
// XXXbz there is no forceget argument in the spec! See bug 1037721.
[Throws]
void reload(optional boolean forceget = false);
};
Location implements URLUtils;
// No support for .searchParams on Location yet. See bug 1037715.
Location implements URLUtilsNoSearchParams;

Some files were not shown because too many files have changed in this diff Show More