Bug 1020179 - Let PContent manage PContentPermissionRequest. r=fabrice, r=khuey

--HG--
extra : rebase_source : dba5c4709942f8ad92fc6aa0ee76942247b08992
This commit is contained in:
Kershaw Chang 2015-04-13 21:08:00 -04:00
parent 2bacc33539
commit e81771306d
24 changed files with 633 additions and 88 deletions

View File

@ -2,13 +2,15 @@
* 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 <map>
#ifdef MOZ_WIDGET_GONK
#include "GonkPermission.h"
#include "mozilla/dom/ContentParent.h"
#endif // MOZ_WIDGET_GONK
#include "nsCOMPtr.h"
#include "nsIDOMElement.h"
#include "nsIPrincipal.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/PContentPermission.h"
#include "mozilla/dom/PermissionMessageUtils.h"
@ -24,11 +26,82 @@
#include "nsJSUtils.h"
#include "nsISupportsPrimitives.h"
#include "nsServiceManagerUtils.h"
#include "nsIDocument.h"
#include "nsIDOMEvent.h"
#include "nsWeakPtr.h"
using mozilla::unused; // <snicker>
using namespace mozilla::dom;
using namespace mozilla;
#define kVisibilityChange "visibilitychange"
NS_IMPL_ISUPPORTS(VisibilityChangeListener, nsIDOMEventListener)
VisibilityChangeListener::VisibilityChangeListener(nsPIDOMWindow* aWindow)
{
MOZ_ASSERT(aWindow);
mWindow = do_GetWeakReference(aWindow);
nsCOMPtr<nsIDocument> doc = aWindow->GetExtantDoc();
if (doc) {
doc->AddSystemEventListener(NS_LITERAL_STRING(kVisibilityChange),
/* listener */ this,
/* use capture */ true,
/* wants untrusted */ false);
}
}
NS_IMETHODIMP
VisibilityChangeListener::HandleEvent(nsIDOMEvent* aEvent)
{
nsAutoString type;
aEvent->GetType(type);
if (!type.EqualsLiteral(kVisibilityChange)) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDocument> doc =
do_QueryInterface(aEvent->InternalDOMEvent()->GetTarget());
MOZ_ASSERT(doc);
if (mCallback) {
mCallback->NotifyVisibility(!doc->Hidden());
}
return NS_OK;
}
void
VisibilityChangeListener::RemoveListener()
{
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
if (!window) {
return;
}
nsCOMPtr<EventTarget> target = do_QueryInterface(window->GetExtantDoc());
if (target) {
target->RemoveSystemEventListener(NS_LITERAL_STRING(kVisibilityChange),
/* listener */ this,
/* use capture */ true);
}
}
void
VisibilityChangeListener::SetCallback(nsIContentPermissionRequestCallback *aCallback)
{
mCallback = aCallback;
}
already_AddRefed<nsIContentPermissionRequestCallback>
VisibilityChangeListener::GetCallback()
{
nsCOMPtr<nsIContentPermissionRequestCallback> callback = mCallback;
return callback.forget();
}
namespace mozilla {
namespace dom {
@ -49,6 +122,7 @@ class ContentPermissionRequestParent : public PContentPermissionRequestParent
private:
virtual bool Recvprompt();
virtual bool RecvNotifyVisibility(const bool& aIsVisible);
virtual void ActorDestroy(ActorDestroyReason why);
};
@ -79,6 +153,16 @@ ContentPermissionRequestParent::Recvprompt()
return true;
}
bool
ContentPermissionRequestParent::RecvNotifyVisibility(const bool& aIsVisible)
{
if (!mProxy) {
return false;
}
mProxy->NotifyVisibility(aIsVisible);
return true;
}
void
ContentPermissionRequestParent::ActorDestroy(ActorDestroyReason why)
{
@ -90,10 +174,10 @@ ContentPermissionRequestParent::ActorDestroy(ActorDestroyReason why)
bool
ContentPermissionRequestParent::IsBeingDestroyed()
{
// When TabParent::Destroy() is called, we are being destroyed. It's unsafe
// to send out any message now.
TabParent* tabParent = TabParent::GetFrom(Manager());
return tabParent->IsDestroyed();
// When ContentParent::MarkAsDead() is called, we are being destroyed.
// It's unsafe to send out any message now.
ContentParent* contentParent = static_cast<ContentParent*>(Manager());
return !contentParent->IsAlive();
}
NS_IMPL_ISUPPORTS(ContentPermissionType, nsIContentPermissionType)
@ -205,6 +289,13 @@ nsContentPermissionUtils::ConvertArrayToPermissionRequest(nsIArray* aSrcArray,
return len;
}
static std::map<PContentPermissionRequestParent*, TabId>&
ContentPermissionRequestParentMap()
{
MOZ_ASSERT(NS_IsMainThread());
static std::map<PContentPermissionRequestParent*, TabId> sPermissionRequestParentMap;
return sPermissionRequestParentMap;
}
/* static */ nsresult
nsContentPermissionUtils::CreatePermissionArray(const nsACString& aType,
@ -225,9 +316,14 @@ nsContentPermissionUtils::CreatePermissionArray(const nsACString& aType,
/* static */ PContentPermissionRequestParent*
nsContentPermissionUtils::CreateContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequests,
Element* element,
const IPC::Principal& principal)
const IPC::Principal& principal,
const TabId& aTabId)
{
return new ContentPermissionRequestParent(aRequests, element, principal);
PContentPermissionRequestParent* parent =
new ContentPermissionRequestParent(aRequests, element, principal);
ContentPermissionRequestParentMap()[parent] = aTabId;
return parent;
}
/* static */ nsresult
@ -259,9 +355,11 @@ nsContentPermissionUtils::AskPermission(nsIContentPermissionRequest* aRequest, n
NS_ENSURE_SUCCESS(rv, rv);
req->IPDLAddRef();
child->SendPContentPermissionRequestConstructor(req,
permArray,
IPC::Principal(principal));
ContentChild::GetSingleton()->SendPContentPermissionRequestConstructor(
req,
permArray,
IPC::Principal(principal),
child->GetTabId());
req->Sendprompt();
return NS_OK;
@ -276,9 +374,139 @@ nsContentPermissionUtils::AskPermission(nsIContentPermissionRequest* aRequest, n
return NS_OK;
}
/* static */ nsTArray<PContentPermissionRequestParent*>
nsContentPermissionUtils::GetContentPermissionRequestParentById(const TabId& aTabId)
{
nsTArray<PContentPermissionRequestParent*> parentArray;
for (auto& it : ContentPermissionRequestParentMap()) {
if (it.second == aTabId) {
parentArray.AppendElement(it.first);
}
}
return Move(parentArray);
}
/* static */ void
nsContentPermissionUtils::NotifyRemoveContentPermissionRequestParent(
PContentPermissionRequestParent* aParent)
{
auto it = ContentPermissionRequestParentMap().find(aParent);
MOZ_ASSERT(it != ContentPermissionRequestParentMap().end());
ContentPermissionRequestParentMap().erase(it);
}
NS_IMPL_ISUPPORTS(nsContentPermissionRequester, nsIContentPermissionRequester)
nsContentPermissionRequester::nsContentPermissionRequester(nsPIDOMWindow* aWindow)
: mWindow(aWindow)
{
mListener = new VisibilityChangeListener(mWindow);
}
nsContentPermissionRequester::~nsContentPermissionRequester()
{
mListener->RemoveListener();
mListener = nullptr;
}
NS_IMETHODIMP
nsContentPermissionRequester::GetVisibility(nsIContentPermissionRequestCallback* aCallback)
{
NS_ENSURE_ARG_POINTER(aCallback);
if (!mWindow) {
MOZ_ASSERT(false);
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDocShell> docshell = mWindow->GetDocShell();
if (!docshell) {
return NS_ERROR_FAILURE;
}
bool isActive = false;
docshell->GetIsActive(&isActive);
aCallback->NotifyVisibility(isActive);
return NS_OK;
}
NS_IMETHODIMP
nsContentPermissionRequester::SetOnVisibilityChange(nsIContentPermissionRequestCallback* aCallback)
{
mListener->SetCallback(aCallback);
if (!aCallback) {
mListener->RemoveListener();
}
return NS_OK;
}
NS_IMETHODIMP
nsContentPermissionRequester::GetOnVisibilityChange(nsIContentPermissionRequestCallback** aCallback)
{
NS_ENSURE_ARG_POINTER(aCallback);
nsCOMPtr<nsIContentPermissionRequestCallback> callback = mListener->GetCallback();
callback.forget(aCallback);
return NS_OK;
}
} // namespace dom
} // namespace mozilla
NS_IMPL_ISUPPORTS(nsContentPermissionRequestProxy::nsContentPermissionRequesterProxy,
nsIContentPermissionRequester)
NS_IMETHODIMP
nsContentPermissionRequestProxy::nsContentPermissionRequesterProxy
::GetVisibility(nsIContentPermissionRequestCallback* aCallback)
{
NS_ENSURE_ARG_POINTER(aCallback);
mGetCallback = aCallback;
mWaitGettingResult = true;
unused << mParent->SendGetVisibility();
return NS_OK;
}
NS_IMETHODIMP
nsContentPermissionRequestProxy::nsContentPermissionRequesterProxy
::SetOnVisibilityChange(nsIContentPermissionRequestCallback* aCallback)
{
mOnChangeCallback = aCallback;
return NS_OK;
}
NS_IMETHODIMP
nsContentPermissionRequestProxy::nsContentPermissionRequesterProxy
::GetOnVisibilityChange(nsIContentPermissionRequestCallback** aCallback)
{
NS_ENSURE_ARG_POINTER(aCallback);
nsCOMPtr<nsIContentPermissionRequestCallback> callback = mOnChangeCallback;
callback.forget(aCallback);
return NS_OK;
}
void
nsContentPermissionRequestProxy::nsContentPermissionRequesterProxy
::NotifyVisibilityResult(const bool& aIsVisible)
{
if (mWaitGettingResult) {
MOZ_ASSERT(mGetCallback);
mWaitGettingResult = false;
mGetCallback->NotifyVisibility(aIsVisible);
return;
}
if (mOnChangeCallback) {
mOnChangeCallback->NotifyVisibility(aIsVisible);
}
}
nsContentPermissionRequestProxy::nsContentPermissionRequestProxy()
{
MOZ_COUNT_CTOR(nsContentPermissionRequestProxy);
@ -296,6 +524,7 @@ nsContentPermissionRequestProxy::Init(const nsTArray<PermissionRequest>& request
NS_ASSERTION(parent, "null parent");
mParent = parent;
mPermissionRequests = requests;
mRequester = new nsContentPermissionRequesterProxy(mParent);
nsCOMPtr<nsIContentPermissionPrompt> prompt = do_GetService(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
if (!prompt) {
@ -309,6 +538,7 @@ nsContentPermissionRequestProxy::Init(const nsTArray<PermissionRequest>& request
void
nsContentPermissionRequestProxy::OnParentDestroyed()
{
mRequester = nullptr;
mParent = nullptr;
}
@ -397,12 +627,12 @@ nsContentPermissionRequestProxy::Allow(JS::HandleValue aChoices)
if (mPermissionRequests[i].type().EqualsLiteral("audio-capture")) {
GonkPermissionService::GetInstance()->addGrantInfo(
"android.permission.RECORD_AUDIO",
TabParent::GetFrom(mParent->Manager())->Manager()->AsContentParent()->Pid());
static_cast<ContentParent*>(mParent->Manager())->Pid());
}
if (mPermissionRequests[i].type().EqualsLiteral("video-capture")) {
GonkPermissionService::GetInstance()->addGrantInfo(
"android.permission.CAMERA",
TabParent::GetFrom(mParent->Manager())->Manager()->AsContentParent()->Pid());
static_cast<ContentParent*>(mParent->Manager())->Pid());
}
}
#endif
@ -442,9 +672,27 @@ nsContentPermissionRequestProxy::Allow(JS::HandleValue aChoices)
return NS_OK;
}
void
nsContentPermissionRequestProxy::NotifyVisibility(const bool& aIsVisible)
{
MOZ_ASSERT(mRequester);
mRequester->NotifyVisibilityResult(aIsVisible);
}
NS_IMETHODIMP
nsContentPermissionRequestProxy::GetRequester(nsIContentPermissionRequester** aRequester)
{
NS_ENSURE_ARG_POINTER(aRequester);
nsRefPtr<nsContentPermissionRequesterProxy> requester = mRequester;
requester.forget(aRequester);
return NS_OK;
}
// RemotePermissionRequest
NS_IMPL_ISUPPORTS0(RemotePermissionRequest)
NS_IMPL_ISUPPORTS(RemotePermissionRequest, nsIContentPermissionRequestCallback);
RemotePermissionRequest::RemotePermissionRequest(
nsIContentPermissionRequest* aRequest,
@ -453,6 +701,8 @@ RemotePermissionRequest::RemotePermissionRequest(
, mWindow(aWindow)
, mIPCOpen(false)
{
mListener = new VisibilityChangeListener(mWindow);
mListener->SetCallback(this);
}
void
@ -474,6 +724,9 @@ bool
RemotePermissionRequest::Recv__delete__(const bool& aAllow,
InfallibleTArray<PermissionChoice>&& aChoices)
{
mListener->RemoveListener();
mListener = nullptr;
if (aAllow && mWindow->IsCurrentInnerWindow()) {
// Use 'undefined' if no choice is provided.
if (aChoices.IsEmpty()) {
@ -507,3 +760,28 @@ RemotePermissionRequest::Recv__delete__(const bool& aAllow,
}
return true;
}
bool
RemotePermissionRequest::RecvGetVisibility()
{
nsCOMPtr<nsIDocShell> docshell = mWindow->GetDocShell();
if (!docshell) {
return false;
}
bool isActive = false;
docshell->GetIsActive(&isActive);
unused << SendNotifyVisibility(isActive);
return true;
}
NS_IMETHODIMP
RemotePermissionRequest::NotifyVisibility(bool isVisible)
{
if (!mIPCOpen) {
return NS_OK;
}
unused << SendNotifyVisibility(isVisible);
return NS_OK;
}

View File

@ -9,6 +9,9 @@
#include "nsTArray.h"
#include "nsIMutableArray.h"
#include "mozilla/dom/PContentPermissionRequestChild.h"
#include "mozilla/dom/ipc/IdType.h"
#include "nsIDOMEventListener.h"
// Microsoft's API Name hackery sucks
// XXXbz Doing this in a header is a gigantic footgun. See
// https://bugzilla.mozilla.org/show_bug.cgi?id=932421#c3 for why.
@ -27,6 +30,25 @@ namespace IPC {
class Principal;
}
class VisibilityChangeListener final : public nsIDOMEventListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMEVENTLISTENER
explicit VisibilityChangeListener(nsPIDOMWindow* aWindow);
void RemoveListener();
void SetCallback(nsIContentPermissionRequestCallback* aCallback);
already_AddRefed<nsIContentPermissionRequestCallback> GetCallback();
private:
virtual ~VisibilityChangeListener() {}
nsWeakPtr mWindow;
nsCOMPtr<nsIContentPermissionRequestCallback> mCallback;
};
namespace mozilla {
namespace dom {
@ -73,44 +95,92 @@ public:
static PContentPermissionRequestParent*
CreateContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequests,
Element* element,
const IPC::Principal& principal);
const IPC::Principal& principal,
const TabId& aTabId);
static nsresult
AskPermission(nsIContentPermissionRequest* aRequest, nsPIDOMWindow* aWindow);
static nsTArray<PContentPermissionRequestParent*>
GetContentPermissionRequestParentById(const TabId& aTabId);
static void
NotifyRemoveContentPermissionRequestParent(PContentPermissionRequestParent* aParent);
};
class nsContentPermissionRequester final : public nsIContentPermissionRequester
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSICONTENTPERMISSIONREQUESTER
explicit nsContentPermissionRequester(nsPIDOMWindow* aWindow);
private:
virtual ~nsContentPermissionRequester();
nsCOMPtr<nsPIDOMWindow> mWindow;
nsRefPtr<VisibilityChangeListener> mListener;
};
} // namespace dom
} // namespace mozilla
using mozilla::dom::ContentPermissionRequestParent;
class nsContentPermissionRequestProxy : public nsIContentPermissionRequest
{
public:
public:
NS_DECL_ISUPPORTS
NS_DECL_NSICONTENTPERMISSIONREQUEST
nsContentPermissionRequestProxy();
nsresult Init(const nsTArray<mozilla::dom::PermissionRequest>& requests,
mozilla::dom::ContentPermissionRequestParent* parent);
ContentPermissionRequestParent* parent);
void OnParentDestroyed();
private:
void NotifyVisibility(const bool& aIsVisible);
private:
class nsContentPermissionRequesterProxy final : public nsIContentPermissionRequester {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSICONTENTPERMISSIONREQUESTER
explicit nsContentPermissionRequesterProxy(ContentPermissionRequestParent* aParent)
: mParent(aParent)
, mWaitGettingResult(false) {}
void NotifyVisibilityResult(const bool& aIsVisible);
private:
virtual ~nsContentPermissionRequesterProxy() {}
ContentPermissionRequestParent* mParent;
bool mWaitGettingResult;
nsCOMPtr<nsIContentPermissionRequestCallback> mGetCallback;
nsCOMPtr<nsIContentPermissionRequestCallback> mOnChangeCallback;
};
virtual ~nsContentPermissionRequestProxy();
// Non-owning pointer to the ContentPermissionRequestParent object which owns this proxy.
mozilla::dom::ContentPermissionRequestParent* mParent;
ContentPermissionRequestParent* mParent;
nsTArray<mozilla::dom::PermissionRequest> mPermissionRequests;
nsRefPtr<nsContentPermissionRequesterProxy> mRequester;
};
/**
* RemotePermissionRequest will send a prompt ipdl request to b2g process.
*/
class RemotePermissionRequest final : public nsISupports
class RemotePermissionRequest final : public nsIContentPermissionRequestCallback
, public mozilla::dom::PContentPermissionRequestChild
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSICONTENTPERMISSIONREQUESTCALLBACK
RemotePermissionRequest(nsIContentPermissionRequest* aRequest,
nsPIDOMWindow* aWindow);
@ -119,6 +189,8 @@ public:
virtual bool Recv__delete__(const bool &aAllow,
InfallibleTArray<PermissionChoice>&& aChoices) override;
virtual bool RecvGetVisibility() override;
void IPDLAddRef()
{
mIPCOpen = true;
@ -143,6 +215,7 @@ private:
nsCOMPtr<nsIContentPermissionRequest> mRequest;
nsCOMPtr<nsPIDOMWindow> mWindow;
bool mIPCOpen;
nsRefPtr<VisibilityChangeListener> mListener;
};
#endif // nsContentPermissionHelper_h

