dom/base/nsContentPermissionHelper.h
author Mike Hommey <mh+mozilla@glandium.org>
Thu, 17 Jan 2019 13:18:37 +0000
changeset 454358 c28522aaf3918c5f556c65432f8bf14a65bff65a
parent 448947 6f3709b3878117466168c40affa7bca0b60cf75b
child 456709 96e1ef345f95c858652910cdb379bbc279ab27c4
permissions -rw-r--r--
Bug 1520149 - Also disable the machine outliner on Android when LTO is enabled. r=dmajor Differential Revision: https://phabricator.services.mozilla.com/D16790

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 nsContentPermissionHelper_h
#define nsContentPermissionHelper_h

#include "nsIContentPermissionPrompt.h"
#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.
#undef LoadImage

class nsPIDOMWindowInner;
class nsContentPermissionRequestProxy;
class VisibilityChangeListener;

// Forward declare IPC::Principal here which is defined in
// PermissionMessageUtils.h. Include this file will transitively includes
// "windows.h" and it defines
//   #define CreateEvent CreateEventW
//   #define LoadImage LoadImageW
// That will mess up windows build.
namespace IPC {
class Principal;
}  // namespace IPC

namespace mozilla {
namespace dom {

class Element;
class PermissionRequest;
class ContentPermissionRequestParent;
class PContentPermissionRequestParent;

class ContentPermissionType : public nsIContentPermissionType {
 public:
  NS_DECL_ISUPPORTS
  NS_DECL_NSICONTENTPERMISSIONTYPE

  ContentPermissionType(const nsACString& aType,
                        const nsTArray<nsString>& aOptions);

 protected:
  virtual ~ContentPermissionType();

  nsCString mType;
  nsTArray<nsString> mOptions;
};

class nsContentPermissionUtils {
 public:
  static uint32_t ConvertPermissionRequestToArray(
      nsTArray<PermissionRequest>& aSrcArray, nsIMutableArray* aDesArray);

  static uint32_t ConvertArrayToPermissionRequest(
      nsIArray* aSrcArray, nsTArray<PermissionRequest>& aDesArray);

  static nsresult CreatePermissionArray(const nsACString& aType,
                                        const nsTArray<nsString>& aOptions,
                                        nsIArray** aTypesArray);

  static PContentPermissionRequestParent* CreateContentPermissionRequestParent(
      const nsTArray<PermissionRequest>& aRequests, Element* aElement,
      const IPC::Principal& aPrincipal,
      const IPC::Principal& aTopLevelPrincipal, const bool aIsHandlingUserInput,
      const TabId& aTabId);

  static nsresult AskPermission(nsIContentPermissionRequest* aRequest,
                                nsPIDOMWindowInner* aWindow);

  static nsTArray<PContentPermissionRequestParent*>
  GetContentPermissionRequestParentById(const TabId& aTabId);

  static void NotifyRemoveContentPermissionRequestParent(
      PContentPermissionRequestParent* aParent);

  static nsTArray<PContentPermissionRequestChild*>
  GetContentPermissionRequestChildById(const TabId& aTabId);

  static void NotifyRemoveContentPermissionRequestChild(
      PContentPermissionRequestChild* aChild);
};

class nsContentPermissionRequester final
    : public nsIContentPermissionRequester {
 public:
  NS_DECL_ISUPPORTS
  NS_DECL_NSICONTENTPERMISSIONREQUESTER

  explicit nsContentPermissionRequester(nsPIDOMWindowInner* aWindow);

 private:
  virtual ~nsContentPermissionRequester();

  nsWeakPtr mWindow;
  RefPtr<VisibilityChangeListener> mListener;
};

nsresult TranslateChoices(
    JS::HandleValue aChoices,
    const nsTArray<PermissionRequest>& aPermissionRequests,
    nsTArray<PermissionChoice>& aTranslatedChoices);

class ContentPermissionRequestBase : public nsIContentPermissionRequest {
 public:
  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
  NS_DECL_CYCLE_COLLECTION_CLASS(ContentPermissionRequestBase)

