Bug 1285069 part 2 - Remove nsPointerLockPermissionRequest, only keep the Allow method under a different name. r?smaug
We still want to keep ApplyPointerLock asynchronous so that the timing
when pointer lock takes effect is not changed by this patch.
MozReview-Commit-ID: EA8c6uzOd8F
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -218,17 +218,16 @@
#include "mozilla/OwningNonNull.h"
#include "mozilla/dom/TabChild.h"
#include "mozilla/dom/UndoManager.h"
#include "mozilla/dom/WebComponentsBinding.h"
#include "nsFrame.h"
#include "nsDOMCaretPosition.h"
#include "nsIDOMHTMLTextAreaElement.h"
#include "nsViewportInfo.h"
-#include "nsIContentPermissionPrompt.h"
#include "mozilla/StaticPtr.h"
#include "nsITextControlElement.h"
#include "nsIDOMNSEditableElement.h"
#include "nsIEditor.h"
#include "nsIDOMCSSStyleRule.h"
#include "mozilla/css/Rule.h"
#include "nsIDOMLocation.h"
#include "nsIHttpChannelInternal.h"
@@ -236,17 +235,16 @@
#include "nsCharSeparatedTokenizer.h"
#include "mozilla/dom/XPathEvaluator.h"
#include "mozilla/dom/XPathNSResolverBinding.h"
#include "mozilla/dom/XPathResult.h"
#include "nsIDocumentEncoder.h"
#include "nsIDocumentActivity.h"
#include "nsIStructuredCloneContainer.h"
#include "nsIMutableArray.h"
-#include "nsContentPermissionHelper.h"
#include "mozilla/dom/DOMStringList.h"
#include "nsWindowMemoryReporter.h"
#include "nsLocation.h"
#include "mozilla/dom/FontFaceSet.h"
#include "mozilla/dom/BoxObject.h"
#include "gfxVR.h"
#include "gfxPrefs.h"
#include "nsISupportsPrimitives.h"
@@ -12295,206 +12293,84 @@ DispatchPointerLockError(nsIDocument* aT
RefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(aTarget,
NS_LITERAL_STRING("mozpointerlockerror"),
true,
false);
asyncDispatcher->PostDOMEvent();
}
-static const uint8_t kPointerLockRequestLimit = 2;
-
-class nsPointerLockPermissionRequest;
-mozilla::StaticRefPtr<nsPointerLockPermissionRequest> gPendingPointerLockRequest;
-
-class nsPointerLockPermissionRequest : public Runnable,
- public nsIContentPermissionRequest
+class PointerLockRequest final : public Runnable
{
public:
- nsPointerLockPermissionRequest(Element* aElement, bool aUserInputOrChromeCaller)
- : mElement(do_GetWeakReference(aElement)),
- mDocument(do_GetWeakReference(aElement->OwnerDoc())),
- mUserInputOrChromeCaller(aUserInputOrChromeCaller)
- {
- nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
- if (doc && doc->GetInnerWindow()) {
- mRequester = new nsContentPermissionRequester(doc->GetInnerWindow());
- }
- }
-
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_NSICONTENTPERMISSIONREQUEST
-
- NS_IMETHOD Run() override
- {
- nsCOMPtr<Element> e = do_QueryReferent(mElement);
- nsCOMPtr<nsIDocument> d = do_QueryReferent(mDocument);
- if (!e || !d || gPendingPointerLockRequest != this ||
- e->GetUncomposedDoc() != d) {
- Handled();
- DispatchPointerLockError(d);
- return NS_OK;
- }
-
- nsDocument* doc = static_cast<nsDocument*>(d.get());
- if (doc->GetFullscreenElement() || doc->mAllowRelocking) {
- Allow(JS::UndefinedHandleValue);
- return NS_OK;
- }
-
- // In non-fullscreen mode user input (or chrome caller) is required!
- // Also, don't let the page to try to get the permission too many times.
- if (!mUserInputOrChromeCaller ||
- doc->mCancelledPointerLockRequests > kPointerLockRequestLimit) {
- Handled();
- DispatchPointerLockError(d);
- return NS_OK;
- }
-
- Allow(JS::UndefinedHandleValue);
- return NS_OK;
- }
-
- void Handled()
- {
- mElement = nullptr;
- mDocument = nullptr;
- if (gPendingPointerLockRequest == this) {
- gPendingPointerLockRequest = nullptr;
- }
- }
-
+ PointerLockRequest(Element* aElement, bool aUserInputOrChromeCaller)
+ : mElement(do_GetWeakReference(aElement))
+ , mDocument(do_GetWeakReference(aElement->OwnerDoc()))
+ , mUserInputOrChromeCaller(aUserInputOrChromeCaller)
+ {}
+
+ NS_IMETHOD Run() final;
+
+private:
nsWeakPtr mElement;
nsWeakPtr mDocument;
bool mUserInputOrChromeCaller;
-
-protected:
- virtual ~nsPointerLockPermissionRequest() {}
- nsCOMPtr<nsIContentPermissionRequester> mRequester;
};
-NS_IMPL_ISUPPORTS_INHERITED(nsPointerLockPermissionRequest,
- Runnable,
- nsIContentPermissionRequest)
-
-NS_IMETHODIMP
-nsPointerLockPermissionRequest::GetTypes(nsIArray** aTypes)
-{
- nsTArray<nsString> emptyOptions;
- return nsContentPermissionUtils::CreatePermissionArray(NS_LITERAL_CSTRING("pointerLock"),
- NS_LITERAL_CSTRING("unused"),
- emptyOptions,
- aTypes);
-}
-
-NS_IMETHODIMP
-nsPointerLockPermissionRequest::GetPrincipal(nsIPrincipal** aPrincipal)
-{
- nsCOMPtr<nsIDocument> d = do_QueryReferent(mDocument);
- if (d) {
- NS_ADDREF(*aPrincipal = d->NodePrincipal());
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsPointerLockPermissionRequest::GetWindow(mozIDOMWindow** aWindow)
-{
- nsCOMPtr<nsIDocument> d = do_QueryReferent(mDocument);
- if (d) {
- NS_IF_ADDREF(*aWindow = d->GetInnerWindow());
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsPointerLockPermissionRequest::GetElement(nsIDOMElement** aElement)
-{
- // It is enough to implement GetWindow.
- *aElement = nullptr;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsPointerLockPermissionRequest::Cancel()
-{
- nsCOMPtr<nsIDocument> d = do_QueryReferent(mDocument);
- Handled();
- if (d) {
- auto doc = static_cast<nsDocument*>(d.get());
- if (doc->mCancelledPointerLockRequests <= kPointerLockRequestLimit) {
- doc->mCancelledPointerLockRequests++;
- }
- DispatchPointerLockError(d);
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsPointerLockPermissionRequest::Allow(JS::HandleValue aChoices)
-{
- MOZ_ASSERT(aChoices.isUndefined());
-
+NS_IMETHODIMP
+PointerLockRequest::Run()
+{
nsCOMPtr<Element> e = do_QueryReferent(mElement);
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
nsDocument* d = static_cast<nsDocument*>(doc.get());
- if (!e || !d || gPendingPointerLockRequest != this ||
- e->GetUncomposedDoc() != d) {
- Handled();
+ if (!e || !d || e->GetUncomposedDoc() != d) {
DispatchPointerLockError(d);
return NS_OK;
}
- // Mark handled here so that we don't need to call it everywhere below.
- Handled();
-
nsCOMPtr<Element> pointerLockedElement =
do_QueryReferent(EventStateManager::sPointerLockedElement);
if (e == pointerLockedElement) {
DispatchPointerLockChange(d);
return NS_OK;
}
// Note, we must bypass focus change, so pass true as the last parameter!
if (!d->ShouldLockPointer(e, pointerLockedElement, true)) {
DispatchPointerLockError(d);
return NS_OK;
}
+ // If it is neither user input initiated, nor requested in fullscreen,
+ // it should be rejected.
+ if (!mUserInputOrChromeCaller && !doc->GetFullscreenElement()) {
+ DispatchPointerLockError(d);
+ return NS_OK;
+ }
+
if (!d->SetPointerLock(e, NS_STYLE_CURSOR_NONE)) {
DispatchPointerLockError(d);
return NS_OK;
}
- d->mCancelledPointerLockRequests = 0;
e->SetPointerLock();
EventStateManager::sPointerLockedElement = do_GetWeakReference(e);
EventStateManager::sPointerLockedDoc = do_GetWeakReference(doc);
NS_ASSERTION(EventStateManager::sPointerLockedElement &&
EventStateManager::sPointerLockedDoc,
"aElement and this should support weak references!");
nsContentUtils::DispatchEventOnlyToChrome(
doc, ToSupports(e), NS_LITERAL_STRING("MozDOMPointerLock:Entered"),
/* Bubbles */ true, /* Cancelable */ false, /* DefaultAction */ nullptr);
DispatchPointerLockChange(d);
return NS_OK;
}
-NS_IMETHODIMP
-nsPointerLockPermissionRequest::GetRequester(nsIContentPermissionRequester** aRequester)
-{
- NS_ENSURE_ARG_POINTER(aRequester);
-
- nsCOMPtr<nsIContentPermissionRequester> requester = mRequester;
- requester.forget(aRequester);
- return NS_OK;
-}
-
nsresult
nsDocument::Observe(nsISupports *aSubject,
const char *aTopic,
const char16_t *aData)
{
if (strcmp("app-theme-changed", aTopic) == 0) {
if (!nsContentUtils::IsSystemPrincipal(NodePrincipal()) &&
!IsUnstyledDocument()) {
@@ -12578,21 +12454,18 @@ nsDocument::RequestPointerLock(Element*
if (!ShouldLockPointer(aElement, pointerLockedElement)) {
DispatchPointerLockError(this);
return;
}
bool userInputOrChromeCaller = EventStateManager::IsHandlingUserInput() ||
nsContentUtils::IsCallerChrome();
-
- gPendingPointerLockRequest =
- new nsPointerLockPermissionRequest(aElement, userInputOrChromeCaller);
- nsCOMPtr<nsIRunnable> r = gPendingPointerLockRequest.get();
- NS_DispatchToMainThread(r);
+ NS_DispatchToMainThread(new PointerLockRequest(aElement,
+ userInputOrChromeCaller));
}
bool
nsDocument::ShouldLockPointer(Element* aElement, Element* aCurrentLock,
bool aNoFocusCheck)
{
// Check if pointer lock pref is enabled
if (!Preferences::GetBool("full-screen-api.pointer-lock.enabled")) {
@@ -12714,18 +12587,16 @@ nsDocument::UnlockPointer(nsIDocument* a
nsCOMPtr<Element> pointerLockedElement =
do_QueryReferent(EventStateManager::sPointerLockedElement);
if (pointerLockedElement) {
pointerLockedElement->ClearPointerLock();
}
EventStateManager::sPointerLockedElement = nullptr;
EventStateManager::sPointerLockedDoc = nullptr;
- static_cast<nsDocument*>(pointerLockedDoc.get())->mAllowRelocking = !!aDoc;
- gPendingPointerLockRequest = nullptr;
nsContentUtils::DispatchEventOnlyToChrome(
doc, ToSupports(pointerLockedElement),
NS_LITERAL_STRING("MozDOMPointerLock:Exited"),
/* Bubbles */ true, /* Cancelable */ false, /* DefaultAction */ nullptr);
DispatchPointerLockChange(pointerLockedDoc);
}
@@ -12769,17 +12640,16 @@ nsIDocument::GetMozPointerLockElement()
}
return pointerLockedElement;
}
void
nsDocument::XPCOMShutdown()
{
- gPendingPointerLockRequest = nullptr;
sProcessingStack.reset();
}
void
nsDocument::UpdateVisibilityState()
{
dom::VisibilityState oldState = mVisibilityState;
mVisibilityState = GetVisibilityState();
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -1646,21 +1646,17 @@ public:
// Whether we're currently under a FlushPendingNotifications call to
// our presshell. This is used to handle flush reentry correctly.
bool mInFlush:1;
// Parser aborted. True if the parser of this document was forcibly
// terminated instead of letting it finish at its own pace.
bool mParserAborted:1;
- friend class nsPointerLockPermissionRequest;
friend class nsCallRequestFullScreen;
- // When set, trying to lock the pointer doesn't require permission from the
- // user.
- bool mAllowRelocking:1;
// ScreenOrientation "pending promise" as described by
// http://www.w3.org/TR/screen-orientation/
RefPtr<mozilla::dom::Promise> mOrientationPendingPromise;
uint16_t mCurrentOrientationAngle;
mozilla::dom::OrientationType mCurrentOrientationType;
@@ -1669,20 +1665,16 @@ public:
// OnPageShow notifications in a row without an OnPageHide in between, if
// we're getting document.open()/close() called on us.
bool mObservingAppThemeChanged:1;
// Keeps track of whether we have a pending
// 'style-sheet-applicable-state-changed' notification.
bool mSSApplicableStateNotificationPending:1;
- // The number of pointer lock requests which are cancelled by the user.
- // The value is saturated to kPointerLockRequestLimit+1 = 3.
- uint8_t mCancelledPointerLockRequests:2;
-
// Whether we have reported use counters for this document with Telemetry yet.
// Normally this is only done at document destruction time, but for image
// documents (SVG documents) that are not guaranteed to be destroyed, we
// report use counters when the image cache no longer has any imgRequestProxys
// pointing to them. We track whether we ever reported use counters so
// that we only report them once for the document.
bool mReportedUseCounters:1;