View File

@ -12009,7 +12009,13 @@ public:
nsPointerLockPermissionRequest(Element* aElement, bool aUserInputOrChromeCaller)
: mElement(do_GetWeakReference(aElement)),
mDocument(do_GetWeakReference(aElement->OwnerDoc())),
mUserInputOrChromeCaller(aUserInputOrChromeCaller) {}
mUserInputOrChromeCaller(aUserInputOrChromeCaller)
{
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
if (doc) {
mRequester = new nsContentPermissionRequester(doc->GetInnerWindow());
}
}
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSICONTENTPERMISSIONREQUEST
@ -12069,6 +12075,7 @@ public:
protected:
virtual ~nsPointerLockPermissionRequest() {}
nsCOMPtr<nsIContentPermissionRequester> mRequester;
};
NS_IMPL_ISUPPORTS_INHERITED(nsPointerLockPermissionRequest,
@ -12174,6 +12181,16 @@ 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;
}
void
nsDocument::SetApprovedForFullscreen(bool aIsApproved)
{

View File

@ -151,6 +151,7 @@ public:
, mCameraId(aCameraId)
, mInitialConfig(aInitialConfig)
, mPromise(aPromise)
, mRequester(new nsContentPermissionRequester(mWindow))
{ }
protected:
@ -165,6 +166,7 @@ protected:
uint32_t mCameraId;
CameraConfiguration mInitialConfig;
nsRefPtr<Promise> mPromise;
nsCOMPtr<nsIContentPermissionRequester> mRequester;
};
NS_IMPL_CYCLE_COLLECTION(CameraPermissionRequest, mWindow, mPromise)
@ -218,6 +220,16 @@ CameraPermissionRequest::Allow(JS::HandleValue aChoices)
return DispatchCallback(nsIPermissionManager::ALLOW_ACTION);
}
NS_IMETHODIMP
CameraPermissionRequest::GetRequester(nsIContentPermissionRequester** aRequester)
{
NS_ENSURE_ARG_POINTER(aRequester);
nsCOMPtr<nsIContentPermissionRequester> requester = mRequester;
requester.forget(aRequester);
return NS_OK;
}
nsresult
CameraPermissionRequest::DispatchCallback(uint32_t aPermission)
{

View File

@ -2176,6 +2176,7 @@ nsDOMDeviceStorageCursor::nsDOMDeviceStorageCursor(nsPIDOMWindow* aWindow,
, mSince(aSince)
, mFile(aFile)
, mPrincipal(aPrincipal)
, mRequester(new nsContentPermissionRequester(GetOwner()))
{
}
@ -2265,6 +2266,16 @@ nsDOMDeviceStorageCursor::Allow(JS::HandleValue aChoices)
return NS_OK;
}
NS_IMETHODIMP
nsDOMDeviceStorageCursor::GetRequester(nsIContentPermissionRequester** aRequester)
{
NS_ENSURE_ARG_POINTER(aRequester);
nsCOMPtr<nsIContentPermissionRequester> requester = mRequester;
requester.forget(aRequester);
return NS_OK;
}
void
nsDOMDeviceStorageCursor::Continue(ErrorResult& aRv)
{
@ -2851,6 +2862,7 @@ public:
, mFile(aFile)
, mRequest(aRequest)
, mDeviceStorage(aDeviceStorage)
, mRequester(new nsContentPermissionRequester(mWindow))
{
MOZ_ASSERT(mWindow);
MOZ_ASSERT(mPrincipal);
@ -2871,6 +2883,7 @@ public:
, mFile(aFile)
, mRequest(aRequest)
, mBlob(aBlob)
, mRequester(new nsContentPermissionRequester(mWindow))
{
MOZ_ASSERT(mWindow);
MOZ_ASSERT(mPrincipal);
@ -2890,6 +2903,7 @@ public:
, mFile(aFile)
, mRequest(aRequest)
, mDSFileDescriptor(aDSFileDescriptor)
, mRequester(new nsContentPermissionRequester(mWindow))
{
MOZ_ASSERT(mRequestType == DEVICE_STORAGE_REQUEST_CREATEFD);
MOZ_ASSERT(mWindow);
@ -3299,6 +3313,15 @@ public:
return NS_OK;
}
NS_IMETHODIMP GetRequester(nsIContentPermissionRequester** aRequester)
{
NS_ENSURE_ARG_POINTER(aRequester);
nsCOMPtr<nsIContentPermissionRequester> requester = mRequester;
requester.forget(aRequester);
return NS_OK;
}
private:
~DeviceStorageRequest() {}
@ -3311,6 +3334,7 @@ private:
nsCOMPtr<nsIDOMBlob> mBlob;
nsRefPtr<nsDOMDeviceStorage> mDeviceStorage;
nsRefPtr<DeviceStorageFileDescriptor> mDSFileDescriptor;
nsCOMPtr<nsIContentPermissionRequester> mRequester;
};
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DeviceStorageRequest)

View File

@ -220,6 +220,7 @@ private:
nsRefPtr<DeviceStorageFile> mFile;
nsCOMPtr<nsIPrincipal> mPrincipal;
nsCOMPtr<nsIContentPermissionRequester> mRequester;
};
//helpers

View File

@ -55,6 +55,7 @@ FileSystemPermissionRequest::FileSystemPermissionRequest(
}
mPrincipal = doc->NodePrincipal();
mRequester = new nsContentPermissionRequester(mWindow);
}
FileSystemPermissionRequest::~FileSystemPermissionRequest()
@ -135,5 +136,15 @@ FileSystemPermissionRequest::Run()
return NS_OK;
}
NS_IMETHODIMP
FileSystemPermissionRequest::GetRequester(nsIContentPermissionRequester** aRequester)
{
NS_ENSURE_ARG_POINTER(aRequester);
nsCOMPtr<nsIContentPermissionRequester> requester = mRequester;
requester.forget(aRequester);
return NS_OK;
}
} /* namespace dom */
} /* namespace mozilla */

