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

--HG--
extra : rebase_source : 1d6355b618e67ff42c65d8088d3ccb1dca339401
extra : source : 98e099aad4b57295ffdce68a0140179d50bfd044
This commit is contained in:
Xidorn Quan 2016-07-13 10:28:28 +10:00
parent efc0e7f9af
commit 4bbb9f1825
2 changed files with 19 additions and 157 deletions

View File

@ -223,7 +223,6 @@
#include "nsDOMCaretPosition.h"
#include "nsIDOMHTMLTextAreaElement.h"
#include "nsViewportInfo.h"
#include "nsIContentPermissionPrompt.h"
#include "mozilla/StaticPtr.h"
#include "nsITextControlElement.h"
#include "nsIDOMNSEditableElement.h"
@ -241,7 +240,6 @@
#include "nsIDocumentActivity.h"
#include "nsIStructuredCloneContainer.h"
#include "nsIMutableArray.h"
#include "nsContentPermissionHelper.h"
#include "mozilla/dom/DOMStringList.h"
#include "nsWindowMemoryReporter.h"
#include "nsLocation.h"
@ -12299,152 +12297,34 @@ DispatchPointerLockError(nsIDocument* aTarget)
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());
}
}
PointerLockRequest(Element* aElement, bool aUserInputOrChromeCaller)
: mElement(do_GetWeakReference(aElement))
, mDocument(do_GetWeakReference(aElement->OwnerDoc()))
, mUserInputOrChromeCaller(aUserInputOrChromeCaller)
{}
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;
}
}
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)
PointerLockRequest::Run()
{
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());
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) {
@ -12458,12 +12338,18 @@ nsPointerLockPermissionRequest::Allow(JS::HandleValue aChoices)
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);
@ -12479,16 +12365,6 @@ nsPointerLockPermissionRequest::Allow(JS::HandleValue aChoices)
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,
@ -12582,11 +12458,8 @@ nsDocument::RequestPointerLock(Element* aElement)
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
@ -12718,8 +12591,6 @@ nsDocument::UnlockPointer(nsIDocument* aDoc)
EventStateManager::sPointerLockedElement = nullptr;
EventStateManager::sPointerLockedDoc = nullptr;
static_cast<nsDocument*>(pointerLockedDoc.get())->mAllowRelocking = !!aDoc;
gPendingPointerLockRequest = nullptr;
nsContentUtils::DispatchEventOnlyToChrome(
doc, ToSupports(pointerLockedElement),
@ -12773,7 +12644,6 @@ nsIDocument::GetMozPointerLockElement()
void
nsDocument::XPCOMShutdown()
{
gPendingPointerLockRequest = nullptr;
sProcessingStack.reset();
}

View File

@ -1651,11 +1651,7 @@ public:
// 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/
@ -1674,10 +1670,6 @@ public:
// '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