import changes from `dev' branch of rmottola/Arctic-Fox:

- Bug 1181382: move declaration into namespace to resolve conflict. r=hsinyi (b1cbc67344)
- Bug 1131470 - Part 3: Implement ScreenOrientation interface. r=baku (805ffd4d18)
- Bug 1131470 - Part 4: Check sandboxing flag for orientation lock. r=baku (2896c9af4c)
- Bug 1131470 - Part 5: Handle changes to active orientation lock. r=smaug (2550433007)
- Bug 1131470 - Part 6: ScreenOrientation tests. r=baku (53e088ab98)
- Bug 1193133 - Drop the document and window references from ServiceWorker. r=bkelly (ce09f526b8)
- Bug 1186307 - part 1 - Unify the StructuredCloneCallbacks in WorkerPrivate.cpp, r=smaug (a109da831d)
- pointer style (c26fa45b91)
- Bug 1174971 - Introduce two variants of getOwnPropertyFromTargetIfSafe. r=gabor,r=arai (4bec0627ce)
- reapply Bug 1131802 part 2. Allocate functions with reserved slots for DOM Xrays so we can store the Xray wrapper reference in those slots instead of as the function parent. r=peterv (ff39e220a3)
- No bug - Add a bug number to the expected failure in message-event.html. (398f3e500a)
- Bug 1164834: MessageEvents coming from postMessage should not be cancelable. r=Ms2ger (380ce180bf)
This commit is contained in:
2022-03-12 10:32:14 +08:00
parent ff1df7517f
commit 38ceaed34c
50 changed files with 1313 additions and 586 deletions
+40
View File
@@ -16,6 +16,7 @@
#include "mozilla/dom/Element.h"
#include "mozilla/dom/TabChild.h"
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
#include "mozilla/dom/ScreenOrientation.h"
#include "mozilla/dom/ToJSValue.h"
#include "mozilla/dom/workers/ServiceWorkerManager.h"
#include "mozilla/EventStateManager.h"
@@ -757,6 +758,7 @@ nsDocShell::nsDocShell()
, mLoadedTransIndex(-1)
, mSandboxFlags(0)
, mFullscreenAllowed(CHECK_ATTRIBUTES)
, mOrientationLock(eScreenOrientation_None)
, mCreated(false)
, mAllowSubframes(true)
, mAllowPlugins(true)
@@ -2560,6 +2562,18 @@ nsDocShell::SetFullscreenAllowed(bool aFullscreenAllowed)
return NS_OK;
}
ScreenOrientationInternal
nsDocShell::OrientationLock()
{
return mOrientationLock;
}
void
nsDocShell::SetOrientationLock(ScreenOrientationInternal aOrientationLock)
{
mOrientationLock = aOrientationLock;
}
NS_IMETHODIMP
nsDocShell::GetMayEnableCharacterEncodingMenu(
bool* aMayEnableCharacterEncodingMenu)
@@ -6065,6 +6079,16 @@ nsDocShell::SetIsActive(bool aIsActive)
if (mScriptGlobal) {
mScriptGlobal->SetIsBackground(!aIsActive);
if (nsCOMPtr<nsIDocument> doc = mScriptGlobal->GetExtantDoc()) {
if (aIsActive) {
nsCOMPtr<nsIDocShellTreeItem> parent;
GetSameTypeParent(getter_AddRefs(parent));
if (!parent) {
// We only care about the top-level browsing context.
uint16_t orientation = OrientationLock();
ScreenOrientation::UpdateActiveOrientationLock(orientation);
}
}
doc->PostVisibilityUpdateEvent();
}
}
@@ -10270,6 +10294,22 @@ nsDocShell::InternalLoad2(nsIURI* aURI,
mTiming->NotifyUnloadAccepted(mCurrentURI);
}
// Whenever a top-level browsing context is navigated, the user agent MUST
// lock the orientation of the document to the document's default
// orientation. We don't explicitly check for a top-level browsing context
// here because orientation is only set on top-level browsing contexts.
if (OrientationLock() != eScreenOrientation_None) {
#ifdef DEBUG
nsCOMPtr<nsIDocShellTreeItem> parent;
GetSameTypeParent(getter_AddRefs(parent));
MOZ_ASSERT(!parent);
#endif
SetOrientationLock(eScreenOrientation_None);
if (mIsActive) {
ScreenOrientation::UpdateActiveOrientationLock(eScreenOrientation_None);
}
}
// Check for saving the presentation here, before calling Stop().
// This is necessary so that we can catch any pending requests.
// Since the new request has not been created yet, we pass null for the
+5
View File
@@ -62,6 +62,7 @@
namespace mozilla {
namespace dom {
class EventTarget;
typedef uint32_t ScreenOrientationInternal;
} // namespace dom
} // namespace mozilla
@@ -879,6 +880,10 @@ protected:
};
FullscreenAllowedState mFullscreenAllowed;
// The orientation lock as described by
// https://w3c.github.io/screen-orientation/
mozilla::dom::ScreenOrientationInternal mOrientationLock;
// Cached value of the "browser.xul.error_pages.enabled" preference.
static bool sUseErrorPages;
+4 -1
View File
@@ -46,7 +46,7 @@ interface nsITabParent;
typedef unsigned long nsLoadFlags;
[scriptable, builtinclass, uuid(97471054-0BC8-4A57-BBFE-6C255BCBBB67)]
[scriptable, builtinclass, uuid(35a26f70-dbb9-450d-b634-cd0bbb9b8e13)]
interface nsIDocShell : nsIDocShellTreeItem
{
/**
@@ -920,6 +920,9 @@ interface nsIDocShell : nsIDocShellTreeItem
void setFullscreenAllowed(in boolean allowed);
[notxpcom] uint32_t orientationLock();
[notxpcom] void setOrientationLock(in uint32_t orientationLock);
[noscript, infallible] attribute boolean affectPrivateSessionLifetime;
/**
+645
View File
@@ -0,0 +1,645 @@
/* 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 "ScreenOrientation.h"
#include "nsIDeviceSensors.h"
#include "nsSandboxFlags.h"
#include "nsScreen.h"
using namespace mozilla::dom;
NS_IMPL_CYCLE_COLLECTION_INHERITED(ScreenOrientation,
DOMEventTargetHelper,
mScreen);
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ScreenOrientation)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
NS_IMPL_ADDREF_INHERITED(ScreenOrientation, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(ScreenOrientation, DOMEventTargetHelper)
static OrientationType
InternalOrientationToType(ScreenOrientationInternal aOrientation)
{
switch (aOrientation) {
case eScreenOrientation_PortraitPrimary:
return OrientationType::Portrait_primary;
case eScreenOrientation_PortraitSecondary:
return OrientationType::Portrait_secondary;
case eScreenOrientation_LandscapePrimary:
return OrientationType::Landscape_primary;
case eScreenOrientation_LandscapeSecondary:
return OrientationType::Landscape_secondary;
default:
MOZ_CRASH("Bad aOrientation value");
}
}
static ScreenOrientationInternal
OrientationTypeToInternal(OrientationType aOrientation)
{
switch (aOrientation) {
case OrientationType::Portrait_primary:
return eScreenOrientation_PortraitPrimary;
case OrientationType::Portrait_secondary:
return eScreenOrientation_PortraitSecondary;
case OrientationType::Landscape_primary:
return eScreenOrientation_LandscapePrimary;
case OrientationType::Landscape_secondary:
return eScreenOrientation_LandscapeSecondary;
default:
MOZ_CRASH("Bad aOrientation value");
}
}
ScreenOrientation::ScreenOrientation(nsPIDOMWindow* aWindow, nsScreen* aScreen)
: DOMEventTargetHelper(aWindow), mScreen(aScreen)
{
MOZ_ASSERT(aWindow);
MOZ_ASSERT(aScreen);
hal::RegisterScreenConfigurationObserver(this);
hal::ScreenConfiguration config;
hal::GetCurrentScreenConfiguration(&config);
mType = InternalOrientationToType(config.orientation());
mAngle = config.angle();
nsIDocument* doc = GetResponsibleDocument();
if (doc) {
doc->SetCurrentOrientation(mType, mAngle);
}
}
ScreenOrientation::~ScreenOrientation()
{
hal::UnregisterScreenConfigurationObserver(this);
MOZ_ASSERT(!mFullScreenListener);
}
class ScreenOrientation::FullScreenEventListener final : public nsIDOMEventListener
{
~FullScreenEventListener() {}
public:
FullScreenEventListener() {}
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMEVENTLISTENER
};
class ScreenOrientation::VisibleEventListener final : public nsIDOMEventListener
{
~VisibleEventListener() {}
public:
VisibleEventListener() {}
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMEVENTLISTENER
};
class ScreenOrientation::LockOrientationTask final : public nsIRunnable
{
~LockOrientationTask();
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIRUNNABLE
LockOrientationTask(ScreenOrientation* aScreenOrientation,
Promise* aPromise,
ScreenOrientationInternal aOrientationLock,
nsIDocument* aDocument,
bool aIsFullScreen);
protected:
bool OrientationLockContains(OrientationType aOrientationType);
nsRefPtr<ScreenOrientation> mScreenOrientation;
nsRefPtr<Promise> mPromise;
ScreenOrientationInternal mOrientationLock;
nsCOMPtr<nsIDocument> mDocument;
bool mIsFullScreen;
};
NS_IMPL_ISUPPORTS(ScreenOrientation::LockOrientationTask, nsIRunnable)
ScreenOrientation::LockOrientationTask::LockOrientationTask(
ScreenOrientation* aScreenOrientation, Promise* aPromise,
ScreenOrientationInternal aOrientationLock,
nsIDocument* aDocument, bool aIsFullScreen)
: mScreenOrientation(aScreenOrientation), mPromise(aPromise),
mOrientationLock(aOrientationLock), mDocument(aDocument),
mIsFullScreen(aIsFullScreen)
{
MOZ_ASSERT(aScreenOrientation);
MOZ_ASSERT(aPromise);
MOZ_ASSERT(aDocument);
}
ScreenOrientation::LockOrientationTask::~LockOrientationTask()
{
}
bool
ScreenOrientation::LockOrientationTask::OrientationLockContains(
OrientationType aOrientationType)
{
return mOrientationLock & OrientationTypeToInternal(aOrientationType);
}
NS_IMETHODIMP
ScreenOrientation::LockOrientationTask::Run()
{
// Step to lock the orientation as defined in the spec.
if (mDocument->GetOrientationPendingPromise() != mPromise) {
// The document's pending promise is not associated with this task
// to lock orientation. There has since been another request to
// lock orientation, thus we don't need to do anything. Old promise
// should be been rejected.
return NS_OK;
}
if (mDocument->Hidden()) {
// Active orientation lock is not the document's orientation lock.
mPromise->MaybeResolve(JS::UndefinedHandleValue);
mDocument->SetOrientationPendingPromise(nullptr);
return NS_OK;
}
if (mOrientationLock == eScreenOrientation_None) {
mScreenOrientation->UnlockDeviceOrientation();
mPromise->MaybeResolve(JS::UndefinedHandleValue);
mDocument->SetOrientationPendingPromise(nullptr);
return NS_OK;
}
ErrorResult rv;
bool result = mScreenOrientation->LockDeviceOrientation(mOrientationLock,
mIsFullScreen, rv);
if (NS_WARN_IF(rv.Failed())) {
return rv.StealNSResult();
}
if (NS_WARN_IF(!result)) {
mPromise->MaybeReject(NS_ERROR_UNEXPECTED);
mDocument->SetOrientationPendingPromise(nullptr);
return NS_OK;
}
if (OrientationLockContains(mDocument->CurrentOrientationType()) ||
(mOrientationLock == eScreenOrientation_Default &&
mDocument->CurrentOrientationAngle() == 0)) {
// Orientation lock will not cause an orientation change.
mPromise->MaybeResolve(JS::UndefinedHandleValue);
mDocument->SetOrientationPendingPromise(nullptr);
}
return NS_OK;
}
already_AddRefed<Promise>
ScreenOrientation::Lock(OrientationLockType aOrientation, ErrorResult& aRv)
{
ScreenOrientationInternal orientation = eScreenOrientation_None;
switch (aOrientation) {
case OrientationLockType::Any:
orientation = eScreenOrientation_PortraitPrimary |
eScreenOrientation_PortraitSecondary |
eScreenOrientation_LandscapePrimary |
eScreenOrientation_LandscapeSecondary;
break;
case OrientationLockType::Natural:
orientation |= eScreenOrientation_Default;
break;
case OrientationLockType::Landscape:
orientation = eScreenOrientation_LandscapePrimary |
eScreenOrientation_LandscapeSecondary;
break;
case OrientationLockType::Portrait:
orientation = eScreenOrientation_PortraitPrimary |
eScreenOrientation_PortraitSecondary;
break;
case OrientationLockType::Portrait_primary:
orientation = eScreenOrientation_PortraitPrimary;
break;
case OrientationLockType::Portrait_secondary:
orientation = eScreenOrientation_PortraitSecondary;
break;
case OrientationLockType::Landscape_primary:
orientation = eScreenOrientation_LandscapePrimary;
break;
case OrientationLockType::Landscape_secondary:
orientation = eScreenOrientation_LandscapeSecondary;
break;
default:
NS_WARNING("Unexpected orientation type");
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
return LockInternal(orientation, aRv);
}
static inline void
AbortOrientationPromises(nsIDocShell* aDocShell)
{
MOZ_ASSERT(aDocShell);
nsIDocument* doc = aDocShell->GetDocument();
if (doc) {
Promise* promise = doc->GetOrientationPendingPromise();
if (promise) {
promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
doc->SetOrientationPendingPromise(nullptr);
}
}
int32_t childCount;
aDocShell->GetChildCount(&childCount);
for (int32_t i = 0; i < childCount; i++) {
nsCOMPtr<nsIDocShellTreeItem> child;
if (NS_SUCCEEDED(aDocShell->GetChildAt(i, getter_AddRefs(child)))) {
nsCOMPtr<nsIDocShell> childShell(do_QueryInterface(child));
if (childShell) {
AbortOrientationPromises(childShell);
}
}
}
}
already_AddRefed<Promise>
ScreenOrientation::LockInternal(ScreenOrientationInternal aOrientation, ErrorResult& aRv)
{
// Steps to apply an orientation lock as defined in spec.
nsIDocument* doc = GetResponsibleDocument();
if (NS_WARN_IF(!doc)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
nsCOMPtr<nsPIDOMWindow> owner = GetOwner();
if (NS_WARN_IF(!owner)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
nsCOMPtr<nsIDocShell> docShell = owner->GetDocShell();
if (NS_WARN_IF(!docShell)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(owner);
MOZ_ASSERT(go);
nsRefPtr<Promise> p = Promise::Create(go, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
#if !defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_WIDGET_GONK)
// User agent does not support locking the screen orientation.
p->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return p.forget();
#else
LockPermission perm = GetLockOrientationPermission(true);
if (perm == LOCK_DENIED) {
p->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
return p.forget();
}
nsCOMPtr<nsIDocShellTreeItem> root;
docShell->GetSameTypeRootTreeItem(getter_AddRefs(root));
nsCOMPtr<nsIDocShell> rootShell(do_QueryInterface(root));
if (!rootShell) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
rootShell->SetOrientationLock(aOrientation);
AbortOrientationPromises(rootShell);
doc->SetOrientationPendingPromise(p);
nsCOMPtr<nsIRunnable> lockOrientationTask =
new LockOrientationTask(this, p, aOrientation, doc,
perm == FULLSCREEN_LOCK_ALLOWED);
aRv = NS_DispatchToMainThread(lockOrientationTask);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
return p.forget();
#endif
}
bool
ScreenOrientation::LockDeviceOrientation(ScreenOrientationInternal aOrientation,
bool aIsFullScreen, ErrorResult& aRv)
{
nsCOMPtr<EventTarget> target = do_QueryInterface(GetOwner()->GetDoc());
// We need to register a listener so we learn when we leave full-screen
// and when we will have to unlock the screen.
// This needs to be done before LockScreenOrientation call to make sure
// the locking can be unlocked.
if (aIsFullScreen && !target) {
return false;
}
if (NS_WARN_IF(!hal::LockScreenOrientation(aOrientation))) {
return false;
}
// We are fullscreen and lock has been accepted.
if (aIsFullScreen && !mFullScreenListener) {
mFullScreenListener = new FullScreenEventListener();
aRv = target->AddSystemEventListener(NS_LITERAL_STRING("mozfullscreenchange"),
mFullScreenListener, /* useCapture = */ true);
if (NS_WARN_IF(aRv.Failed())) {
return false;
}
}
return true;
}
void
ScreenOrientation::Unlock(ErrorResult& aRv)
{
nsRefPtr<Promise> p = LockInternal(eScreenOrientation_None, aRv);
}
void
ScreenOrientation::UnlockDeviceOrientation()
{
hal::UnlockScreenOrientation();
if (!mFullScreenListener) {
return;
}
// Remove event listener in case of fullscreen lock.
nsCOMPtr<EventTarget> target = do_QueryInterface(GetOwner()->GetDoc());
if (target) {
nsresult rv = target->RemoveSystemEventListener(NS_LITERAL_STRING("mozfullscreenchange"),
mFullScreenListener, /* useCapture */ true);
NS_WARN_IF(NS_FAILED(rv));
}
mFullScreenListener = nullptr;
}
OrientationType
ScreenOrientation::DeviceType() const
{
return mType;
}
uint16_t
ScreenOrientation::DeviceAngle() const
{
return mAngle;
}
OrientationType
ScreenOrientation::GetType(ErrorResult& aRv) const
{
nsIDocument* doc = GetResponsibleDocument();
if (!doc) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return OrientationType::Portrait_primary;
}
return doc->CurrentOrientationType();
}
uint16_t
ScreenOrientation::GetAngle(ErrorResult& aRv) const
{
nsIDocument* doc = GetResponsibleDocument();
if (!doc) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return 0;
}
return doc->CurrentOrientationAngle();
}
ScreenOrientation::LockPermission
ScreenOrientation::GetLockOrientationPermission(bool aCheckSandbox) const
{
nsCOMPtr<nsPIDOMWindow> owner = GetOwner();
if (!owner) {
return LOCK_DENIED;
}
// Chrome can always lock the screen orientation.
nsIDocShell* docShell = owner->GetDocShell();
if (docShell && docShell->ItemType() == nsIDocShellTreeItem::typeChrome) {
return LOCK_ALLOWED;
}
nsCOMPtr<nsIDocument> doc = owner->GetDoc();
if (!doc || doc->Hidden()) {
return LOCK_DENIED;
}
// Sandboxed without "allow-orientation-lock"
if (aCheckSandbox && doc->GetSandboxFlags() & SANDBOXED_ORIENTATION_LOCK) {
return LOCK_DENIED;
}
// Apps can always lock the screen orientation.
if (doc->NodePrincipal()->GetAppStatus() >=
nsIPrincipal::APP_STATUS_INSTALLED) {
return LOCK_ALLOWED;
}
if (Preferences::GetBool("dom.screenorientation.testing.non_fullscreen_lock_allow",
false)) {
return LOCK_ALLOWED;
}
// Other content must be full-screen in order to lock orientation.
return doc->MozFullScreen() ? FULLSCREEN_LOCK_ALLOWED : LOCK_DENIED;
}
nsIDocument*
ScreenOrientation::GetResponsibleDocument() const
{
nsCOMPtr<nsPIDOMWindow> owner = GetOwner();
if (!owner) {
return nullptr;
}
return owner->GetDoc();
}
void
ScreenOrientation::Notify(const hal::ScreenConfiguration& aConfiguration)
{
nsIDocument* doc = GetResponsibleDocument();
if (!doc) {
return;
}
ScreenOrientationInternal orientation = aConfiguration.orientation();
if (orientation != eScreenOrientation_PortraitPrimary &&
orientation != eScreenOrientation_PortraitSecondary &&
orientation != eScreenOrientation_LandscapePrimary &&
orientation != eScreenOrientation_LandscapeSecondary) {
// The platform may notify of some other values from
// an orientation lock, but we only care about real
// changes to screen orientation which result in one of
// the values we care about.
return;
}
OrientationType previousOrientation = mType;
mAngle = aConfiguration.angle();
mType = InternalOrientationToType(orientation);
nsresult rv;
if (mScreen && mType != previousOrientation) {
// Use of mozorientationchange is deprecated.
rv = mScreen->DispatchTrustedEvent(NS_LITERAL_STRING("mozorientationchange"));
NS_WARN_IF(NS_FAILED(rv));
}
if (doc->Hidden() && !mVisibleListener) {
mVisibleListener = new VisibleEventListener();
rv = doc->AddSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
mVisibleListener, /* useCapture = */ true);
NS_WARN_IF(NS_FAILED(rv));
return;
}
if (mType != doc->CurrentOrientationType()) {
doc->SetCurrentOrientation(mType, mAngle);
Promise* pendingPromise = doc->GetOrientationPendingPromise();
if (pendingPromise) {
pendingPromise->MaybeResolve(JS::UndefinedHandleValue);
doc->SetOrientationPendingPromise(nullptr);
}
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableMethod(this,
&ScreenOrientation::DispatchChangeEvent);
rv = NS_DispatchToMainThread(runnable);
NS_WARN_IF(NS_FAILED(rv));
}
}
void
ScreenOrientation::UpdateActiveOrientationLock(ScreenOrientationInternal aOrientation)
{
if (aOrientation == eScreenOrientation_None) {
hal::UnlockScreenOrientation();
} else {
hal::LockScreenOrientation(aOrientation);
}
}
void
ScreenOrientation::DispatchChangeEvent()
{
nsresult rv = DispatchTrustedEvent(NS_LITERAL_STRING("change"));
NS_WARN_IF(NS_FAILED(rv));
}
JSObject*
ScreenOrientation::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return ScreenOrientationBinding::Wrap(aCx, this, aGivenProto);
}
NS_IMPL_ISUPPORTS(ScreenOrientation::VisibleEventListener, nsIDOMEventListener)
NS_IMETHODIMP
ScreenOrientation::VisibleEventListener::HandleEvent(nsIDOMEvent* aEvent)
{
// Document may have become visible, if the page is visible, run the steps
// following the "now visible algorithm" as specified.
nsCOMPtr<EventTarget> target = aEvent->InternalDOMEvent()->GetCurrentTarget();
MOZ_ASSERT(target);
nsCOMPtr<nsIDocument> doc = do_QueryInterface(target);
if (!doc || doc->Hidden()) {
return NS_OK;
}
nsGlobalWindow* win = static_cast<nsGlobalWindow*>(doc->GetInnerWindow());
if (!win) {
return NS_OK;
}
ErrorResult rv;
nsScreen* screen = win->GetScreen(rv);
if (NS_WARN_IF(rv.Failed())) {
return rv.StealNSResult();
}
MOZ_ASSERT(screen);
ScreenOrientation* orientation = screen->Orientation();
MOZ_ASSERT(orientation);
rv = target->RemoveSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
this, true);
if (NS_WARN_IF(rv.Failed())) {
return rv.StealNSResult();
}
if (doc->CurrentOrientationType() != orientation->DeviceType()) {
doc->SetCurrentOrientation(orientation->DeviceType(), orientation->DeviceAngle());
Promise* pendingPromise = doc->GetOrientationPendingPromise();
if (pendingPromise) {
pendingPromise->MaybeResolve(JS::UndefinedHandleValue);
doc->SetOrientationPendingPromise(nullptr);
}
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableMethod(orientation,
&ScreenOrientation::DispatchChangeEvent);
rv = NS_DispatchToMainThread(runnable);
if (NS_WARN_IF(rv.Failed())) {
return rv.StealNSResult();
}
}
return NS_OK;
}
NS_IMPL_ISUPPORTS(ScreenOrientation::FullScreenEventListener, nsIDOMEventListener)
NS_IMETHODIMP
ScreenOrientation::FullScreenEventListener::HandleEvent(nsIDOMEvent* aEvent)
{
#ifdef DEBUG
nsAutoString eventType;
aEvent->GetType(eventType);
MOZ_ASSERT(eventType.EqualsLiteral("mozfullscreenchange"));
#endif
nsCOMPtr<EventTarget> target = aEvent->InternalDOMEvent()->GetCurrentTarget();
MOZ_ASSERT(target);
nsCOMPtr<nsIDocument> doc = do_QueryInterface(target);
MOZ_ASSERT(doc);
// We have to make sure that the event we got is the event sent when
// fullscreen is disabled because we could get one when fullscreen
// got enabled if the lock call is done at the same moment.
if (doc->MozFullScreen()) {
return NS_OK;
}
hal::UnlockScreenOrientation();
nsresult rv = target->RemoveSystemEventListener(NS_LITERAL_STRING("mozfullscreenchange"),
this, true);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
+91
View File
@@ -7,9 +7,16 @@
#ifndef mozilla_dom_ScreenOrientation_h
#define mozilla_dom_ScreenOrientation_h
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/dom/ScreenOrientationBinding.h"
#include "mozilla/HalScreenConfiguration.h"
class nsScreen;
namespace mozilla {
namespace dom {
class Promise;
// Make sure that any change to ScreenOrientationInternal values are
// also made in mobile/android/base/GeckoScreenOrientation.java
typedef uint32_t ScreenOrientationInternal;
@@ -23,6 +30,90 @@ static const ScreenOrientationInternal eScreenOrientation_LandscapeSecondary = 1
//it could be PortraitPrimary or LandscapePrimary depends on display resolution
static const ScreenOrientationInternal eScreenOrientation_Default = 1u << 4;
class ScreenOrientation final : public DOMEventTargetHelper,
public mozilla::hal::ScreenConfigurationObserver
{
// nsScreen has deprecated API that shares implementation.
friend class ::nsScreen;
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ScreenOrientation, mozilla::DOMEventTargetHelper)
NS_REALLY_FORWARD_NSIDOMEVENTTARGET(mozilla::DOMEventTargetHelper)
IMPL_EVENT_HANDLER(change)
ScreenOrientation(nsPIDOMWindow* aWindow, nsScreen* aScreen);
already_AddRefed<Promise> Lock(OrientationLockType aOrientation,
ErrorResult& aRv);
void Unlock(ErrorResult& aRv);
// DeviceType and DeviceAngle gets the current type and angle of the device.
OrientationType DeviceType() const;
uint16_t DeviceAngle() const;
// GetType and GetAngle gets the type and angle of the responsible document
// (as defined in specification).
OrientationType GetType(ErrorResult& aRv) const;
uint16_t GetAngle(ErrorResult& aRv) const;
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
void Notify(const mozilla::hal::ScreenConfiguration& aConfiguration) override;
static void UpdateActiveOrientationLock(ScreenOrientationInternal aOrientation);
private:
virtual ~ScreenOrientation();
// Listener to unlock orientation if we leave fullscreen.
class FullScreenEventListener;
// Listener to update document's orienation lock when document becomes
// visible.
class VisibleEventListener;
// Task to run step to lock orientation as defined in specification.
class LockOrientationTask;
enum LockPermission {
LOCK_DENIED,
FULLSCREEN_LOCK_ALLOWED,
LOCK_ALLOWED
};
// This method calls into the HAL to lock the device and sets
// up listeners for full screen change.
bool LockDeviceOrientation(ScreenOrientationInternal aOrientation,
bool aIsFullscreen, ErrorResult& aRv);
// This method calls in to the HAL to unlock the device and removes
// full screen change listener.
void UnlockDeviceOrientation();
// This method performs the same function as |Lock| except it takes
// a ScreenOrientationInternal argument instead of an OrientationType.
// This method exists in order to share implementation with nsScreen that
// uses ScreenOrientationInternal.
already_AddRefed<Promise> LockInternal(ScreenOrientationInternal aOrientation,
ErrorResult& aRv);
void DispatchChangeEvent();
LockPermission GetLockOrientationPermission(bool aCheckSandbox) const;
// Gets the responsible document as defined in the spec.
nsIDocument* GetResponsibleDocument() const;
nsRefPtr<nsScreen> mScreen;
nsRefPtr<FullScreenEventListener> mFullScreenListener;
nsRefPtr<VisibleEventListener> mVisibleListener;
OrientationType mType;
uint16_t mAngle;
};
} // namespace dom
} // namespace mozilla
+7
View File
@@ -7,11 +7,18 @@
#include "StructuredCloneHelper.h"
#include "ImageContainer.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/dom/BlobBinding.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/FileList.h"
#include "mozilla/dom/FileListBinding.h"
#include "mozilla/dom/ImageBitmap.h"
#include "mozilla/dom/ImageBitmapBinding.h"
#include "mozilla/dom/MessagePort.h"
#include "mozilla/dom/MessagePortBinding.h"
#include "mozilla/dom/PMessagePort.h"
#include "mozilla/dom/StructuredCloneTags.h"
#include "mozilla/dom/ToJSValue.h"
namespace mozilla {
namespace dom {
+1
View File
@@ -12,6 +12,7 @@
#include "nsTArray.h"
namespace mozilla {
class ErrorResult;
namespace layers {
class Image;
}
+1
View File
@@ -333,6 +333,7 @@ UNIFIED_SOURCES += [
'ProcessGlobal.cpp',
'ResponsiveImageSelector.cpp',
'SameProcessMessageQueue.cpp',
'ScreenOrientation.cpp',
'ScriptSettings.cpp',
'ShadowRoot.cpp',
'StructuredCloneHelper.cpp',
+3
View File
@@ -25,6 +25,9 @@
#include "mozilla/MemoryReporting.h"
#include "mozilla/dom/BindingDeclarations.h"
// Undefine LoadImage to prevent naming conflict with Windows.
#undef LoadImage
class nsAString;
class nsIDocument;
class nsStyledElementNotElementCSSInlineStyle;
+2
View File
@@ -1341,6 +1341,7 @@ nsContentUtils::ParseSandboxAttributeToFlags(const nsAttrValue* sandboxAttr)
| SANDBOXED_SCRIPTS
| SANDBOXED_AUTOMATIC_FEATURES
| SANDBOXED_POINTER_LOCK
| SANDBOXED_ORIENTATION_LOCK
| SANDBOXED_DOMAIN;
// Macro for updating the flag according to the keywords
@@ -1352,6 +1353,7 @@ nsContentUtils::ParseSandboxAttributeToFlags(const nsAttrValue* sandboxAttr)
IF_KEYWORD(allowscripts, SANDBOXED_SCRIPTS | SANDBOXED_AUTOMATIC_FEATURES)
IF_KEYWORD(allowtopnavigation, SANDBOXED_TOPLEVEL_NAVIGATION)
IF_KEYWORD(allowpointerlock, SANDBOXED_POINTER_LOCK)
IF_KEYWORD(alloworientationlock, SANDBOXED_ORIENTATION_LOCK)
IF_KEYWORD(allowpopups, SANDBOXED_AUXILIARY_NAVIGATION)
return out;
+35
View File
@@ -38,6 +38,7 @@
#include "nsQueryObject.h"
#include "nsDOMClassInfo.h"
#include "mozilla/Services.h"
#include "nsScreen.h"
#include "mozilla/AsyncEventDispatcher.h"
#include "mozilla/BasicEvents.h"
@@ -1922,6 +1923,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFirstBaseNodeWithHref)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMImplementation)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mImageMaps)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOrientationPendingPromise)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOriginalDocument)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCachedEncoder)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStateObjectCached)
@@ -2022,6 +2024,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mChildrenCollection)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mRegistry)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mMasterDocument)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOrientationPendingPromise)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mImportManager)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSubImportLinks)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFontFaceSet)
@@ -12032,6 +12035,38 @@ nsDocument::IsFullScreenEnabled(bool aCallerIsChrome, bool aLogFailure)
return allowed;
}
uint16_t
nsDocument::CurrentOrientationAngle() const
{
return mCurrentOrientationAngle;
}
OrientationType
nsDocument::CurrentOrientationType() const
{
return mCurrentOrientationType;
}
void
nsDocument::SetCurrentOrientation(mozilla::dom::OrientationType aType,
uint16_t aAngle)
{
mCurrentOrientationType = aType;
mCurrentOrientationAngle = aAngle;
}
Promise*
nsDocument::GetOrientationPendingPromise() const
{
return mOrientationPendingPromise;
}
void
nsDocument::SetOrientationPendingPromise(Promise* aPromise)
{
mOrientationPendingPromise = aPromise;
}
static void
DispatchPointerLockChange(nsIDocument* aTarget)
{
+16
View File
@@ -1273,6 +1273,13 @@ public:
bool SetPointerLock(Element* aElement, int aCursorStyle);
static void UnlockPointer(nsIDocument* aDoc = nullptr);
void SetCurrentOrientation(mozilla::dom::OrientationType aType,
uint16_t aAngle) override;
uint16_t CurrentOrientationAngle() const override;
mozilla::dom::OrientationType CurrentOrientationType() const override;
void SetOrientationPendingPromise(mozilla::dom::Promise* aPromise) override;
mozilla::dom::Promise* GetOrientationPendingPromise() const override;
// This method may fire a DOM event; if it does so it will happen
// synchronously.
void UpdateVisibilityState();
@@ -1510,6 +1517,8 @@ protected:
virtual nsIScriptGlobalObject* GetScriptHandlingObjectInternal() const override;
virtual bool InternalAllowXULXBL() override;
void UpdateScreenOrientation();
#define NS_DOCUMENT_NOTIFY_OBSERVERS(func_, params_) \
NS_OBSERVER_ARRAY_NOTIFY_XPCOM_OBSERVERS(mObservers, nsIDocumentObserver, \
func_, params_);
@@ -1674,6 +1683,13 @@ public:
bool mAsyncFullscreenPending:1;
// ScreenOrientation "pending promise" as described by
// http://www.w3.org/TR/screen-orientation/
nsRefPtr<mozilla::dom::Promise> mOrientationPendingPromise;
uint16_t mCurrentOrientationAngle;
mozilla::dom::OrientationType mCurrentOrientationType;
// Whether we're observing the "app-theme-changed" observer service
// notification. We need to keep track of this because we might get multiple
// OnPageShow notifications in a row without an OnPageHide in between, if
+1
View File
@@ -79,6 +79,7 @@ GK_ATOM(allowevents, "allowevents")
GK_ATOM(allownegativeassertions, "allownegativeassertions")
GK_ATOM(allowforms,"allow-forms")
GK_ATOM(allowfullscreen, "allowfullscreen")
GK_ATOM(alloworientationlock,"allow-orientation-lock")
GK_ATOM(allowpointerlock,"allow-pointer-lock")
GK_ATOM(allowpopups,"allow-popups")
GK_ATOM(allowsameorigin,"allow-same-origin")
+10
View File
@@ -132,7 +132,9 @@ class MediaQueryList;
class GlobalObject;
class NodeFilter;
class NodeIterator;
enum class OrientationType : uint32_t;
class ProcessingInstruction;
class Promise;
class Selection;
class StyleSheetList;
class SVGDocument;
@@ -1204,6 +1206,14 @@ public:
static void UnlockPointer(nsIDocument* aDoc = nullptr);
// ScreenOrientation related APIs
virtual void SetCurrentOrientation(mozilla::dom::OrientationType aType,
uint16_t aAngle) = 0;
virtual uint16_t CurrentOrientationAngle() const = 0;
virtual mozilla::dom::OrientationType CurrentOrientationType() const = 0;
virtual void SetOrientationPendingPromise(mozilla::dom::Promise* aPromise) = 0;
virtual mozilla::dom::Promise* GetOrientationPendingPromise() const = 0;
//----------------------------------------------------------------------
+5
View File
@@ -76,4 +76,9 @@ const unsigned long SANDBOXED_DOMAIN = 0x100;
* showModalDialog() method.
*/
const unsigned long SANDBOXED_AUXILIARY_NAVIGATION = 0x200;
/**
* This flag prevents locking screen orientation.
*/
const unsigned long SANDBOXED_ORIENTATION_LOCK = 0x400;
#endif
+23 -136
View File
@@ -4,7 +4,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/Hal.h"
#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent()
#include "mozilla/dom/ScreenBinding.h"
#include "nsScreen.h"
@@ -36,36 +35,32 @@ nsScreen::Create(nsPIDOMWindow* aWindow)
NS_ENSURE_TRUE(sgo, nullptr);
nsRefPtr<nsScreen> screen = new nsScreen(aWindow);
hal::RegisterScreenConfigurationObserver(screen);
hal::ScreenConfiguration config;
hal::GetCurrentScreenConfiguration(&config);
screen->mOrientationInternal = config.orientation();
return screen.forget();
}
nsScreen::nsScreen(nsPIDOMWindow* aWindow)
: DOMEventTargetHelper(aWindow)
, mEventListener(nullptr)
, mScreenOrientation(new ScreenOrientation(aWindow, this))
{
}
nsScreen::~nsScreen()
{
MOZ_ASSERT(!mEventListener);
hal::UnregisterScreenConfigurationObserver(this);
}
// QueryInterface implementation for nsScreen
NS_INTERFACE_MAP_BEGIN(nsScreen)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsScreen)
NS_INTERFACE_MAP_ENTRY(nsIDOMScreen)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
NS_IMPL_ADDREF_INHERITED(nsScreen, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(nsScreen, DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_INHERITED(nsScreen,
DOMEventTargetHelper,
mScreenOrientation)
int32_t
nsScreen::GetPixelDepth(ErrorResult& aRv)
{
@@ -162,45 +157,33 @@ nsScreen::GetAvailRect(nsRect& aRect)
return NS_OK;
}
void
nsScreen::Notify(const hal::ScreenConfiguration& aConfiguration)
mozilla::dom::ScreenOrientation*
nsScreen::Orientation() const
{
ScreenOrientationInternal previousOrientation = mOrientationInternal;
mOrientationInternal = aConfiguration.orientation();
NS_ASSERTION(mOrientationInternal == eScreenOrientation_PortraitPrimary ||
mOrientationInternal == eScreenOrientation_PortraitSecondary ||
mOrientationInternal == eScreenOrientation_LandscapePrimary ||
mOrientationInternal == eScreenOrientation_LandscapeSecondary,
"Invalid orientation value passed to notify method!");
if (mOrientationInternal != previousOrientation) {
DispatchTrustedEvent(NS_LITERAL_STRING("mozorientationchange"));
}
return mScreenOrientation;
}
void
nsScreen::GetMozOrientation(nsString& aOrientation)
nsScreen::GetMozOrientation(nsString& aOrientation) const
{
if (ShouldResistFingerprinting()) {
aOrientation.AssignLiteral("landscape-primary");
} else {
switch (mOrientationInternal) {
case eScreenOrientation_PortraitPrimary:
switch (mScreenOrientation->DeviceType()) {
case OrientationType::Portrait_primary:
aOrientation.AssignLiteral("portrait-primary");
break;
case eScreenOrientation_PortraitSecondary:
case OrientationType::Portrait_secondary:
aOrientation.AssignLiteral("portrait-secondary");
break;
case eScreenOrientation_LandscapePrimary:
case OrientationType::Landscape_primary:
aOrientation.AssignLiteral("landscape-primary");
break;
case eScreenOrientation_LandscapeSecondary:
case OrientationType::Landscape_secondary:
aOrientation.AssignLiteral("landscape-secondary");
break;
case eScreenOrientation_None:
default:
MOZ_CRASH("Unacceptable mOrientationInternal value");
MOZ_CRASH("Unacceptable screen orientation type.");
}
}
}
@@ -214,35 +197,6 @@ nsScreen::GetSlowMozOrientation(nsAString& aOrientation)
return NS_OK;
}
nsScreen::LockPermission
nsScreen::GetLockOrientationPermission() const
{
nsCOMPtr<nsPIDOMWindow> owner = GetOwner();
if (!owner) {
return LOCK_DENIED;
}
// Chrome can always lock the screen orientation.
nsIDocShell* docShell = owner->GetDocShell();
if (docShell && docShell->ItemType() == nsIDocShellTreeItem::typeChrome) {
return LOCK_ALLOWED;
}
nsCOMPtr<nsIDocument> doc = owner->GetDoc();
if (!doc || doc->Hidden()) {
return LOCK_DENIED;
}
// Apps can always lock the screen orientation.
if (doc->NodePrincipal()->GetAppStatus() >=
nsIPrincipal::APP_STATUS_INSTALLED) {
return LOCK_ALLOWED;
}
// Other content must be full-screen in order to lock orientation.
return doc->MozFullScreen() ? FULLSCREEN_LOCK_ALLOWED : LOCK_DENIED;
}
bool
nsScreen::MozLockOrientation(const nsAString& aOrientation, ErrorResult& aRv)
{
@@ -287,34 +241,13 @@ nsScreen::MozLockOrientation(const Sequence<nsString>& aOrientations,
}
}
switch (GetLockOrientationPermission()) {
case LOCK_DENIED:
switch (mScreenOrientation->GetLockOrientationPermission(false)) {
case ScreenOrientation::LOCK_DENIED:
return false;
case LOCK_ALLOWED:
return hal::LockScreenOrientation(orientation);
case FULLSCREEN_LOCK_ALLOWED: {
// We need to register a listener so we learn when we leave full-screen
// and when we will have to unlock the screen.
// This needs to be done before LockScreenOrientation call to make sure
// the locking can be unlocked.
nsCOMPtr<EventTarget> target = do_QueryInterface(GetOwner()->GetDoc());
if (!target) {
return false;
}
if (!hal::LockScreenOrientation(orientation)) {
return false;
}
// We are fullscreen and lock has been accepted.
if (!mEventListener) {
mEventListener = new FullScreenEventListener();
}
aRv = target->AddSystemEventListener(NS_LITERAL_STRING("mozfullscreenchange"),
mEventListener, /* useCapture = */ true);
return true;
}
case ScreenOrientation::LOCK_ALLOWED:
return mScreenOrientation->LockDeviceOrientation(orientation, false, aRv);
case ScreenOrientation::FULLSCREEN_LOCK_ALLOWED:
return mScreenOrientation->LockDeviceOrientation(orientation, true, aRv);
}
// This is only for compilers that don't understand that the previous switch
@@ -325,20 +258,7 @@ nsScreen::MozLockOrientation(const Sequence<nsString>& aOrientations,
void
nsScreen::MozUnlockOrientation()
{
hal::UnlockScreenOrientation();
if (!mEventListener) {
return;
}
// Remove event listener in case of fullscreen lock.
nsCOMPtr<EventTarget> target = do_QueryInterface(GetOwner()->GetDoc());
if (target) {
target->RemoveSystemEventListener(NS_LITERAL_STRING("mozfullscreenchange"),
mEventListener, /* useCapture */ true);
}
mEventListener = nullptr;
mScreenOrientation->UnlockDeviceOrientation();
}
bool
@@ -361,39 +281,6 @@ nsScreen::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
return ScreenBinding::Wrap(aCx, this, aGivenProto);
}
NS_IMPL_ISUPPORTS(nsScreen::FullScreenEventListener, nsIDOMEventListener)
NS_IMETHODIMP
nsScreen::FullScreenEventListener::HandleEvent(nsIDOMEvent* aEvent)
{
#ifdef DEBUG
nsAutoString eventType;
aEvent->GetType(eventType);
MOZ_ASSERT(eventType.EqualsLiteral("mozfullscreenchange"));
#endif
nsCOMPtr<EventTarget> target = aEvent->InternalDOMEvent()->GetCurrentTarget();
MOZ_ASSERT(target);
nsCOMPtr<nsIDocument> doc = do_QueryInterface(target);
MOZ_ASSERT(doc);
// We have to make sure that the event we got is the event sent when
// fullscreen is disabled because we could get one when fullscreen
// got enabled if the lock call is done at the same moment.
if (doc->MozFullScreen()) {
return NS_OK;
}
target->RemoveSystemEventListener(NS_LITERAL_STRING("mozfullscreenchange"),
this, true);
hal::UnlockScreenOrientation();
return NS_OK;
}
nsresult
nsScreen::GetWindowInnerRect(nsRect& aRect)
{
+5 -25
View File
@@ -10,7 +10,6 @@
#include "mozilla/dom/ScreenOrientation.h"
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/HalScreenConfiguration.h"
#include "nsIDOMScreen.h"
#include "nsCOMPtr.h"
#include "nsRect.h"
@@ -20,7 +19,6 @@ class nsDeviceContext;
// Script "screen" object
class nsScreen : public mozilla::DOMEventTargetHelper
, public nsIDOMScreen
, public mozilla::hal::ScreenConfigurationObserver
{
typedef mozilla::ErrorResult ErrorResult;
public:
@@ -28,6 +26,7 @@ public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIDOMSCREEN
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsScreen, mozilla::DOMEventTargetHelper)
NS_REALLY_FORWARD_NSIDOMEVENTTARGET(mozilla::DOMEventTargetHelper)
nsPIDOMWindow* GetParentObject() const
@@ -115,7 +114,8 @@ public:
return rect.height;
}
void GetMozOrientation(nsString& aOrientation);
// Deprecated
void GetMozOrientation(nsString& aOrientation) const;
IMPL_EVENT_HANDLER(mozorientationchange)
@@ -125,7 +125,7 @@ public:
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
void Notify(const mozilla::hal::ScreenConfiguration& aConfiguration) override;
mozilla::dom::ScreenOrientation* Orientation() const;
protected:
nsDeviceContext* GetDeviceContext();
@@ -133,35 +133,15 @@ protected:
nsresult GetAvailRect(nsRect& aRect);
nsresult GetWindowInnerRect(nsRect& aRect);
mozilla::dom::ScreenOrientationInternal mOrientationInternal;
private:
class FullScreenEventListener final : public nsIDOMEventListener
{
~FullScreenEventListener() {}
public:
FullScreenEventListener() {}
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMEVENTLISTENER
};
explicit nsScreen(nsPIDOMWindow* aWindow);
virtual ~nsScreen();
enum LockPermission {
LOCK_DENIED,
FULLSCREEN_LOCK_ALLOWED,
LOCK_ALLOWED
};
LockPermission GetLockOrientationPermission() const;
bool IsDeviceSizePageSize();
bool ShouldResistFingerprinting() const;
nsRefPtr<FullScreenEventListener> mEventListener;
nsRefPtr<mozilla::dom::ScreenOrientation> mScreenOrientation;
};
#endif /* nsScreen_h___ */
+14
View File
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<body>
<script src="orientationcommon.js"></script>
<script>
window.addEventListener("message", function(event) {
var p = specialPowersLock(event.data);
p.then(function() {
event.source.postMessage("success", "*");
}).catch(function(err) {
event.source.postMessage("error", "*");
});
}, false);
</script>
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<body>
<script>
var recordedOrientations = [];
screen.orientation.onchange = function() {
recordedOrientations.push(screen.orientation.type);
};
window.addEventListener("message", function(event) {
if (event.data == "report") {
event.source.postMessage(recordedOrientations, "*");
}
}, false);
</script>
+11
View File
@@ -179,11 +179,13 @@ support-files =
file_htmlserializer_2_latin1.html
file_htmlserializer_ipv6.html
file_htmlserializer_ipv6_out.html
file_lock_orientation.html
file_mozfiledataurl_audio.ogg
file_mozfiledataurl_doc.html
file_mozfiledataurl_img.jpg
file_mozfiledataurl_inner.html
file_mozfiledataurl_text.txt
file_record_orientation.html
file_restrictedEventSource.sjs
file_simplecontentpolicy.js
file_websocket_basic_wsh.py
@@ -222,6 +224,7 @@ support-files =
invalid_accesscontrol.resource
invalid_accesscontrol.resource^headers^
mutationobserver_dialog.html
orientationcommon.js
progressserver.sjs
responseIdentical.sjs
script-1_bug597345.sjs
@@ -304,6 +307,14 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Fails on b2g-desktop, track
[test_pluginAudioNotification.html]
skip-if = (buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'android') # Plugins don't work on Android and/or B2G/Mulet
[test_screen_orientation.html]
[test_orientation_alternate.html]
skip-if = toolkit != 'gonk'
[test_orientation_frame.html]
skip-if = toolkit != 'gonk'
[test_orientation_frame_lock.html]
skip-if = toolkit != 'gonk'
[test_orientation_sandbox_no_lock.html]
skip-if = toolkit != 'gonk'
[test_settimeout_extra_arguments.html]
[test_settimeout_inner.html]
[test_setting_opener.html]
+21
View File
@@ -0,0 +1,21 @@
function specialPowersLock(orientation) {
return new Promise(function(resolve, reject) {
SpecialPowers.pushPrefEnv({
'set': [ ["dom.screenorientation.testing.non_fullscreen_lock_allow", true] ]
}, function() {
var p = screen.orientation.lock(orientation);
resolve(p);
});
});
}
function specialPowersUnlock() {
return new Promise(function(resolve, reject) {
SpecialPowers.pushPrefEnv({
'set': [ ["dom.screenorientation.testing.non_fullscreen_lock_allow", true] ]
}, function() {
screen.orientation.unlock();
resolve();
});
});
}
@@ -0,0 +1,27 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Test for ScreenOrientation API</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="orientationcommon.js"></script>
<div id="log"></div>
<script>
async_test(function(t) {
var originalOrientation = screen.orientation.type;
var alternateOrientation = originalOrientation == "portrait-primary" ?
"landscape-primary" : "portrait-primary";
var p = specialPowersLock(alternateOrientation);
p.then(function() {
t.step(function() { assert_equals(screen.orientation.type, alternateOrientation); });
return specialPowersLock(originalOrientation);
}).then(function() {
t.step(function() { assert_equals(screen.orientation.type, originalOrientation); });
return specialPowersUnlock();
}).then(function() {
t.done();
}).catch(t.step_func(function(err) {
assert_unreached("Error setting orientation: " + err);
t.done();
}));
}, "Test locking and unlocking orientation.");
</script>
+37
View File
@@ -0,0 +1,37 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Test for ScreenOrientation API</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="orientationcommon.js"></script>
<div id="log"></div>
<iframe id="frame"></iframe>
<script>
async_test(function(t) {
var originalOrientation = screen.orientation.type;
var alternateOrientation = originalOrientation == "portrait-primary" ?
"landscape-primary" : "portrait-primary";
window.addEventListener("message", function(event) {
t.step(function() { assert_array_equals(event.data, [alternateOrientation, originalOrientation]); });
t.done();
}, false);
var frame = document.getElementById("frame");
frame.src = "file_record_orientation.html";
frame.onload = function() {
var p = specialPowersLock(alternateOrientation);
p.then(function() {
return specialPowersLock(originalOrientation);
}).then(function() {
return specialPowersUnlock();
}).then(function() {
frame.contentWindow.postMessage("report", "*");
}).catch(t.step_func(function(err) {
assert_unreached("Error setting orientation: " + err);
t.done();
}));
};
}, "Test orientation change event in frame.");
</script>
@@ -0,0 +1,46 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Test for ScreenOrientation API</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="orientationcommon.js"></script>
<div id="log"></div>
<iframe sandbox="allow-scripts allow-orientation-lock" id="frame"></iframe>
<script>
async_test(function(t) {
var originalOrientation = screen.orientation.type;
var alternateOrientation = originalOrientation == "portrait-primary" ?
"landscape-primary" : "portrait-primary";
var orientationChanges = [];
window.screen.orientation.onchange = function() {
orientationChanges.push(screen.orientation.type);
};
window.addEventListener("message", function(event) {
t.step(function() {
assert_equals(event.data, "success");
assert_array_equals(orientationChanges, [ alternateOrientation ]);
});
// Return the orientation to its original settings.
var p = specialPowersLock(originalOrientation);
p.then(function() {
return specialPowersUnlock();
}).then(function() {
t.done();
}).catch(t.step_func(function(err) {
assert_unreached("Error setting orientation: " + err);
t.done();
}));
}, false);
var frame = document.getElementById("frame");
frame.src = "http://example.com/tests/dom/base/test/file_lock_orientation.html";
frame.onload = function() {
assert_array_equals(orientationChanges, []);
frame.contentWindow.postMessage(alternateOrientation, "*");
};
}, "Test orientation lock from within a frame with sandbox permission.");
</script>
@@ -0,0 +1,36 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Test for ScreenOrientation API</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="orientationcommon.js"></script>
<div id="log"></div>
<iframe sandbox="allow-scripts" id="frame"></iframe>
<script>
async_test(function(t) {
var originalOrientation = screen.orientation.type;
var alternateOrientation = originalOrientation == "portrait-primary" ?
"landscape-primary" : "portrait-primary";
var orientationChanges = [];
window.screen.orientation.onchange = function() {
orientationChanges.push(screen.orientation.type);
};
window.addEventListener("message", function(event) {
t.step(function() {
assert_equals(event.data, "error");
assert_array_equals(orientationChanges, []);
t.done();
});
}, false);
var frame = document.getElementById("frame");
frame.src = "http://example.com/tests/dom/base/test/file_lock_orientation.html";
frame.onload = function() {
assert_array_equals(orientationChanges, []);
frame.contentWindow.postMessage(alternateOrientation, "*");
};
}, "Test orientation lock from within a frame without sandbox permission.");
</script>
+2
View File
@@ -18,6 +18,8 @@ struct JSContext;
struct JSStructuredCloneReader;
struct JSStructuredCloneWriter;
class nsIGlobalObject;
namespace mozilla {
class ErrorResult;
+1 -1
View File
@@ -14,11 +14,11 @@
class nsISmsService;
class nsIDOMMozSmsMessage;
class nsIDOMMozMmsMessage;
class Promise;
namespace mozilla {
namespace dom {
class Promise;
class DOMRequest;
class DOMCursor;
struct MmsParameters;
@@ -965,6 +965,8 @@ var interfaceNamesInGlobalScope =
"RTCStatsReport",
// IMPORTANT: Do not change this list without review from a DOM peer!
"Screen",
// IMPORTANT: Do not change this list without review from a DOM peer!
"ScreenOrientation",
// IMPORTANT: Do not change this list without review from a DOM peer!
"ScriptProcessorNode",
// IMPORTANT: Do not change this list without review from a DOM peer!
+8
View File
@@ -29,6 +29,7 @@ interface Screen : EventTarget {
readonly attribute long availLeft;
/**
* DEPRECATED, use ScreenOrientation API instead.
* Returns the current screen orientation.
* Can be: landscape-primary, landscape-secondary,
* portrait-primary or portrait-secondary.
@@ -38,6 +39,7 @@ interface Screen : EventTarget {
attribute EventHandler onmozorientationchange;
/**
* DEPRECATED, use ScreenOrientation API instead.
* Lock screen orientation to the specified type.
*/
[Throws, UnsafeInPrerendering]
@@ -46,8 +48,14 @@ interface Screen : EventTarget {
boolean mozLockOrientation(sequence<DOMString> orientation);
/**
* DEPRECATED, use ScreenOrientation API instead.
* Unlock the screen orientation.
*/
[UnsafeInPrerendering]
void mozUnlockOrientation();
};
// https://w3c.github.io/screen-orientation
partial interface Screen {
readonly attribute ScreenOrientation orientation;
};
+42
View File
@@ -0,0 +1,42 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/.
*
* The origin of this IDL file is
* https://w3c.github.io/screen-orientation
*
* Copyright © 2014 W3C® (MIT, ERCIM, Keio, Beihang), All Rights
* Reserved. W3C liability, trademark and document use rules apply.
*/
enum OrientationType {
"portrait-primary",
"portrait-secondary",
"landscape-primary",
"landscape-secondary"
};
enum OrientationLockType {
"any",
"natural",
"landscape",
"portrait",
"portrait-primary",
"portrait-secondary",
"landscape-primary",
"landscape-secondary"
};
[UnsafeInPrerendering]
interface ScreenOrientation : EventTarget {
[Throws]
Promise<void> lock(OrientationLockType orientation);
[Throws]
void unlock();
[Throws]
readonly attribute OrientationType type;
[Throws]
readonly attribute unsigned short angle;
attribute EventHandler onchange;
};
+1
View File
@@ -385,6 +385,7 @@ WEBIDL_FILES = [
'RGBColor.webidl',
'RTCStatsReport.webidl',
'Screen.webidl',
'ScreenOrientation.webidl',
'ScriptProcessorNode.webidl',
'ScrollAreaEvent.webidl',
'ScrollBoxObject.webidl',
+4 -12
View File
@@ -52,11 +52,6 @@ ServiceWorker::ServiceWorker(nsPIDOMWindow* aWindow,
MOZ_ASSERT(aInfo);
MOZ_ASSERT(mSharedWorker);
if (aWindow) {
mDocument = aWindow->GetExtantDoc();
mWindow = aWindow->GetOuterWindow();
}
// This will update our state too.
mInfo->AppendWorker(this);
}
@@ -74,7 +69,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ServiceWorker)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_INHERITED(ServiceWorker, DOMEventTargetHelper,
mSharedWorker, mDocument, mWindow)
mSharedWorker)
JSObject*
ServiceWorker::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
@@ -103,12 +98,9 @@ ServiceWorker::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
return;
}
MOZ_ASSERT(mDocument && mWindow,
"Cannot call PostMessage on a ServiceWorker object that doesn't "
"have a window");
nsAutoPtr<ServiceWorkerClientInfo> clientInfo(
new ServiceWorkerClientInfo(mDocument, mWindow));
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(GetParentObject());
nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
nsAutoPtr<ServiceWorkerClientInfo> clientInfo(new ServiceWorkerClientInfo(doc));
workerPrivate->PostMessageToServiceWorker(aCx, aMessage, aTransferable,
clientInfo, aRv);
-5
View File
@@ -11,7 +11,6 @@
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/ServiceWorkerBinding.h" // For ServiceWorkerState.
class nsIDocument;
class nsPIDOMWindow;
namespace mozilla {
@@ -92,10 +91,6 @@ private:
// can be released and recreated as required rather than re-implement some of
// the SharedWorker logic.
nsRefPtr<SharedWorker> mSharedWorker;
// We need to keep the document and window alive for PostMessage to be able
// to access them.
nsCOMPtr<nsIDocument> mDocument;
nsCOMPtr<nsPIDOMWindow> mWindow;
};
} // namespace workers
+4 -5
View File
@@ -29,8 +29,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ServiceWorkerClient)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
ServiceWorkerClientInfo::ServiceWorkerClientInfo(nsIDocument* aDoc,
nsPIDOMWindow* aWindow)
ServiceWorkerClientInfo::ServiceWorkerClientInfo(nsIDocument* aDoc)
: mWindowId(0)
{
MOZ_ASSERT(aDoc);
@@ -55,7 +54,7 @@ ServiceWorkerClientInfo::ServiceWorkerClientInfo(nsIDocument* aDoc,
NS_WARNING("Failed to get focus information.");
}
nsRefPtr<nsGlobalWindow> outerWindow = static_cast<nsGlobalWindow*>(aWindow);
nsRefPtr<nsGlobalWindow> outerWindow = static_cast<nsGlobalWindow*>(aDoc->GetWindow());
MOZ_ASSERT(outerWindow);
if (!outerWindow->IsTopLevelWindow()) {
mFrameType = FrameType::Nested;
@@ -135,7 +134,7 @@ private:
JS::Rooted<JS::Value> messageData(aCx);
if (!mBuffer.read(aCx, &messageData,
WorkerStructuredCloneCallbacks(true), &closure)) {
WorkerStructuredCloneCallbacks(), &closure)) {
xpc::Throw(aCx, NS_ERROR_DOM_DATA_CLONE_ERR);
return NS_ERROR_FAILURE;
}
@@ -195,7 +194,7 @@ ServiceWorkerClient::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
transferable.setObject(*array);
}
const JSStructuredCloneCallbacks* callbacks = WorkerStructuredCloneCallbacks(false);
const JSStructuredCloneCallbacks* callbacks = WorkerStructuredCloneCallbacks();
WorkerStructuredCloneClosure closure;
+1 -2
View File
@@ -15,7 +15,6 @@
#include "mozilla/dom/ClientBinding.h"
class nsIDocument;
class nsPIDOMWindow;
namespace mozilla {
namespace dom {
@@ -32,7 +31,7 @@ class ServiceWorkerClientInfo final
friend class ServiceWorkerWindowClient;
public:
ServiceWorkerClientInfo(nsIDocument* aDoc, nsPIDOMWindow* aWindow);
explicit ServiceWorkerClientInfo(nsIDocument* aDoc);
private:
nsString mClientId;
+2 -2
View File
@@ -3876,7 +3876,7 @@ ServiceWorkerManager::DispatchFetchEvent(const OriginAttributes& aOriginAttribut
MOZ_ASSERT(aDoc);
aRv = GetDocumentController(aDoc->GetInnerWindow(), failRunnable,
getter_AddRefs(serviceWorker));
clientInfo = new ServiceWorkerClientInfo(aDoc, aDoc->GetWindow());
clientInfo = new ServiceWorkerClientInfo(aDoc);
} else {
nsCOMPtr<nsIChannel> internalChannel;
aRv = aChannel->GetChannel(getter_AddRefs(internalChannel));
@@ -4261,7 +4261,7 @@ EnumControlledDocuments(nsISupports* aKey,
return PL_DHASH_NEXT;
}
ServiceWorkerClientInfo clientInfo(document, document->GetWindow());
ServiceWorkerClientInfo clientInfo(document);
data->mDocuments.AppendElement(clientInfo);
return PL_DHASH_NEXT;
+8 -3
View File
@@ -91,9 +91,14 @@ public:
UniquePtr<ServiceWorkerClientInfo> clientInfo;
if (window) {
nsContentUtils::DispatchChromeEvent(window->GetExtantDoc(), window->GetOuterWindow(), NS_LITERAL_STRING("DOMServiceWorkerFocusClient"), true, true);
clientInfo.reset(new ServiceWorkerClientInfo(window->GetDocument(),
window->GetOuterWindow()));
nsCOMPtr<nsIDocument> doc = window->GetDocument();
if (doc) {
nsContentUtils::DispatchChromeEvent(doc,
window->GetOuterWindow(),
NS_LITERAL_STRING("DOMServiceWorkerFocusClient"),
true, true);
clientInfo.reset(new ServiceWorkerClientInfo(doc));
}
}
DispatchResult(Move(clientInfo));
+46 -277
View File
@@ -406,8 +406,7 @@ EnsureBlobForBackgroundManager(BlobImpl* aBlobImpl,
already_AddRefed<Blob>
ReadBlobOrFileNoWrap(JSContext* aCx,
JSStructuredCloneReader* aReader,
bool aIsMainThread)
JSStructuredCloneReader* aReader)
{
MOZ_ASSERT(aCx);
MOZ_ASSERT(aReader);
@@ -426,14 +425,11 @@ ReadBlobOrFileNoWrap(JSContext* aCx,
MOZ_ASSERT(blobImpl);
nsCOMPtr<nsISupports> parent;
if (aIsMainThread) {
AssertIsOnMainThread();
if (NS_IsMainThread()) {
nsCOMPtr<nsIScriptGlobalObject> scriptGlobal =
nsJSUtils::GetStaticScriptGlobal(JS::CurrentGlobalOrNull(aCx));
parent = do_QueryInterface(scriptGlobal);
} else {
MOZ_ASSERT(!NS_IsMainThread());
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
MOZ_ASSERT(workerPrivate);
@@ -450,10 +446,9 @@ ReadBlobOrFileNoWrap(JSContext* aCx,
void
ReadBlobOrFile(JSContext* aCx,
JSStructuredCloneReader* aReader,
bool aIsMainThread,
JS::MutableHandle<JSObject*> aBlobOrFile)
{
nsRefPtr<Blob> blob = ReadBlobOrFileNoWrap(aCx, aReader, aIsMainThread);
nsRefPtr<Blob> blob = ReadBlobOrFileNoWrap(aCx, aReader);
aBlobOrFile.set(blob->WrapObject(aCx, nullptr));
}
@@ -461,7 +456,6 @@ ReadBlobOrFile(JSContext* aCx,
void
ReadFormData(JSContext* aCx,
JSStructuredCloneReader* aReader,
bool aIsMainThread,
uint32_t aCount,
JS::MutableHandle<JSObject*> aFormData)
{
@@ -470,8 +464,7 @@ ReadFormData(JSContext* aCx,
MOZ_ASSERT(!aFormData);
nsCOMPtr<nsISupports> parent;
if (aIsMainThread) {
AssertIsOnMainThread();
if (NS_IsMainThread()) {
nsCOMPtr<nsIScriptGlobalObject> scriptGlobal =
nsJSUtils::GetStaticScriptGlobal(JS::CurrentGlobalOrNull(aCx));
parent = do_QueryInterface(scriptGlobal);
@@ -502,7 +495,7 @@ ReadFormData(JSContext* aCx,
if (isFile) {
// Read out the tag since the blob reader isn't expecting it.
MOZ_ALWAYS_TRUE(JS_ReadUint32Pair(aReader, &dummy, &dummy));
nsRefPtr<Blob> blob = ReadBlobOrFileNoWrap(aCx, aReader, aIsMainThread);
nsRefPtr<Blob> blob = ReadBlobOrFileNoWrap(aCx, aReader);
MOZ_ASSERT(blob);
formData->Append(name, *blob, thirdArg);
} else {
@@ -516,28 +509,29 @@ ReadFormData(JSContext* aCx,
}
bool
WriteBlobOrFile(JSContext* aCx,
JSStructuredCloneWriter* aWriter,
BlobImpl* aBlobOrBlobImpl,
WriteBlobOrFile(JSStructuredCloneWriter* aWriter,
BlobImpl* aBlobImpl,
WorkerStructuredCloneClosure& aClosure)
{
MOZ_ASSERT(aCx);
MOZ_ASSERT(aWriter);
MOZ_ASSERT(aBlobOrBlobImpl);
MOZ_ASSERT(aBlobImpl);
nsRefPtr<BlobImpl> blobImpl = EnsureBlobForBackgroundManager(aBlobOrBlobImpl);
MOZ_ASSERT(blobImpl);
aBlobOrBlobImpl = blobImpl;
if (NS_WARN_IF(!JS_WriteUint32Pair(aWriter, DOMWORKER_SCTAG_BLOB, 0)) ||
NS_WARN_IF(!JS_WriteBytes(aWriter,
&aBlobOrBlobImpl,
sizeof(aBlobOrBlobImpl)))) {
if (!aBlobImpl->MayBeClonedToOtherThreads()) {
NS_WARNING("Not all the blob implementations can be sent between threads.");
return false;
}
aClosure.mClonedObjects.AppendElement(aBlobOrBlobImpl);
nsRefPtr<BlobImpl> blobImpl = EnsureBlobForBackgroundManager(aBlobImpl);
MOZ_ASSERT(blobImpl);
aBlobImpl = blobImpl;
if (NS_WARN_IF(!JS_WriteUint32Pair(aWriter, DOMWORKER_SCTAG_BLOB, 0)) ||
NS_WARN_IF(!JS_WriteBytes(aWriter, &aBlobImpl, sizeof(aBlobImpl)))) {
return false;
}
aClosure.mClonedObjects.AppendElement(aBlobImpl);
return true;
}
@@ -565,7 +559,8 @@ WriteFormData(JSContext* aCx,
return false;
}
class MOZ_STACK_CLASS Closure {
class MOZ_STACK_CLASS Closure final
{
JSContext* mCx;
JSStructuredCloneWriter* mWriter;
WorkerStructuredCloneClosure& mClones;
@@ -590,7 +585,8 @@ WriteFormData(JSContext* aCx,
}
if (isFile) {
if (!WriteBlobOrFile(closure->mCx, closure->mWriter, aFile->Impl(), closure->mClones)) {
if (!WriteBlobOrFile(closure->mWriter, aFile->Impl(),
closure->mClones)) {
return false;
}
} else {
@@ -613,27 +609,27 @@ struct WorkerStructuredCloneCallbacks
Read(JSContext* aCx, JSStructuredCloneReader* aReader, uint32_t aTag,
uint32_t aData, void* aClosure)
{
JS::Rooted<JSObject*> result(aCx);
// See if object is a nsIDOMBlob pointer.
if (aTag == DOMWORKER_SCTAG_BLOB) {
MOZ_ASSERT(!aData);
JS::Rooted<JSObject*> blobOrFile(aCx);
ReadBlobOrFile(aCx, aReader, /* aIsMainThread */ false, &blobOrFile);
ReadBlobOrFile(aCx, aReader, &blobOrFile);
return blobOrFile;
}
// See if the object is an ImageData.
else if (aTag == SCTAG_DOM_IMAGEDATA) {
if (aTag == SCTAG_DOM_IMAGEDATA) {
MOZ_ASSERT(!aData);
return ReadStructuredCloneImageData(aCx, aReader);
}
// See if the object is a FormData.
else if (aTag == DOMWORKER_SCTAG_FORMDATA) {
if (aTag == DOMWORKER_SCTAG_FORMDATA) {
JS::Rooted<JSObject*> formData(aCx);
// aData is the entry count.
ReadFormData(aCx, aReader, /* aIsMainThread */ false, aData, &formData);
ReadFormData(aCx, aReader, aData, &formData);
return formData;
}
@@ -649,8 +645,7 @@ struct WorkerStructuredCloneCallbacks
closure->mClonedImages, aData);
}
Error(aCx, 0);
return nullptr;
return NS_DOMReadStructuredClone(aCx, aReader, aTag, aData, nullptr);
}
static bool
@@ -668,7 +663,7 @@ struct WorkerStructuredCloneCallbacks
BlobImpl* blobImpl = blob->Impl();
MOZ_ASSERT(blobImpl);
if (WriteBlobOrFile(aCx, aWriter, blobImpl, *closure)) {
if (WriteBlobOrFile(aWriter, blobImpl, *closure)) {
return true;
}
}
@@ -702,8 +697,7 @@ struct WorkerStructuredCloneCallbacks
}
}
Error(aCx, 0);
return false;
return NS_DOMWriteStructuredClone(aCx, aWriter, aObj, nullptr);
}
static void
@@ -810,198 +804,6 @@ const JSStructuredCloneCallbacks gWorkerStructuredCloneCallbacks = {
WorkerStructuredCloneCallbacks::FreeTransfer
};
struct MainThreadWorkerStructuredCloneCallbacks
{
static JSObject*
Read(JSContext* aCx, JSStructuredCloneReader* aReader, uint32_t aTag,
uint32_t aData, void* aClosure)
{
AssertIsOnMainThread();
// See if object is a Blob/File pointer.
if (aTag == DOMWORKER_SCTAG_BLOB) {
MOZ_ASSERT(!aData);
JS::Rooted<JSObject*> blobOrFile(aCx);
ReadBlobOrFile(aCx, aReader, /* aIsMainThread */ true, &blobOrFile);
return blobOrFile;
}
// See if the object is a FormData.
else if (aTag == DOMWORKER_SCTAG_FORMDATA) {
JS::Rooted<JSObject*> formData(aCx);
// aData is the entry count.
ReadFormData(aCx, aReader, /* aIsMainThread */ true, aData, &formData);
return formData;
}
// See if the object is a ImageBitmap
if (aTag == SCTAG_DOM_IMAGEBITMAP) {
NS_ASSERTION(aClosure, "Null pointer!");
// Get the current global object.
auto* closure = static_cast<WorkerStructuredCloneClosure*>(aClosure);
nsCOMPtr<nsIGlobalObject> parent = do_QueryInterface(closure->mParentWindow);
// aData is the index of the cloned image.
return ImageBitmap::ReadStructuredClone(aCx, aReader, parent,
closure->mClonedImages, aData);
}
JS_ClearPendingException(aCx);
return NS_DOMReadStructuredClone(aCx, aReader, aTag, aData, nullptr);
}
static bool
Write(JSContext* aCx, JSStructuredCloneWriter* aWriter,
JS::Handle<JSObject*> aObj, void* aClosure)
{
AssertIsOnMainThread();
NS_ASSERTION(aClosure, "Null pointer!");
auto* closure = static_cast<WorkerStructuredCloneClosure*>(aClosure);
// See if this is a Blob/File object.
{
nsRefPtr<Blob> blob;
if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob, aObj, blob))) {
BlobImpl* blobImpl = blob->Impl();
MOZ_ASSERT(blobImpl);
if (!blobImpl->MayBeClonedToOtherThreads()) {
NS_WARNING("Not all the blob implementations can be sent between threads.");
} else if (WriteBlobOrFile(aCx, aWriter, blobImpl, *closure)) {
return true;
}
}
}
// Handle imageBitmap cloning
{
ImageBitmap* imageBitmap = nullptr;
if (NS_SUCCEEDED(UNWRAP_OBJECT(ImageBitmap, aObj, imageBitmap))) {
return ImageBitmap::WriteStructuredClone(aWriter,
closure->mClonedImages,
imageBitmap);
}
}
JS_ClearPendingException(aCx);
return NS_DOMWriteStructuredClone(aCx, aWriter, aObj, nullptr);
}
static void
Error(JSContext* aCx, uint32_t aErrorId)
{
AssertIsOnMainThread();
NS_DOMStructuredCloneError(aCx, aErrorId);
}
};
const JSStructuredCloneCallbacks gMainThreadWorkerStructuredCloneCallbacks = {
MainThreadWorkerStructuredCloneCallbacks::Read,
MainThreadWorkerStructuredCloneCallbacks::Write,
MainThreadWorkerStructuredCloneCallbacks::Error,
WorkerStructuredCloneCallbacks::ReadTransfer,
WorkerStructuredCloneCallbacks::Transfer,
WorkerStructuredCloneCallbacks::FreeTransfer
};
struct ChromeWorkerStructuredCloneCallbacks
{
static JSObject*
Read(JSContext* aCx, JSStructuredCloneReader* aReader, uint32_t aTag,
uint32_t aData, void* aClosure)
{
return WorkerStructuredCloneCallbacks::Read(aCx, aReader, aTag, aData,
aClosure);
}
static bool
Write(JSContext* aCx, JSStructuredCloneWriter* aWriter,
JS::Handle<JSObject*> aObj, void* aClosure)
{
return WorkerStructuredCloneCallbacks::Write(aCx, aWriter, aObj, aClosure);
}
static void
Error(JSContext* aCx, uint32_t aErrorId)
{
return WorkerStructuredCloneCallbacks::Error(aCx, aErrorId);
}
};
const JSStructuredCloneCallbacks gChromeWorkerStructuredCloneCallbacks = {
ChromeWorkerStructuredCloneCallbacks::Read,
ChromeWorkerStructuredCloneCallbacks::Write,
ChromeWorkerStructuredCloneCallbacks::Error,
WorkerStructuredCloneCallbacks::ReadTransfer,
WorkerStructuredCloneCallbacks::Transfer,
WorkerStructuredCloneCallbacks::FreeTransfer
};
struct MainThreadChromeWorkerStructuredCloneCallbacks
{
static JSObject*
Read(JSContext* aCx, JSStructuredCloneReader* aReader, uint32_t aTag,
uint32_t aData, void* aClosure)
{
AssertIsOnMainThread();
JSObject* clone =
MainThreadWorkerStructuredCloneCallbacks::Read(aCx, aReader, aTag, aData,
aClosure);
if (clone) {
return clone;
}
clone =
ChromeWorkerStructuredCloneCallbacks::Read(aCx, aReader, aTag, aData,
aClosure);
if (clone) {
return clone;
}
JS_ClearPendingException(aCx);
return NS_DOMReadStructuredClone(aCx, aReader, aTag, aData, nullptr);
}
static bool
Write(JSContext* aCx, JSStructuredCloneWriter* aWriter,
JS::Handle<JSObject*> aObj, void* aClosure)
{
AssertIsOnMainThread();
if (MainThreadWorkerStructuredCloneCallbacks::Write(aCx, aWriter, aObj,
aClosure) ||
ChromeWorkerStructuredCloneCallbacks::Write(aCx, aWriter, aObj,
aClosure) ||
NS_DOMWriteStructuredClone(aCx, aWriter, aObj, nullptr)) {
return true;
}
return false;
}
static void
Error(JSContext* aCx, uint32_t aErrorId)
{
AssertIsOnMainThread();
NS_DOMStructuredCloneError(aCx, aErrorId);
}
};
const JSStructuredCloneCallbacks gMainThreadChromeWorkerStructuredCloneCallbacks = {
MainThreadChromeWorkerStructuredCloneCallbacks::Read,
MainThreadChromeWorkerStructuredCloneCallbacks::Write,
MainThreadChromeWorkerStructuredCloneCallbacks::Error,
nullptr,
nullptr,
nullptr
};
class MainThreadReleaseRunnable final : public nsRunnable
{
nsTArray<nsCOMPtr<nsISupports>> mDoomed;
@@ -1346,7 +1148,7 @@ public:
JS::Rooted<JS::Value> messageData(aCx);
if (!mBuffer.read(aCx, &messageData,
workers::WorkerStructuredCloneCallbacks(aIsMainThread),
workers::WorkerStructuredCloneCallbacks(),
&closure)) {
xpc::Throw(aCx, NS_ERROR_DOM_DATA_CLONE_ERR);
return false;
@@ -1356,7 +1158,7 @@ public:
nsresult rv =
event->InitMessageEvent(NS_LITERAL_STRING("message"),
false /* non-bubbling */,
true /* cancelable */,
false /* non-cancelable */,
messageData,
EmptyString(),
EmptyString(),
@@ -3483,26 +3285,6 @@ WorkerPrivateParent<Derived>::PostMessageInternal(
}
}
const JSStructuredCloneCallbacks* callbacks;
if (GetParent()) {
if (IsChromeWorker()) {
callbacks = &gChromeWorkerStructuredCloneCallbacks;
}
else {
callbacks = &gWorkerStructuredCloneCallbacks;
}
}
else {
AssertIsOnMainThread();
if (IsChromeWorker()) {
callbacks = &gMainThreadChromeWorkerStructuredCloneCallbacks;
}
else {
callbacks = &gMainThreadWorkerStructuredCloneCallbacks;
}
}
JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
if (aTransferable.WasPassed()) {
const Sequence<JS::Value>& realTransferable = aTransferable.Value();
@@ -3527,7 +3309,8 @@ WorkerPrivateParent<Derived>::PostMessageInternal(
WorkerRunnable::WorkerThreadModifyBusyCount,
aToMessagePort, aMessagePortSerial);
if (!runnable->Write(aCx, aMessage, transferable, callbacks)) {
if (!runnable->Write(aCx, aMessage, transferable,
&gWorkerStructuredCloneCallbacks)) {
aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
return;
}
@@ -3577,8 +3360,6 @@ WorkerPrivateParent<Derived>::DispatchMessageEventToMessagePort(
AssertIsOnMainThread();
JSAutoStructuredCloneBuffer buffer(Move(aBuffer));
const JSStructuredCloneCallbacks* callbacks =
WorkerStructuredCloneCallbacks(true);
class MOZ_STACK_CLASS AutoCloneBufferCleaner final
{
@@ -3608,7 +3389,9 @@ WorkerPrivateParent<Derived>::DispatchMessageEventToMessagePort(
MOZ_ASSERT(aClosure.mMessagePorts.IsEmpty());
closure.mMessagePortIdentifiers.SwapElements(aClosure.mMessagePortIdentifiers);
AutoCloneBufferCleaner bufferCleaner(buffer, callbacks, closure);
AutoCloneBufferCleaner bufferCleaner(buffer,
&gWorkerStructuredCloneCallbacks,
closure);
SharedWorker* sharedWorker;
if (!mSharedWorkers.Get(aMessagePortSerial, &sharedWorker)) {
@@ -3632,7 +3415,7 @@ WorkerPrivateParent<Derived>::DispatchMessageEventToMessagePort(
JSContext* cx = jsapi.cx();
JS::Rooted<JS::Value> data(cx);
if (!buffer.read(cx, &data, WorkerStructuredCloneCallbacks(true),
if (!buffer.read(cx, &data, &gWorkerStructuredCloneCallbacks,
&closure)) {
return false;
}
@@ -6292,17 +6075,13 @@ WorkerPrivate::PostMessageToParentInternal(
transferable.setObject(*array);
}
const JSStructuredCloneCallbacks* callbacks =
IsChromeWorker() ?
&gChromeWorkerStructuredCloneCallbacks :
&gWorkerStructuredCloneCallbacks;
nsRefPtr<MessageEventRunnable> runnable =
new MessageEventRunnable(this,
WorkerRunnable::ParentThreadUnchangedBusyCount,
aToMessagePort, aMessagePortSerial);
if (!runnable->Write(aCx, aMessage, transferable, callbacks)) {
if (!runnable->Write(aCx, aMessage, transferable,
&gWorkerStructuredCloneCallbacks)) {
aRv = NS_ERROR_DOM_DATA_CLONE_ERR;
return;
}
@@ -7445,19 +7224,9 @@ GetWorkerCrossThreadDispatcher(JSContext* aCx, JS::Value aWorker)
}
const JSStructuredCloneCallbacks*
WorkerStructuredCloneCallbacks(bool aMainRuntime)
WorkerStructuredCloneCallbacks()
{
return aMainRuntime ?
&gMainThreadWorkerStructuredCloneCallbacks :
&gWorkerStructuredCloneCallbacks;
}
const JSStructuredCloneCallbacks*
ChromeWorkerStructuredCloneCallbacks(bool aMainRuntime)
{
return aMainRuntime ?
&gMainThreadChromeWorkerStructuredCloneCallbacks :
&gChromeWorkerStructuredCloneCallbacks;
return &gWorkerStructuredCloneCallbacks;
}
// Force instantiation.
+1 -4
View File
@@ -1520,10 +1520,7 @@ enum WorkerStructuredDataType
};
const JSStructuredCloneCallbacks*
WorkerStructuredCloneCallbacks(bool aMainRuntime);
const JSStructuredCloneCallbacks*
ChromeWorkerStructuredCloneCallbacks(bool aMainRuntime);
WorkerStructuredCloneCallbacks();
class AutoSyncLoopHolder
{
+6 -18
View File
@@ -1229,9 +1229,7 @@ EventRunnable::PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
if (doClone) {
// Anything subject to GC must be cloned.
const JSStructuredCloneCallbacks* callbacks =
aWorkerPrivate->IsChromeWorker() ?
workers::ChromeWorkerStructuredCloneCallbacks(true) :
workers::WorkerStructuredCloneCallbacks(true);
workers::WorkerStructuredCloneCallbacks();
WorkerStructuredCloneClosure closure;
@@ -1344,9 +1342,7 @@ EventRunnable::WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
JSAutoStructuredCloneBuffer responseBuffer(Move(mResponseBuffer));
const JSStructuredCloneCallbacks* callbacks =
aWorkerPrivate->IsChromeWorker() ?
workers::ChromeWorkerStructuredCloneCallbacks(false) :
workers::WorkerStructuredCloneCallbacks(false);
workers::WorkerStructuredCloneCallbacks();
WorkerStructuredCloneClosure closure;
closure.mClonedObjects.SwapElements(mResponseClosure.mClonedObjects);
@@ -1531,9 +1527,7 @@ SendRunnable::MainThreadRun()
nsresult rv = NS_OK;
const JSStructuredCloneCallbacks* callbacks =
mWorkerPrivate->IsChromeWorker() ?
workers::ChromeWorkerStructuredCloneCallbacks(true) :
workers::WorkerStructuredCloneCallbacks(true);
workers::WorkerStructuredCloneCallbacks();
JS::Rooted<JS::Value> body(cx);
if (mBody.read(cx, &body, callbacks, &mClosure)) {
@@ -2178,9 +2172,7 @@ XMLHttpRequest::Send(JS::Handle<JSObject*> aBody, ErrorResult& aRv)
}
const JSStructuredCloneCallbacks* callbacks =
mWorkerPrivate->IsChromeWorker() ?
ChromeWorkerStructuredCloneCallbacks(false) :
WorkerStructuredCloneCallbacks(false);
WorkerStructuredCloneCallbacks();
WorkerStructuredCloneClosure closure;
@@ -2224,9 +2216,7 @@ XMLHttpRequest::Send(Blob& aBody, ErrorResult& aRv)
}
const JSStructuredCloneCallbacks* callbacks =
mWorkerPrivate->IsChromeWorker() ?
ChromeWorkerStructuredCloneCallbacks(false) :
WorkerStructuredCloneCallbacks(false);
WorkerStructuredCloneCallbacks();
WorkerStructuredCloneClosure closure;
@@ -2262,9 +2252,7 @@ XMLHttpRequest::Send(nsFormData& aBody, ErrorResult& aRv)
}
const JSStructuredCloneCallbacks* callbacks =
mWorkerPrivate->IsChromeWorker() ?
ChromeWorkerStructuredCloneCallbacks(false) :
WorkerStructuredCloneCallbacks(false);
WorkerStructuredCloneCallbacks();
JSAutoStructuredCloneBuffer buffer;
WorkerStructuredCloneClosure closure;
+46 -40
View File
@@ -117,7 +117,7 @@ GetXrayType(JSObject* obj)
}
JSObject*
XrayAwareCalleeGlobal(JSObject *fun)
XrayAwareCalleeGlobal(JSObject* fun)
{
MOZ_ASSERT(js::IsFunctionObject(fun));
@@ -127,17 +127,17 @@ XrayAwareCalleeGlobal(JSObject *fun)
}
// The functions we expect here have the Xray wrapper they're associated with
// in their XRAY_DOM_FUNCTION_PARENT_WRAPPER_SLOT and, in a debug build, their
// JSNative in their XRAY_DOM_FUNCTION_NATIVE_SLOT_FOR_ASSERT. Assert that
// in their XRAY_DOM_FUNCTION_PARENT_WRAPPER_SLOT and, in a debug build,
// themselves in their XRAY_DOM_FUNCTION_NATIVE_SLOT_FOR_SELF. Assert that
// last bit.
MOZ_ASSERT(js::GetFunctionNativeReserved(fun, XRAY_DOM_FUNCTION_NATIVE_SLOT_FOR_ASSERT).toPrivate() ==
js::GetFunctionObjectNative(fun));
MOZ_ASSERT(&js::GetFunctionNativeReserved(fun, XRAY_DOM_FUNCTION_NATIVE_SLOT_FOR_SELF).toObject() ==
fun);
Value v =
js::GetFunctionNativeReserved(fun, XRAY_DOM_FUNCTION_PARENT_WRAPPER_SLOT);
MOZ_ASSERT(IsXrayWrapper(&v.toObject()));
JSObject *xrayTarget = js::UncheckedUnwrap(&v.toObject());
JSObject* xrayTarget = js::UncheckedUnwrap(&v.toObject());
return js::GetGlobalForObjectCrossCompartment(xrayTarget);
}
@@ -269,6 +269,21 @@ ReportWrapperDenial(JSContext* cx, HandleId id, WrapperDenialType type, const ch
return true;
}
bool JSXrayTraits::getOwnPropertyFromWrapperIfSafe(JSContext* cx,
HandleObject wrapper,
HandleId id,
MutableHandle<JSPropertyDescriptor> outDesc)
{
MOZ_ASSERT(js::IsObjectInContextCompartment(wrapper, cx));
RootedObject target(cx, getTargetObject(wrapper));
{
JSAutoCompartment ac(cx, target);
if (!getOwnPropertyFromTargetIfSafe(cx, target, wrapper, id, outDesc))
return false;
}
return JS_WrapPropertyDescriptor(cx, outDesc);
}
bool JSXrayTraits::getOwnPropertyFromTargetIfSafe(JSContext* cx,
HandleObject target,
HandleObject wrapper,
@@ -382,12 +397,7 @@ JSXrayTraits::resolveOwnProperty(JSContext* cx, const Wrapper& jsWrapper,
// "should" look like over Xrays, the underlying object is squishy enough
// that it makes sense to just treat them like Objects for Xray purposes.
if (key == JSProto_Object || key == JSProto_Array) {
{
JSAutoCompartment ac(cx, target);
if (!getOwnPropertyFromTargetIfSafe(cx, target, wrapper, id, desc))
return false;
}
return JS_WrapPropertyDescriptor(cx, desc);
return getOwnPropertyFromWrapperIfSafe(cx, wrapper, id, desc);
} else if (IsTypedArrayKey(key)) {
if (IsArrayIndex(GetArrayIndexFromId(cx, id))) {
JS_ReportError(cx, "Accessing TypedArray data over Xrays is slow, and forbidden "
@@ -450,10 +460,8 @@ JSXrayTraits::resolveOwnProperty(JSContext* cx, const Wrapper& jsWrapper,
return true;
}
} else if (key == JSProto_RegExp) {
if (id == GetRTIdByIndex(cx, XPCJSRuntime::IDX_LASTINDEX)) {
JSAutoCompartment ac(cx, target);
return getOwnPropertyFromTargetIfSafe(cx, target, wrapper, id, desc);
}
if (id == GetRTIdByIndex(cx, XPCJSRuntime::IDX_LASTINDEX))
return getOwnPropertyFromWrapperIfSafe(cx, wrapper, id, desc);
}
// The rest of this function applies only to prototypes.
@@ -499,10 +507,8 @@ JSXrayTraits::resolveOwnProperty(JSContext* cx, const Wrapper& jsWrapper,
}
// Handle the 'lastIndex' property for RegExp prototypes.
if (key == JSProto_RegExp && id == GetRTIdByIndex(cx, XPCJSRuntime::IDX_LASTINDEX)) {
JSAutoCompartment ac(cx, target);
return getOwnPropertyFromTargetIfSafe(cx, target, wrapper, id, desc);
}
if (key == JSProto_RegExp && id == GetRTIdByIndex(cx, XPCJSRuntime::IDX_LASTINDEX))
return getOwnPropertyFromWrapperIfSafe(cx, wrapper, id, desc);
// Grab the JSClass. We require all Xrayable classes to have a ClassSpec.
const js::Class* clasp = js::GetObjectClass(target);
@@ -588,7 +594,7 @@ JSXrayTraits::resolveOwnProperty(JSContext* cx, const Wrapper& jsWrapper,
}
bool
JSXrayTraits::delete_(JSContext *cx, HandleObject wrapper, HandleId id, ObjectOpResult &result)
JSXrayTraits::delete_(JSContext* cx, HandleObject wrapper, HandleId id, ObjectOpResult& result)
{
RootedObject holder(cx, ensureHolder(cx, wrapper));
@@ -611,11 +617,11 @@ JSXrayTraits::delete_(JSContext *cx, HandleObject wrapper, HandleId id, ObjectOp
}
bool
JSXrayTraits::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
JSXrayTraits::defineProperty(JSContext* cx, HandleObject wrapper, HandleId id,
Handle<JSPropertyDescriptor> desc,
Handle<JSPropertyDescriptor> existingDesc,
ObjectOpResult &result,
bool *defined)
ObjectOpResult& result,
bool* defined)
{
*defined = false;
RootedObject holder(cx, ensureHolder(cx, wrapper));
@@ -1063,7 +1069,7 @@ XrayTraits::cloneExpandoChain(JSContext* cx, HandleObject dst, HandleObject src)
// preserved when expandos were originally added to |src|. Assert the
// wrapper for |src| has been preserved if it has expandos set.
if (oldHead) {
nsISupports *identity = mozilla::dom::UnwrapDOMObjectToISupports(src);
nsISupports* identity = mozilla::dom::UnwrapDOMObjectToISupports(src);
if (identity) {
nsWrapperCache* cache = nullptr;
CallQueryInterface(identity, &cache);
@@ -1244,7 +1250,7 @@ XPCWrappedNativeXrayTraits::resolveNativeProperty(JSContext* cx, HandleObject wr
if (id != nsXPConnect::GetRuntimeInstance()->GetStringID(XPCJSRuntime::IDX_TO_STRING))
return true;
JSFunction *toString = JS_NewFunction(cx, XrayToString, 0, 0, "toString");
JSFunction* toString = JS_NewFunction(cx, XrayToString, 0, 0, "toString");
if (!toString)
return false;
@@ -1442,10 +1448,10 @@ XPCWrappedNativeXrayTraits::resolveOwnProperty(JSContext* cx, const Wrapper& jsW
}
bool
XPCWrappedNativeXrayTraits::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
XPCWrappedNativeXrayTraits::defineProperty(JSContext* cx, HandleObject wrapper, HandleId id,
Handle<JSPropertyDescriptor> desc,
Handle<JSPropertyDescriptor> existingDesc,
JS::ObjectOpResult &result, bool *defined)
JS::ObjectOpResult& result, bool* defined)
{
*defined = false;
RootedObject holder(cx, singleton.ensureHolder(cx, wrapper));
@@ -1602,10 +1608,10 @@ DOMXrayTraits::resolveOwnProperty(JSContext* cx, const Wrapper& jsWrapper, Handl
}
bool
DOMXrayTraits::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
DOMXrayTraits::defineProperty(JSContext* cx, HandleObject wrapper, HandleId id,
Handle<JSPropertyDescriptor> desc,
Handle<JSPropertyDescriptor> existingDesc,
JS::ObjectOpResult &result, bool *defined)
JS::ObjectOpResult& result, bool* defined)
{
// Check for an indexed property on a Window. If that's happening, do
// nothing but claim we defined it so it won't get added as an expando.
@@ -1685,7 +1691,7 @@ DOMXrayTraits::construct(JSContext* cx, HandleObject wrapper,
}
bool
DOMXrayTraits::getPrototype(JSContext *cx, JS::HandleObject wrapper,
DOMXrayTraits::getPrototype(JSContext* cx, JS::HandleObject wrapper,
JS::HandleObject target,
JS::MutableHandleObject protop)
{
@@ -1816,8 +1822,8 @@ XrayToString(JSContext* cx, unsigned argc, Value* vp)
template <typename Base, typename Traits>
bool
XrayWrapper<Base, Traits>::preventExtensions(JSContext *cx, HandleObject wrapper,
ObjectOpResult &result) const
XrayWrapper<Base, Traits>::preventExtensions(JSContext* cx, HandleObject wrapper,
ObjectOpResult& result) const
{
// Xray wrappers are supposed to provide a clean view of the target
// reflector, hiding any modifications by script in the target scope. So
@@ -1957,7 +1963,7 @@ XrayWrapper<Base, Traits>::getOwnPropertyDescriptor(JSContext* cx, HandleObject
// to the content object. This is ok, because the the expando object is only
// ever accessed by code across the compartment boundary.
static bool
RecreateLostWaivers(JSContext *cx, const JSPropertyDescriptor *orig,
RecreateLostWaivers(JSContext* cx, const JSPropertyDescriptor* orig,
MutableHandle<JSPropertyDescriptor> wrapped)
{
// Compute whether the original objects were waived, and implicitly, whether
@@ -2001,9 +2007,9 @@ RecreateLostWaivers(JSContext *cx, const JSPropertyDescriptor *orig,
template <typename Base, typename Traits>
bool
XrayWrapper<Base, Traits>::defineProperty(JSContext *cx, HandleObject wrapper,
XrayWrapper<Base, Traits>::defineProperty(JSContext* cx, HandleObject wrapper,
HandleId id, Handle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const
ObjectOpResult& result) const
{
assertEnteredPolicy(cx, wrapper, id, BaseProxyHandler::SET);
@@ -2075,7 +2081,7 @@ XrayWrapper<Base, Traits>::ownPropertyKeys(JSContext* cx, HandleObject wrapper,
template <typename Base, typename Traits>
bool
XrayWrapper<Base, Traits>::delete_(JSContext* cx, HandleObject wrapper,
HandleId id, ObjectOpResult &result) const
HandleId id, ObjectOpResult& result) const
{
assertEnteredPolicy(cx, wrapper, id, BaseProxyHandler::SET);
@@ -2200,7 +2206,7 @@ XrayWrapper<Base, Traits>::defaultValue(JSContext* cx, HandleObject wrapper,
template <typename Base, typename Traits>
bool
XrayWrapper<Base, Traits>::getPrototype(JSContext *cx, JS::HandleObject wrapper,
XrayWrapper<Base, Traits>::getPrototype(JSContext* cx, JS::HandleObject wrapper,
JS::MutableHandleObject protop) const
{
// We really only want this override for non-SecurityWrapper-inheriting
@@ -2233,8 +2239,8 @@ XrayWrapper<Base, Traits>::getPrototype(JSContext *cx, JS::HandleObject wrapper,
template <typename Base, typename Traits>
bool
XrayWrapper<Base, Traits>::setPrototype(JSContext *cx, JS::HandleObject wrapper,
JS::HandleObject proto, JS::ObjectOpResult &result) const
XrayWrapper<Base, Traits>::setPrototype(JSContext* cx, JS::HandleObject wrapper,
JS::HandleObject proto, JS::ObjectOpResult& result) const
{
// Do this only for non-SecurityWrapper-inheriting |Base|. See the comment
// in getPrototype().
+31 -24
View File
@@ -18,9 +18,9 @@
// the Xray wrapper they're associated with.
#define XRAY_DOM_FUNCTION_PARENT_WRAPPER_SLOT 0
// Slot where in debug builds Xray functions for Web IDL methods store
// a pointer to their JSNative, just so we can assert that they're the
// a pointer to their themselves, just so we can assert that they're the
// sort of functions we expect.
#define XRAY_DOM_FUNCTION_NATIVE_SLOT_FOR_ASSERT 1
#define XRAY_DOM_FUNCTION_NATIVE_SLOT_FOR_SELF 1
// Xray wrappers re-resolve the original native properties on the native
// object and always directly access to those properties.
@@ -78,8 +78,8 @@ public:
JS::HandleObject wrapper, JS::HandleObject holder,
JS::HandleId id, JS::MutableHandle<JSPropertyDescriptor> desc);
bool delete_(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id,
JS::ObjectOpResult &result) {
bool delete_(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id,
JS::ObjectOpResult& result) {
return result.succeed();
}
@@ -132,10 +132,10 @@ public:
virtual bool resolveOwnProperty(JSContext* cx, const js::Wrapper& jsWrapper, JS::HandleObject wrapper,
JS::HandleObject holder, JS::HandleId id,
JS::MutableHandle<JSPropertyDescriptor> desc) override;
bool defineProperty(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id,
bool defineProperty(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id,
JS::Handle<JSPropertyDescriptor> desc,
JS::Handle<JSPropertyDescriptor> existingDesc,
JS::ObjectOpResult &result, bool *defined);
JS::ObjectOpResult& result, bool* defined);
virtual bool enumerateNames(JSContext* cx, JS::HandleObject wrapper, unsigned flags,
JS::AutoIdVector& props);
static bool call(JSContext* cx, JS::HandleObject wrapper,
@@ -184,22 +184,22 @@ public:
virtual bool resolveOwnProperty(JSContext* cx, const js::Wrapper& jsWrapper, JS::HandleObject wrapper,
JS::HandleObject holder, JS::HandleId id,
JS::MutableHandle<JSPropertyDescriptor> desc) override;
bool defineProperty(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id,
bool defineProperty(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id,
JS::Handle<JSPropertyDescriptor> desc,
JS::Handle<JSPropertyDescriptor> existingDesc,
JS::ObjectOpResult &result, bool *defined);
JS::ObjectOpResult& result, bool* defined);
virtual bool enumerateNames(JSContext* cx, JS::HandleObject wrapper, unsigned flags,
JS::AutoIdVector& props);
static bool call(JSContext* cx, JS::HandleObject wrapper,
const JS::CallArgs& args, const js::Wrapper& baseInstance);
static bool construct(JSContext *cx, JS::HandleObject wrapper,
const JS::CallArgs &args, const js::Wrapper& baseInstance);
static bool construct(JSContext* cx, JS::HandleObject wrapper,
const JS::CallArgs& args, const js::Wrapper& baseInstance);
static bool getPrototype(JSContext *cx, JS::HandleObject wrapper,
static bool getPrototype(JSContext* cx, JS::HandleObject wrapper,
JS::HandleObject target,
JS::MutableHandleObject protop);
virtual void preserveWrapper(JSObject *target) override;
virtual void preserveWrapper(JSObject* target) override;
virtual JSObject* createHolder(JSContext* cx, JSObject* wrapper) override;
@@ -225,12 +225,12 @@ public:
JS::HandleObject holder, JS::HandleId id,
JS::MutableHandle<JSPropertyDescriptor> desc) override;
bool delete_(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id, JS::ObjectOpResult &result);
bool delete_(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id, JS::ObjectOpResult& result);
bool defineProperty(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id,
bool defineProperty(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id,
JS::Handle<JSPropertyDescriptor> desc,
JS::Handle<JSPropertyDescriptor> existingDesc,
JS::ObjectOpResult &result, bool *defined);
JS::ObjectOpResult& result, bool* defined);
virtual bool enumerateNames(JSContext* cx, JS::HandleObject wrapper, unsigned flags,
JS::AutoIdVector& props);
@@ -322,6 +322,13 @@ public:
return static_cast<JSProtoKey>(key);
}
// Operates in the wrapper compartment.
static bool getOwnPropertyFromWrapperIfSafe(JSContext* cx,
JS::HandleObject wrapper,
JS::HandleId id,
JS::MutableHandle<JSPropertyDescriptor> desc);
// Like the above, but operates in the target compartment.
static bool getOwnPropertyFromTargetIfSafe(JSContext* cx,
JS::HandleObject target,
JS::HandleObject wrapper,
@@ -350,14 +357,14 @@ public:
MOZ_CRASH("resolveNativeProperty hook should never be called with HasPrototype = 1");
}
virtual bool resolveOwnProperty(JSContext *cx, const js::Wrapper &jsWrapper, JS::HandleObject wrapper,
virtual bool resolveOwnProperty(JSContext* cx, const js::Wrapper& jsWrapper, JS::HandleObject wrapper,
JS::HandleObject holder, JS::HandleId id,
JS::MutableHandle<JSPropertyDescriptor> desc) override;
bool defineProperty(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id,
bool defineProperty(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id,
JS::Handle<JSPropertyDescriptor> desc,
JS::Handle<JSPropertyDescriptor> existingDesc,
JS::ObjectOpResult &result, bool *defined)
JS::ObjectOpResult& result, bool* defined)
{
*defined = false;
return true;
@@ -385,7 +392,7 @@ public:
return false;
}
bool getPrototype(JSContext *cx, JS::HandleObject wrapper,
bool getPrototype(JSContext* cx, JS::HandleObject wrapper,
JS::HandleObject target,
JS::MutableHandleObject protop)
{
@@ -434,7 +441,7 @@ class XrayWrapper : public Base {
virtual bool ownPropertyKeys(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::AutoIdVector& props) const override;
virtual bool delete_(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::Handle<jsid> id, JS::ObjectOpResult &result) const override;
JS::Handle<jsid> id, JS::ObjectOpResult& result) const override;
virtual bool enumerate(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::MutableHandle<JSObject*> objp) const override;
virtual bool getPrototype(JSContext* cx, JS::HandleObject wrapper,
@@ -442,9 +449,9 @@ class XrayWrapper : public Base {
virtual bool setPrototype(JSContext* cx, JS::HandleObject wrapper,
JS::HandleObject proto, JS::ObjectOpResult& result) const override;
virtual bool setImmutablePrototype(JSContext* cx, JS::HandleObject wrapper,
bool *succeeded) const override;
virtual bool preventExtensions(JSContext *cx, JS::Handle<JSObject*> wrapper,
JS::ObjectOpResult &result) const override;
bool* succeeded) const override;
virtual bool preventExtensions(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::ObjectOpResult& result) const override;
virtual bool isExtensible(JSContext* cx, JS::Handle<JSObject*> wrapper, bool* extensible) const override;
virtual bool has(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
bool* bp) const override;
@@ -526,7 +533,7 @@ public:
JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp) const override;
virtual bool set(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
JS::Handle<JS::Value> v, JS::Handle<JS::Value> receiver,
JS::ObjectOpResult &result) const override;
JS::ObjectOpResult& result) const override;
virtual bool getPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy,
JS::Handle<jsid> id,
@@ -1,6 +1,5 @@
[lock-bad-argument.html]
type: testharness
expected: ERROR
[Test that screen.orientation.lock() throws when the input isn't valid.]
expected: NOTRUN
expected: FAIL
@@ -1,8 +1,6 @@
[lock-basic.html]
type: testharness
[Test that screen.orientation.unlock() doesn't throw when there is no lock]
expected: FAIL
expected: TIMEOUT
[Test that screen.orientation.lock returns a pending promise.]
expected: FAIL
expected: TIMEOUT
@@ -2,7 +2,7 @@
type: testharness
expected: TIMEOUT
[Test without 'allow-orientation-lock' sandboxing directive]
expected: NOTRUN
expected: FAIL
[Test with 'allow-orientation-lock' sandboxing directive]
expected: NOTRUN
@@ -1,6 +1,6 @@
[onchange-event-subframe.html]
type: testharness
expected: ERROR
expected: TIMEOUT
[Test subframes receive orientation change events]
expected: NOTRUN
@@ -1,6 +1,6 @@
[onchange-event.html]
type: testharness
expected: ERROR
expected: TIMEOUT
[Test that orientationchange event is fired when the orientation changes.]
expected: NOTRUN
@@ -1,11 +0,0 @@
[orientation-api.html]
type: testharness
[Test that the Screen Orientation API is present.]
expected: FAIL
[Test Screen Orientation API property types.]
expected: FAIL
[Test that screen.orientation is an EventTarget.]
expected: FAIL
@@ -1,14 +1,8 @@
[orientation-reading.html]
type: testharness
[Test screen.orientation properties]
expected: FAIL
[Test screen.orientation default values.]
expected: FAIL
[Test that screen.orientation properties are not writable]
expected: FAIL
[Test that screen.orientation values change if the orientation changes]
expected: FAIL
@@ -1,5 +0,0 @@
[message-event.html]
type: testharness
[Properties of the 'message' event]
expected: FAIL