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 // Converts blindly, that is, strings are not matched against any list. 64 // 65 // @param aSrcArray needs to contain elements of type 66 // `nsIContentPermissionType`. 67 static void ConvertArrayToPermissionRequest( 68 nsIArray* aSrcArray, nsTArray<PermissionRequest>& aDesArray); 69 70 static nsresult CreatePermissionArray(const nsACString& aType, 71 const nsTArray<nsString>& aOptions, 72 nsIArray** aTypesArray); 73 74 // @param aIsRequestDelegatedToUnsafeThirdParty see 75 // ContentPermissionRequestParent. 76 static PContentPermissionRequestParent* CreateContentPermissionRequestParent( 77 const nsTArray<PermissionRequest>& aRequests, Element* aElement, 78 nsIPrincipal* aPrincipal, nsIPrincipal* aTopLevelPrincipal, 79 const bool aHasValidTransientUserGestureActivation, 80 const bool aIsRequestDelegatedToUnsafeThirdParty, const TabId& aTabId); 81 82 static nsresult AskPermission(nsIContentPermissionRequest* aRequest, 83 nsPIDOMWindowInner* aWindow); 84 85 static nsTArray<PContentPermissionRequestParent*> 86 GetContentPermissionRequestParentById(const TabId& aTabId); 87 88 static void NotifyRemoveContentPermissionRequestParent( 89 PContentPermissionRequestParent* aParent); 90 91 static nsTArray<PContentPermissionRequestChild*> 92 GetContentPermissionRequestChildById(const TabId& aTabId); 93 94 static void NotifyRemoveContentPermissionRequestChild( 95 PContentPermissionRequestChild* aChild); 96 }; 97 98 nsresult TranslateChoices( 99 JS::HandleValue aChoices, 100 const nsTArray<PermissionRequest>& aPermissionRequests, 101 nsTArray<PermissionChoice>& aTranslatedChoices); 102 103 class ContentPermissionRequestBase : public nsIContentPermissionRequest { 104 public: 105 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 106 NS_DECL_CYCLE_COLLECTION_CLASS(ContentPermissionRequestBase) 107 108 NS_IMETHOD GetTypes(nsIArray** aTypes) override; 109 NS_IMETHOD GetPrincipal(nsIPrincipal** aPrincipal) override; 110 NS_IMETHOD GetDelegatePrincipal(const nsACString& aType, 111 nsIPrincipal** aPrincipal) override; 112 NS_IMETHOD GetTopLevelPrincipal(nsIPrincipal** aTopLevelPrincipal) override; 113 NS_IMETHOD GetWindow(mozIDOMWindow** aWindow) override; 114 NS_IMETHOD GetElement(mozilla::dom::Element** aElement) override; 115 NS_IMETHOD GetHasValidTransientUserGestureActivation( 116 bool* aHasValidTransientUserGestureActivation) override; 117 NS_IMETHOD GetIsRequestDelegatedToUnsafeThirdParty( 118 bool* aIsRequestDelegatedToUnsafeThirdParty) override; 119 // Overrides for Allow() and Cancel() aren't provided by this class. 120 // That is the responsibility of the subclasses. 121 122 enum class PromptResult { 123 Granted, 124 Denied, 125 Pending, 126 }; 127 nsresult ShowPrompt(PromptResult& aResult); 128 129 PromptResult CheckPromptPrefs() const; 130 131 // Check if the permission has an opportunity to request. 132 bool CheckPermissionDelegate() const; 133 134 enum class DelayedTaskType { 135 Allow, 136 Deny, 137 Request, 138 }; 139 void RequestDelayedTask(nsIEventTarget* aTarget, DelayedTaskType aType); 140 141 protected: 142 // @param aPrefName see `mPrefName`. 143 // @param aType see `mType`. 144 ContentPermissionRequestBase(nsIPrincipal* aPrincipal, 145 nsPIDOMWindowInner* aWindow, 146 const nsACString& aPrefName, 147 const nsACString& aType); 148 virtual ~ContentPermissionRequestBase() = default; 149 150 nsCOMPtr<nsIPrincipal> mPrincipal; 151 nsCOMPtr<nsIPrincipal> mTopLevelPrincipal; 152 nsCOMPtr<nsPIDOMWindowInner> mWindow; 153 RefPtr<PermissionDelegateHandler> mPermissionHandler; 154 155 // The prefix of a pref which allows tests to bypass showing the prompt. 156 // Tests will have to set both of 157 // ${mPrefName}.prompt.testing and 158 // ${mPrefName}.prompt.testing.allow 159 // to either true or false. If no such testing is required, mPrefName may be 160 // empty. 161 const nsCString mPrefName; 162 163 // The type of the request, such as "autoplay-media-audible". 164 const nsCString mType; 165 166 bool mHasValidTransientUserGestureActivation; 167 168 // See nsIPermissionDelegateHandler.maybeUnsafePermissionDelegate`. 169 bool mIsRequestDelegatedToUnsafeThirdParty; 170 }; 171 172 } // namespace dom 173 } // namespace mozilla 174 175 using mozilla::dom::ContentPermissionRequestParent; 176 177 class nsContentPermissionRequestProxy : public nsIContentPermissionRequest { 178 public: 179 NS_DECL_ISUPPORTS 180 NS_DECL_NSICONTENTPERMISSIONREQUEST 181 182 explicit nsContentPermissionRequestProxy( 183 ContentPermissionRequestParent* parent); 184 185 nsresult Init(const nsTArray<mozilla::dom::PermissionRequest>& requests); 186 187 void OnParentDestroyed(); 188 189 private: 190 virtual ~nsContentPermissionRequestProxy(); 191 192 // Non-owning pointer to the ContentPermissionRequestParent object which owns 193 // this proxy. 194 ContentPermissionRequestParent* mParent; 195 nsTArray<mozilla::dom::PermissionRequest> mPermissionRequests; 196 }; 197 198 /** 199 * RemotePermissionRequest will send a prompt ipdl request to the chrome process 200 * (https://wiki.mozilla.org/Security/Sandbox/Process_model#Chrome_process_.28Parent.29). 201 */ 202 class RemotePermissionRequest final 203 : public mozilla::dom::PContentPermissionRequestChild { 204 public: 205 NS_INLINE_DECL_REFCOUNTING(RemotePermissionRequest) 206 207 RemotePermissionRequest(nsIContentPermissionRequest* aRequest, 208 nsPIDOMWindowInner* aWindow); 209 210 // It will be called when prompt dismissed. MOZ_CAN_RUN_SCRIPT_BOUNDARY 211 // because we don't have MOZ_CAN_RUN_SCRIPT bits in IPC code yet. 212 MOZ_CAN_RUN_SCRIPT_BOUNDARY 213 mozilla::ipc::IPCResult RecvNotifyResult( 214 const bool& aAllow, nsTArray<PermissionChoice>&& aChoices); 215 IPDLAddRef()216 void IPDLAddRef() { 217 mIPCOpen = true; 218 AddRef(); 219 } 220 IPDLRelease()221 void IPDLRelease() { 222 mIPCOpen = false; 223 Release(); 224 } 225 226 void Destroy(); 227 IPCOpen()228 bool IPCOpen() const { return mIPCOpen && !mDestroyed; } 229 230 private: 231 virtual ~RemotePermissionRequest(); 232 233 MOZ_CAN_RUN_SCRIPT 234 void DoAllow(JS::HandleValue aChoices); 235 MOZ_CAN_RUN_SCRIPT 236 void DoCancel(); 237 238 nsCOMPtr<nsIContentPermissionRequest> mRequest; 239 nsCOMPtr<nsPIDOMWindowInner> mWindow; 240 bool mIPCOpen; 241 bool mDestroyed; 242 }; 243 244 #endif // nsContentPermissionHelper_h 245