View File

@ -42,6 +42,7 @@ private:
nsRefPtr<FileSystemTaskBase> mTask;
nsCOMPtr<nsPIDOMWindow> mWindow;
nsCOMPtr<nsIPrincipal> mPrincipal;
nsCOMPtr<nsIContentPermissionRequester> mRequester;
};
} // namespace dom

View File

@ -111,6 +111,7 @@ class nsGeolocationRequest final
int32_t mWatchId;
bool mShutdown;
nsCOMPtr<nsIContentPermissionRequester> mRequester;
};
static PositionOptions*
@ -356,6 +357,13 @@ nsGeolocationRequest::nsGeolocationRequest(Geolocation* aLocator,
mWatchId(aWatchId),
mShutdown(false)
{
nsCOMPtr<nsIDOMWindow> win = do_QueryReferent(mLocator->GetOwner());
if (win) {
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(win);
if (window) {
mRequester = new nsContentPermissionRequester(window);
}
}
}
nsGeolocationRequest::~nsGeolocationRequest()
@ -500,6 +508,16 @@ nsGeolocationRequest::Allow(JS::HandleValue aChoices)
return NS_OK;
}
NS_IMETHODIMP
nsGeolocationRequest::GetRequester(nsIContentPermissionRequester** aRequester)
{
NS_ENSURE_ARG_POINTER(aRequester);
nsCOMPtr<nsIContentPermissionRequester> requester = mRequester;
requester.forget(aRequester);
return NS_OK;
}
void
nsGeolocationRequest::SetTimeoutTimer()
{

View File

@ -32,12 +32,40 @@ interface nsIContentPermissionType : nsISupports {
readonly attribute nsIArray options; // ["choice1", "choice2"]
};
/**
* Interface provides the callback type.
*/
[scriptable, uuid(5fb5bb60-7069-11e4-9803-0800200c9a66)]
interface nsIContentPermissionRequestCallback : nsISupports {
/**
* The callback of the visibility result.
*/
void notifyVisibility(in boolean isVisible);
};
/**
* Interface provides the way to get the visibility and
* the notification.
*/
[scriptable, uuid(f8577124-6a5f-486f-ae04-c5bcae911eb5)]
interface nsIContentPermissionRequester : nsISupports {
/**
* The function to get the visibility.
*/
void getVisibility(in nsIContentPermissionRequestCallback callback);
/**
* The callback to get the notification of visibility change.
*/
attribute nsIContentPermissionRequestCallback onVisibilityChange;
};
/**
* Interface allows access to a content to request
* permission to perform a privileged operation such as
* geolocation.
*/
[scriptable, uuid(69a39d88-d1c4-4ba9-9b19-bafc7a1bb783)]
[scriptable, uuid(408c8fcd-1420-4aff-94d8-39bf74d79219)]
interface nsIContentPermissionRequest : nsISupports {
/**
* The array will include the request types. Elements of this array are
@ -59,6 +87,12 @@ interface nsIContentPermissionRequest : nsISupports {
readonly attribute nsIDOMWindow window;
readonly attribute nsIDOMElement element;
/**
* The requester to get the required information of
* the window.
*/
readonly attribute nsIContentPermissionRequester requester;
/**
* allow or cancel the request
*/

View File

@ -98,6 +98,7 @@
#include "nsISystemMessageCache.h"
#include "nsDirectoryServiceUtils.h"
#include "nsDirectoryServiceDefs.h"
#include "nsContentPermissionHelper.h"
#include "IHistory.h"
#include "nsNetUtil.h"
@ -2719,6 +2720,23 @@ ContentChild::RecvUpdateWindow(const uintptr_t& aChildId)
#endif
}
PContentPermissionRequestChild*
ContentChild::AllocPContentPermissionRequestChild(const InfallibleTArray<PermissionRequest>& aRequests,
const IPC::Principal& aPrincipal,
const TabId& aTabId)
{
NS_RUNTIMEABORT("unused");
return nullptr;
}
bool
ContentChild::DeallocPContentPermissionRequestChild(PContentPermissionRequestChild* actor)
{
auto child = static_cast<RemotePermissionRequest*>(actor);
child->IPDLRelease();
return true;
}
// This code goes here rather than nsGlobalWindow.cpp because nsGlobalWindow.cpp
// can't include ContentChild.h since it includes windows.h.

View File

@ -457,6 +457,13 @@ public:
virtual bool
DeallocPOfflineCacheUpdateChild(POfflineCacheUpdateChild* offlineCacheUpdate) override;
virtual PContentPermissionRequestChild*
AllocPContentPermissionRequestChild(const InfallibleTArray<PermissionRequest>& aRequests,
const IPC::Principal& aPrincipal,
const TabId& aTabId) override;
virtual bool
DeallocPContentPermissionRequestChild(PContentPermissionRequestChild* actor) override;
private:
virtual void ActorDestroy(ActorDestroyReason why) override;

View File

@ -46,6 +46,7 @@
#include "mozilla/dom/FileSystemRequestParent.h"
#include "mozilla/dom/GeolocationBinding.h"
#include "mozilla/dom/PContentBridgeParent.h"
#include "mozilla/dom/PContentPermissionRequestParent.h"
#include "mozilla/dom/PCycleCollectWithLogsParent.h"
#include "mozilla/dom/PFMRadioParent.h"
#include "mozilla/dom/PMemoryReportRequestParent.h"
@ -100,6 +101,7 @@
#include "nsIAlertsService.h"
#include "nsIAppsService.h"
#include "nsIClipboard.h"
#include "nsContentPermissionHelper.h"
#include "nsICycleCollectorListener.h"
#include "nsIDocument.h"
#include "nsIDOMGeoGeolocation.h"
@ -2067,6 +2069,18 @@ ContentParent::NotifyTabDestroyed(PBrowserParent* aTab,
--mNumDestroyingTabs;
}
TabId id = static_cast<TabParent*>(aTab)->GetTabId();
nsTArray<PContentPermissionRequestParent*> parentArray =
nsContentPermissionUtils::GetContentPermissionRequestParentById(id);
// Need to close undeleted ContentPermissionRequestParents before tab is closed.
for (auto& permissionRequestParent : parentArray) {
nsTArray<PermissionChoice> emptyChoices;
unused << PContentPermissionRequestParent::Send__delete__(permissionRequestParent,
false,
emptyChoices);
}
// There can be more than one PBrowser for a given app process
// because of popup windows. When the last one closes, shut
// us down.
@ -4883,6 +4897,32 @@ ContentParent::RecvUpdateDropEffect(const uint32_t& aDragAction,
return true;
}
PContentPermissionRequestParent*
ContentParent::AllocPContentPermissionRequestParent(const InfallibleTArray<PermissionRequest>& aRequests,
const IPC::Principal& aPrincipal,
const TabId& aTabId)
{
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
nsRefPtr<TabParent> tp = cpm->GetTopLevelTabParentByProcessAndTabId(this->ChildID(),
aTabId);
if (!tp) {
return nullptr;
}
return nsContentPermissionUtils::CreateContentPermissionRequestParent(aRequests,
tp->GetOwnerElement(),
aPrincipal,
aTabId);
}
bool
ContentParent::DeallocPContentPermissionRequestParent(PContentPermissionRequestParent* actor)
{
nsContentPermissionUtils::NotifyRemoveContentPermissionRequestParent(actor);
delete actor;
return true;
}
} // namespace dom
} // namespace mozilla

