mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-28 11:28:38 +00:00
merge mozilla-inbound to mozilla-central a=merge
This commit is contained in:
commit
90fb1d9bfd
19
configure.in
19
configure.in
@ -7798,6 +7798,25 @@ AC_SUBST(PROFILE_GEN_LDFLAGS)
|
||||
AC_SUBST(PROFILE_USE_CFLAGS)
|
||||
AC_SUBST(PROFILE_USE_LDFLAGS)
|
||||
|
||||
dnl =============================================
|
||||
dnl Support for -fno-integrated-as (recent clang)
|
||||
dnl =============================================
|
||||
dnl Under clang 3.4+, use -fno-integrated-as to
|
||||
dnl build libvpx's vp8_asm_enc_offsets.c
|
||||
|
||||
_SAVE_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -fno-integrated-as"
|
||||
|
||||
AC_MSG_CHECKING([whether C compiler supports -fno-integrated-as])
|
||||
AC_TRY_COMPILE([], [return 0;],
|
||||
[ NO_INTEGRATED_AS_CFLAGS="-fno-integrated-as"
|
||||
result="yes" ], result="no")
|
||||
AC_MSG_RESULT([$result])
|
||||
|
||||
CFLAGS="$_SAVE_CFLAGS"
|
||||
|
||||
AC_SUBST(NO_INTEGRATED_AS_CFLAGS)
|
||||
|
||||
fi # ! SKIP_COMPILER_CHECKS
|
||||
|
||||
AC_DEFINE(CPP_THROW_NEW, [throw()])
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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*
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -72,6 +72,7 @@ class AudioTrackList;
|
||||
class VideoTrackList;
|
||||
|
||||
class HTMLMediaElement : public nsGenericHTMLElement,
|
||||
public nsIDOMHTMLMediaElement,
|
||||
public nsIObserver,
|
||||
public MediaDecoderOwner,
|
||||
public nsIAudioChannelAgentCallback
|
||||
|
@ -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);
|
||||
|
@ -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; \
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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; \
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
392
content/media/omx/MediaCodecProxy.cpp
Normal file
392
content/media/omx/MediaCodecProxy.cpp
Normal 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
|
156
content/media/omx/MediaCodecProxy.h
Normal file
156
content/media/omx/MediaCodecProxy.h
Normal 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
|
@ -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
|
||||
|
@ -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
|
@ -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
|
@ -16,6 +16,7 @@ SOURCES += [
|
||||
'IMediaResourceManagerClient.cpp',
|
||||
'IMediaResourceManagerDeathNotifier.cpp',
|
||||
'IMediaResourceManagerService.cpp',
|
||||
'MediaResourceHandler.cpp',
|
||||
'MediaResourceManagerClient.cpp',
|
||||
'MediaResourceManagerService.cpp',
|
||||
]
|
||||
|
@ -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'
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
||||
];
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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__
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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': {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
71
dom/browser-element/mochitest/browserElement_ThemeColor.js
Normal file
71
dom/browser-element/mochitest/browserElement_ThemeColor.js
Normal 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);
|
||||
|
@ -0,0 +1,8 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta name="theme-color" content="pink">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
@ -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]
|
||||
|
@ -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]
|
||||
|
@ -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>
|
@ -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>
|
@ -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
|
||||
|
@ -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
|
||||
|
38
dom/crypto/BasicSymmetricKeyAlgorithm.h
Normal file
38
dom/crypto/BasicSymmetricKeyAlgorithm.h
Normal 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
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ TEST_DIRS += ['test']
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'AesKeyAlgorithm.h',
|
||||
'BasicSymmetricKeyAlgorithm.h',
|
||||
'CryptoBuffer.h',
|
||||
'CryptoKey.h',
|
||||
'CryptoKeyPair.h',
|
||||
|
@ -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"
|
||||
)
|
||||
},
|
||||
}
|
||||
|
@ -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 );
|
||||
}
|
||||
);*/
|
||||
|
@ -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++
|
||||
|
@ -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',
|
||||
|
@ -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
|
||||
{
|
||||
};
|
@ -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();
|
||||
};
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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>
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
});
|
||||
|
@ -17,9 +17,6 @@
|
||||
</body>
|
||||
|
||||
<script>
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
SpecialPowers.setAllAppsLaunchable(true);
|
||||
|
@ -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
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user