gecko-dev/dom/html/AutoplayPermissionRequest.h
Chris Pearce 848dee9a6f Bug 1472580 - Ensure we always get a allow/cancel response to an autoplay media permission request. r=smaug
The front end code can't always guarantee to give us an allow/cancel response
to a permission request. In particular in these cases:
* if we close a tab while showing a doorhanger, or
* if we navigate a tab while showing a doorhanger, or
* if the permission prompt requested in a background tab and never shown.

Handling all of these cases is problematic; we don't get events for all of
these where it's easy and cheap to determine that we should cancel the
permission request.

Canceling the permission request is important in the autoplay-media permission
request case as there's objects waiting on the resolution of the permission
request, and they leak in ASan builds while running chrome tests if the Gecko
size of the permission request doesn't get a notification telling it to stop
waiting.

But we can however rely on the doorhanger code to drop its reference to the
nsIContentPermissionRequest object that we pass to it when the doorhanger goes
away. So we can cancel the permission request in our
nsIContentPermissionRequest's implementation's destructor in order to easily
catch all the above cases.

In order to do that, we need to split AutoplayRequest into two; one part being
the implementation of nsIContentPermissionRequest (AutoplayPermissionRequest),
and the other part being the code to own the PromiseHolder and manage the
permission request (AutoplayPermissionManager).

AutoplayPermissionRequest keeps a weak reference to AutoplayPermissionManager,
so that it can tell the AutoplayPermissionManager to reject the request promise
when it's destroyed.

This fixes the ASan leak for which I got backed out from earlier in this bug,
and also fixes the cases above.

MozReview-Commit-ID: KoVkgIqDleW

--HG--
rename : dom/html/AutoplayRequest.cpp => dom/html/AutoplayPermissionManager.cpp
rename : dom/html/AutoplayRequest.h => dom/html/AutoplayPermissionManager.h
extra : rebase_source : dbca520a93d8c416f6d64c2da027630181bb5910
2018-07-06 21:15:20 +12:00

58 lines
2.2 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef AutoplayPermissionRequest_h_
#define AutoplayPermissionRequest_h_
#include "nsGlobalWindowInner.h"
#include "nsISupportsImpl.h"
#include "nsContentPermissionHelper.h"
namespace mozilla {
class AutoplayPermissionManager;
// The AutoplayPermissionRequest is the object we pass off to the chrome JS
// code to represent a request for permission to autoplay. Unfortunately the
// front end code doesn't guarantee to give us an approve/cancel callback in
// all cases. If chrome JS dismisses the permission request for whatever
// reason (tab closed, user presses ESC, navigation, etc), the permission UI
// code will drop its reference to the AutoplayPermissionRequest and it will
// be destroyed. The AutoplayPermissionRequest keeps a weak reference to
// the AutoplayPermissionManager. If the AutoplayPermissionManager is still
// alive when the AutoplayPermissionRequest's destructor runs, the
// AutoplayPermissionRequest's destructor calls the AutoplayPermissionManager
// back with a cancel operation. Thus the AutoplayPermissionManager can
// guarantee to always approve or cancel requests to play.
class AutoplayPermissionRequest final : public nsIContentPermissionRequest
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSICONTENTPERMISSIONREQUEST
static already_AddRefed<AutoplayPermissionRequest> Create(
nsGlobalWindowInner* aWindow,
AutoplayPermissionManager* aManager);
private:
AutoplayPermissionRequest(AutoplayPermissionManager* aManager,
nsGlobalWindowInner* aWindow,
nsIPrincipal* aNodePrincipal,
nsIEventTarget* aMainThreadTarget);
~AutoplayPermissionRequest();
WeakPtr<AutoplayPermissionManager> mManager;
nsWeakPtr mWindow;
nsCOMPtr<nsIPrincipal> mNodePrincipal;
nsCOMPtr<nsIEventTarget> mMainThreadTarget;
nsCOMPtr<nsIContentPermissionRequester> mRequester;
};
} // namespace mozilla
#endif // AutoplayPermissionRequest_h_