View File

@ -372,6 +372,14 @@ public:
virtual bool RecvFinishShutdown() override;
void MaybeInvokeDragSession(TabParent* aParent);
virtual PContentPermissionRequestParent*
AllocPContentPermissionRequestParent(const InfallibleTArray<PermissionRequest>& aRequests,
const IPC::Principal& aPrincipal,
const TabId& aTabId) override;
virtual bool
DeallocPContentPermissionRequestParent(PContentPermissionRequestParent* actor) override;
protected:
void OnChannelConnected(int32_t pid) override;
virtual void ActorDestroy(ActorDestroyReason why) override;

View File

@ -10,7 +10,6 @@ include protocol PColorPicker;
include protocol PContent;
include protocol PContentBridge;
include protocol PDocumentRenderer;
include protocol PContentPermissionRequest;
include protocol PFilePicker;
include protocol PIndexedDBPermissionRequest;
include protocol PRenderFrame;
@ -18,7 +17,6 @@ include protocol PPluginWidget;
include DOMTypes;
include JavaScriptTypes;
include URIParams;
include PContentPermission;
include ServiceWorkerRegistrarTypes;
@ -103,7 +101,6 @@ prio(normal upto urgent) sync protocol PBrowser
manages PColorPicker;
manages PDocumentRenderer;
manages PContentPermissionRequest;
manages PFilePicker;
manages PIndexedDBPermissionRequest;
manages PRenderFrame;
@ -384,21 +381,6 @@ parent:
*/
PColorPicker(nsString title, nsString initialColor);
/**
* Initiates an asynchronous request for permission for the
* provided principal.
*
* @param aRequests
* The array of permissions to request.
* @param aPrincipal
* The principal of the request.
*
* NOTE: The principal is untrusted in the parent process. Only
* principals that can live in the content process should
* provided.
*/
PContentPermissionRequest(PermissionRequest[] aRequests, Principal aPrincipal);
PFilePicker(nsString aTitle, int16_t aMode);
/**

View File

@ -12,6 +12,7 @@ include protocol PBrowser;
include protocol PCellBroadcast;
include protocol PCompositor;
include protocol PContentBridge;
include protocol PContentPermissionRequest;
include protocol PCycleCollectWithLogs;
include protocol PCrashReporter;
include protocol PDocAccessible;
@ -55,6 +56,7 @@ include PTabContext;
include URIParams;
include PluginTypes;
include ProtocolTypes;
include PContentPermission;
// Workaround to prevent error if PContentChild.cpp & PContentBridgeParent.cpp
// are put into different UnifiedProtocolsXX.cpp files.
@ -380,6 +382,7 @@ prio(normal upto urgent) sync protocol PContent
manages PBluetooth;
manages PBrowser;
manages PCellBroadcast;
manages PContentPermissionRequest;
manages PCrashReporter;
manages PCycleCollectWithLogs;
manages PDocAccessible;
@ -951,6 +954,25 @@ parent:
async FinishShutdown();
UpdateDropEffect(uint32_t aDragAction, uint32_t aDropEffect);
/**
* Initiates an asynchronous request for permission for the
* provided principal.
*
* @param aRequests
* The array of permissions to request.
* @param aPrincipal
* The principal of the request.
* @param tabId
* To identify which tab issues this request.
*
* NOTE: The principal is untrusted in the parent process. Only
* principals that can live in the content process should
* provided.
*/
PContentPermissionRequest(PermissionRequest[] aRequests, Principal aPrincipal,
TabId tabId);
both:
AsyncMessage(nsString aMessage, ClonedMessageData aData,
CpowEntry[] aCpows, Principal aPrincipal);