  NS_IMETHOD GetTypes(nsIArray** aTypes) override;
  NS_IMETHOD GetPrincipal(nsIPrincipal** aPrincipal) override;
  NS_IMETHOD GetTopLevelPrincipal(nsIPrincipal** aTopLevelPrincipal) override;
  NS_IMETHOD GetWindow(mozIDOMWindow** aWindow) override;
  NS_IMETHOD GetElement(mozilla::dom::Element** aElement) override;
  NS_IMETHOD GetIsHandlingUserInput(bool* aIsHandlingUserInput) override;
  NS_IMETHOD GetRequester(nsIContentPermissionRequester** aRequester) override;
  // Overrides for Allow() and Cancel() aren't provided by this class.
  // That is the responsibility of the subclasses.

  enum class PromptResult {
    Granted,
    Denied,
    Pending,
  };
  nsresult ShowPrompt(PromptResult& aResult);

  PromptResult CheckPromptPrefs();

  enum class DelayedTaskType {
    Allow,
    Deny,
    Request,
  };
  void RequestDelayedTask(nsIEventTarget* aTarget, DelayedTaskType aType);

 protected:
  ContentPermissionRequestBase(nsIPrincipal* aPrincipal,
                               bool aIsHandlingUserInput,
                               nsPIDOMWindowInner* aWindow,
                               const nsACString& aPrefName,
                               const nsACString& aType);
  virtual ~ContentPermissionRequestBase() = default;

  nsCOMPtr<nsIPrincipal> mPrincipal;
  nsCOMPtr<nsIPrincipal> mTopLevelPrincipal;
  nsCOMPtr<nsPIDOMWindowInner> mWindow;
  nsCOMPtr<nsIContentPermissionRequester> mRequester;
  nsCString mPrefName;
  nsCString mType;
  bool mIsHandlingUserInput;
};

}  // namespace dom
}  // namespace mozilla

using mozilla::dom::ContentPermissionRequestParent;

class nsContentPermissionRequestProxy : public nsIContentPermissionRequest {
 public:
  NS_DECL_ISUPPORTS
  NS_DECL_NSICONTENTPERMISSIONREQUEST

  explicit nsContentPermissionRequestProxy(
      ContentPermissionRequestParent* parent);

  nsresult Init(const nsTArray<mozilla::dom::PermissionRequest>& requests);

  void OnParentDestroyed();

  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.
  ContentPermissionRequestParent* mParent;
  nsTArray<mozilla::dom::PermissionRequest> mPermissionRequests;
  RefPtr<nsContentPermissionRequesterProxy> mRequester;
};

/**
 * RemotePermissionRequest will send a prompt ipdl request to b2g process.
 */
class RemotePermissionRequest final
    : public nsIContentPermissionRequestCallback,
      public mozilla::dom::PContentPermissionRequestChild {
 public:
  NS_DECL_ISUPPORTS
  NS_DECL_NSICONTENTPERMISSIONREQUESTCALLBACK

  RemotePermissionRequest(nsIContentPermissionRequest* aRequest,
                          nsPIDOMWindowInner* aWindow);

  // It will be called when prompt dismissed.
  virtual mozilla::ipc::IPCResult RecvNotifyResult(
      const bool& aAllow,
      InfallibleTArray<PermissionChoice>&& aChoices) override;

  virtual mozilla::ipc::IPCResult RecvGetVisibility() override;

  void IPDLAddRef() {
    mIPCOpen = true;
    AddRef();
  }

  void IPDLRelease() {
    mIPCOpen = false;
    Release();
  }

  void Destroy();

  bool IPCOpen() const { return mIPCOpen && !mDestroyed; }

 private:
  virtual ~RemotePermissionRequest();

  void DoAllow(JS::HandleValue aChoices);
  void DoCancel();

  nsCOMPtr<nsIContentPermissionRequest> mRequest;
  nsCOMPtr<nsPIDOMWindowInner> mWindow;
  bool mIPCOpen;
  bool mDestroyed;
  RefPtr<VisibilityChangeListener> mListener;
};

#endif  // nsContentPermissionHelper_h