1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef nsContentPermissionHelper_h
8 #define nsContentPermissionHelper_h
9 
10 #include "nsIContentPermissionPrompt.h"
11 #include "nsTArray.h"
12 #include "nsIMutableArray.h"
13 #include "mozilla/dom/PContentPermissionRequestChild.h"
14 #include "mozilla/dom/ipc/IdType.h"
15 #include "mozilla/PermissionDelegateHandler.h"
16 
17 // Microsoft's API Name hackery sucks
18 // XXXbz Doing this in a header is a gigantic footgun. See
19 // https://bugzilla.mozilla.org/show_bug.cgi?id=932421#c3 for why.
20 #undef LoadImage
21 
22 class nsPIDOMWindowInner;
23 class nsContentPermissionRequestProxy;
24 
25 // Forward declare IPC::Principal here which is defined in
26 // PermissionMessageUtils.h. Include this file will transitively includes
27 // "windows.h" and it defines
28 //   #define CreateEvent CreateEventW
29 //   #define LoadImage LoadImageW
30 // That will mess up windows build.
31 namespace IPC {
32 class Principal;
33 }  // namespace IPC
34 
35 namespace mozilla {
36 namespace dom {
37 
38 class Element;
39 class PermissionRequest;
40 class ContentPermissionRequestParent;
41 class PContentPermissionRequestParent;
42 
43 class ContentPermissionType : public nsIContentPermissionType {
44  public:
45   NS_DECL_ISUPPORTS
46   NS_DECL_NSICONTENTPERMISSIONTYPE
47 
48   ContentPermissionType(const nsACString& aType,
49                         const nsTArray<nsString>& aOptions);
50 
51  protected:
52   virtual ~ContentPermissionType();
53 
54   nsCString mType;
55   nsTArray<nsString> mOptions;
56 };
57 
58 class nsContentPermissionUtils {
59  public:
60   static uint32_t ConvertPermissionRequestToArray(
61       nsTArray<PermissionRequest>& aSrcArray, nsIMutableArray* aDesArray);
62 
63   static uint32_t ConvertArrayToPermissionRequest(
64       nsIArray* aSrcArray, nsTArray<PermissionRequest>& aDesArray);
65 
66   static nsresult CreatePermissionArray(const nsACString& aType,
67                                         const nsTArray<nsString>& aOptions,
68                                         nsIArray** aTypesArray);
69 
70   static PContentPermissionRequestParent* CreateContentPermissionRequestParent(
71       const nsTArray<PermissionRequest>& aRequests, Element* aElement,
72       nsIPrincipal* aPrincipal, nsIPrincipal* aTopLevelPrincipal,
73       const bool aIsHandlingUserInput,
74       const bool aMaybeUnsafePermissionDelegate, const TabId& aTabId);
75 
76   static nsresult AskPermission(nsIContentPermissionRequest* aRequest,
77                                 nsPIDOMWindowInner* aWindow);
78 
79   static nsTArray<PContentPermissionRequestParent*>
80   GetContentPermissionRequestParentById(const TabId& aTabId);
81 
82   static void NotifyRemoveContentPermissionRequestParent(
83       PContentPermissionRequestParent* aParent);
84 
85   static nsTArray<PContentPermissionRequestChild*>
86   GetContentPermissionRequestChildById(const TabId& aTabId);
87 
88   static void NotifyRemoveContentPermissionRequestChild(
89       PContentPermissionRequestChild* aChild);
90 };
91 
92 nsresult TranslateChoices(
93     JS::HandleValue aChoices,
94     const nsTArray<PermissionRequest>& aPermissionRequests,
95     nsTArray<PermissionChoice>& aTranslatedChoices);
96 
97 class ContentPermissionRequestBase : public nsIContentPermissionRequest {
98  public:
99   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
100   NS_DECL_CYCLE_COLLECTION_CLASS(ContentPermissionRequestBase)
101 
102   NS_IMETHOD GetTypes(nsIArray** aTypes) override;
103   NS_IMETHOD GetPrincipal(nsIPrincipal** aPrincipal) override;
104   NS_IMETHOD GetDelegatePrincipal(const nsACString& aType,
105                                   nsIPrincipal** aPrincipal) override;
106   NS_IMETHOD GetTopLevelPrincipal(nsIPrincipal** aTopLevelPrincipal) override;
107   NS_IMETHOD GetWindow(mozIDOMWindow** aWindow) override;
108   NS_IMETHOD GetElement(mozilla::dom::Element** aElement) override;
109   NS_IMETHOD GetIsHandlingUserInput(bool* aIsHandlingUserInput) override;
110   NS_IMETHOD GetMaybeUnsafePermissionDelegate(
111       bool* aMaybeUnsafePermissionDelegate) override;
112   // Overrides for Allow() and Cancel() aren't provided by this class.
113   // That is the responsibility of the subclasses.
114 
115   enum class PromptResult {
116     Granted,
117     Denied,
118     Pending,
119   };
120   nsresult ShowPrompt(PromptResult& aResult);
121 
122   PromptResult CheckPromptPrefs();
123 
124   // Check if the permission has an opportunity to request.
125   bool CheckPermissionDelegate();
126 
127   enum class DelayedTaskType {
128     Allow,
129     Deny,
130     Request,
131   };
132   void RequestDelayedTask(nsIEventTarget* aTarget, DelayedTaskType aType);
133 
134  protected:
135   ContentPermissionRequestBase(nsIPrincipal* aPrincipal,
136                                nsPIDOMWindowInner* aWindow,
137                                const nsACString& aPrefName,
138                                const nsACString& aType);
139   virtual ~ContentPermissionRequestBase() = default;
140 
141   nsCOMPtr<nsIPrincipal> mPrincipal;
142   nsCOMPtr<nsIPrincipal> mTopLevelPrincipal;
143   nsCOMPtr<nsPIDOMWindowInner> mWindow;
144   RefPtr<PermissionDelegateHandler> mPermissionHandler;
145   nsCString mPrefName;
146   nsCString mType;
147   bool mIsHandlingUserInput;
148   bool mMaybeUnsafePermissionDelegate;
149 };
150 
151 }  // namespace dom
152 }  // namespace mozilla
153 
154 using mozilla::dom::ContentPermissionRequestParent;
155 
156 class nsContentPermissionRequestProxy : public nsIContentPermissionRequest {
157  public:
158   NS_DECL_ISUPPORTS
159   NS_DECL_NSICONTENTPERMISSIONREQUEST
160 
161   explicit nsContentPermissionRequestProxy(
162       ContentPermissionRequestParent* parent);
163 
164   nsresult Init(const nsTArray<mozilla::dom::PermissionRequest>& requests);
165 
166   void OnParentDestroyed();
167 
168  private:
169   virtual ~nsContentPermissionRequestProxy();
170 
171   // Non-owning pointer to the ContentPermissionRequestParent object which owns
172   // this proxy.
173   ContentPermissionRequestParent* mParent;
174   nsTArray<mozilla::dom::PermissionRequest> mPermissionRequests;
175 };
176 
177 /**
178  * RemotePermissionRequest will send a prompt ipdl request to b2g process.
179  */
180 class RemotePermissionRequest final
181     : public mozilla::dom::PContentPermissionRequestChild {
182  public:
183   NS_INLINE_DECL_REFCOUNTING(RemotePermissionRequest)
184 
185   RemotePermissionRequest(nsIContentPermissionRequest* aRequest,
186                           nsPIDOMWindowInner* aWindow);
187 
188   // It will be called when prompt dismissed.  MOZ_CAN_RUN_SCRIPT_BOUNDARY
189   // because we don't have MOZ_CAN_RUN_SCRIPT bits in IPC code yet.
190   MOZ_CAN_RUN_SCRIPT_BOUNDARY
191   mozilla::ipc::IPCResult RecvNotifyResult(
192       const bool& aAllow, nsTArray<PermissionChoice>&& aChoices);
193 
IPDLAddRef()194   void IPDLAddRef() {
195     mIPCOpen = true;
196     AddRef();
197   }
198 
IPDLRelease()199   void IPDLRelease() {
200     mIPCOpen = false;
201     Release();
202   }
203 
204   void Destroy();
205 
IPCOpen()206   bool IPCOpen() const { return mIPCOpen && !mDestroyed; }
207 
208  private:
209   virtual ~RemotePermissionRequest();
210 
211   MOZ_CAN_RUN_SCRIPT
212   void DoAllow(JS::HandleValue aChoices);
213   MOZ_CAN_RUN_SCRIPT
214   void DoCancel();
215 
216   nsCOMPtr<nsIContentPermissionRequest> mRequest;
217   nsCOMPtr<nsPIDOMWindowInner> mWindow;
218   bool mIPCOpen;
219   bool mDestroyed;
220 };
221 
222 #endif  // nsContentPermissionHelper_h
223