View File

@ -2,7 +2,7 @@
* 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 protocol PBrowser;
include protocol PContent;
include PContentPermission;
namespace mozilla {
@ -10,12 +10,14 @@ namespace dom {
protocol PContentPermissionRequest
{
manager PBrowser;
manager PContent;
parent:
prompt();
NotifyVisibility(bool visibility);
child:
GetVisibility();
__delete__(bool allow, PermissionChoice[] choices);
};

View File

@ -71,7 +71,6 @@
#include "nsWeakReference.h"
#include "nsWindowWatcher.h"
#include "PermissionMessageUtils.h"
#include "nsContentPermissionHelper.h"
#include "PuppetWidget.h"
#include "StructuredCloneUtils.h"
#include "nsViewportInfo.h"
@ -2618,22 +2617,6 @@ TabChild::DeallocPColorPickerChild(PColorPickerChild* aColorPicker)
return true;
}
PContentPermissionRequestChild*
TabChild::AllocPContentPermissionRequestChild(const InfallibleTArray<PermissionRequest>& aRequests,
const IPC::Principal& aPrincipal)
{
NS_RUNTIMEABORT("unused");
return nullptr;
}
bool
TabChild::DeallocPContentPermissionRequestChild(PContentPermissionRequestChild* actor)
{
RemotePermissionRequest* child = static_cast<RemotePermissionRequest*>(actor);
child->IPDLRelease();
return true;
}
PFilePickerChild*
TabChild::AllocPFilePickerChild(const nsString&, const int16_t&)
{

View File

@ -403,12 +403,6 @@ public:
AllocPColorPickerChild(const nsString& title, const nsString& initialColor) override;
virtual bool DeallocPColorPickerChild(PColorPickerChild* actor) override;
virtual PContentPermissionRequestChild*
AllocPContentPermissionRequestChild(const InfallibleTArray<PermissionRequest>& aRequests,
const IPC::Principal& aPrincipal) override;
virtual bool
DeallocPContentPermissionRequestChild(PContentPermissionRequestChild* actor) override;
virtual PFilePickerChild*
AllocPFilePickerChild(const nsString& aTitle, const int16_t& aMode) override;
virtual bool

View File

@ -13,7 +13,6 @@
#include "mozilla/BrowserElementParent.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/DataTransfer.h"
#include "mozilla/dom/PContentPermissionRequestParent.h"
#include "mozilla/dom/ServiceWorkerRegistrar.h"
#include "mozilla/dom/indexedDB/ActorsParent.h"
#include "mozilla/plugins/PluginWidgetParent.h"
@ -34,7 +33,6 @@
#include "BlobParent.h"
#include "nsCOMPtr.h"
#include "nsContentAreaDragDrop.h"
#include "nsContentPermissionHelper.h"
#include "nsContentUtils.h"
#include "nsDebug.h"
#include "nsFocusManager.h"
@ -1073,20 +1071,6 @@ TabParent::DeallocPDocumentRendererParent(PDocumentRendererParent* actor)
return true;
}
PContentPermissionRequestParent*
TabParent::AllocPContentPermissionRequestParent(const InfallibleTArray<PermissionRequest>& aRequests,
const IPC::Principal& aPrincipal)
{
return nsContentPermissionUtils::CreateContentPermissionRequestParent(aRequests, mFrameElement, aPrincipal);
}
bool
TabParent::DeallocPContentPermissionRequestParent(PContentPermissionRequestParent* actor)
{
delete actor;
return true;
}
PFilePickerParent*
TabParent::AllocPFilePickerParent(const nsString& aTitle, const int16_t& aMode)
{

View File

@ -326,12 +326,6 @@ public:
const nsIntSize& renderSize) override;
virtual bool DeallocPDocumentRendererParent(PDocumentRendererParent* actor) override;
virtual PContentPermissionRequestParent*
AllocPContentPermissionRequestParent(const InfallibleTArray<PermissionRequest>& aRequests,
const IPC::Principal& aPrincipal) override;
virtual bool
DeallocPContentPermissionRequestParent(PContentPermissionRequestParent* actor) override;
virtual PFilePickerParent*
AllocPFilePickerParent(const nsString& aTitle,
const int16_t& aMode) override;

View File

@ -129,6 +129,7 @@ private:
nsRefPtr<dom::GetUserMediaRequest> mRequest;
nsTArray<nsCOMPtr<nsIMediaDevice> > mAudioDevices; // candidate audio devices
nsTArray<nsCOMPtr<nsIMediaDevice> > mVideoDevices; // candidate video devices
nsCOMPtr<nsIContentPermissionRequester> mRequester;
};
// MediaPermissionRequest
@ -155,6 +156,9 @@ MediaPermissionRequest::MediaPermissionRequest(nsRefPtr<dom::GetUserMediaRequest
mVideoDevices.AppendElement(device);
}
}
nsCOMPtr<nsPIDOMWindow> window = GetOwner();
mRequester = new nsContentPermissionRequester(window.get());
}
// nsIContentPermissionRequest methods
@ -274,6 +278,16 @@ MediaPermissionRequest::Allow(JS::HandleValue aChoices)
return DoAllow(audioDevice, videoDevice);
}
NS_IMETHODIMP
MediaPermissionRequest::GetRequester(nsIContentPermissionRequester** aRequester)
{
NS_ENSURE_ARG_POINTER(aRequester);
nsCOMPtr<nsIContentPermissionRequester> requester = mRequester;
requester.forget(aRequester);
return NS_OK;
}
nsresult
MediaPermissionRequest::DoAllow(const nsString &audioDevice,
const nsString &videoDevice)

View File

@ -30,12 +30,16 @@ class DesktopNotificationRequest : public nsIContentPermissionRequest
{
}
nsCOMPtr<nsIContentPermissionRequester> mRequester;
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSICONTENTPERMISSIONREQUEST
explicit DesktopNotificationRequest(DesktopNotification* aNotification)
: mDesktopNotification(aNotification) {}
: mDesktopNotification(aNotification)
{
mRequester = new nsContentPermissionRequester(mDesktopNotification->GetOwner());
}
NS_IMETHOD Run() override
{
@ -313,6 +317,16 @@ DesktopNotificationRequest::Allow(JS::HandleValue aChoices)
return rv;
}
NS_IMETHODIMP
DesktopNotificationRequest::GetRequester(nsIContentPermissionRequester** aRequester)
{
NS_ENSURE_ARG_POINTER(aRequester);
nsCOMPtr<nsIContentPermissionRequester> requester = mRequester;
requester.forget(aRequester);
return NS_OK;
}
NS_IMETHODIMP
DesktopNotificationRequest::GetTypes(nsIArray** aTypes)
{

View File

@ -172,7 +172,10 @@ public:
NotificationPermissionCallback* aCallback)
: mPrincipal(aPrincipal), mWindow(aWindow),
mPermission(NotificationPermission::Default),
mCallback(aCallback) {}
mCallback(aCallback)
{
mRequester = new nsContentPermissionRequester(mWindow);
}
protected:
virtual ~NotificationPermissionRequest() {}
@ -183,6 +186,7 @@ protected:
nsCOMPtr<nsPIDOMWindow> mWindow;
NotificationPermission mPermission;
nsRefPtr<NotificationPermissionCallback> mCallback;
nsCOMPtr<nsIContentPermissionRequester> mRequester;
};
class NotificationObserver : public nsIObserver
@ -307,6 +311,16 @@ NotificationPermissionRequest::Allow(JS::HandleValue aChoices)
return DispatchCallback();
}
NS_IMETHODIMP
NotificationPermissionRequest::GetRequester(nsIContentPermissionRequester** aRequester)
{
NS_ENSURE_ARG_POINTER(aRequester);
nsCOMPtr<nsIContentPermissionRequester> requester = mRequester;
requester.forget(aRequester);
return NS_OK;
}
inline nsresult
NotificationPermissionRequest::DispatchCallback()
{