dom/base/nsContentPermissionHelper.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 #ifdef MOZ_WIDGET_GONK
michael@0 6 #include "GonkPermission.h"
michael@0 7 #include "mozilla/dom/ContentParent.h"
michael@0 8 #endif // MOZ_WIDGET_GONK
michael@0 9 #include "nsCOMPtr.h"
michael@0 10 #include "nsIDOMElement.h"
michael@0 11 #include "nsIPrincipal.h"
michael@0 12 #include "mozilla/dom/Element.h"
michael@0 13 #include "mozilla/dom/PContentPermission.h"
michael@0 14 #include "mozilla/dom/PermissionMessageUtils.h"
michael@0 15 #include "mozilla/dom/PContentPermissionRequestParent.h"
michael@0 16 #include "mozilla/dom/TabParent.h"
michael@0 17 #include "mozilla/unused.h"
michael@0 18 #include "nsComponentManagerUtils.h"
michael@0 19 #include "nsArrayUtils.h"
michael@0 20 #include "nsIMutableArray.h"
michael@0 21 #include "nsContentPermissionHelper.h"
michael@0 22 #include "nsCxPusher.h"
michael@0 23 #include "nsJSUtils.h"
michael@0 24 #include "nsISupportsPrimitives.h"
michael@0 25
michael@0 26 using mozilla::unused; // <snicker>
michael@0 27 using namespace mozilla::dom;
michael@0 28 using namespace mozilla;
michael@0 29
michael@0 30 namespace mozilla {
michael@0 31 namespace dom {
michael@0 32
michael@0 33 class ContentPermissionRequestParent : public PContentPermissionRequestParent
michael@0 34 {
michael@0 35 public:
michael@0 36 ContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequests,
michael@0 37 Element* element,
michael@0 38 const IPC::Principal& principal);
michael@0 39 virtual ~ContentPermissionRequestParent();
michael@0 40
michael@0 41 bool IsBeingDestroyed();
michael@0 42
michael@0 43 nsCOMPtr<nsIPrincipal> mPrincipal;
michael@0 44 nsCOMPtr<Element> mElement;
michael@0 45 nsRefPtr<nsContentPermissionRequestProxy> mProxy;
michael@0 46 nsTArray<PermissionRequest> mRequests;
michael@0 47
michael@0 48 private:
michael@0 49 virtual bool Recvprompt();
michael@0 50 virtual void ActorDestroy(ActorDestroyReason why);
michael@0 51 };
michael@0 52
michael@0 53 ContentPermissionRequestParent::ContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequests,
michael@0 54 Element* aElement,
michael@0 55 const IPC::Principal& aPrincipal)
michael@0 56 {
michael@0 57 MOZ_COUNT_CTOR(ContentPermissionRequestParent);
michael@0 58
michael@0 59 mPrincipal = aPrincipal;
michael@0 60 mElement = aElement;
michael@0 61 mRequests = aRequests;
michael@0 62 }
michael@0 63
michael@0 64 ContentPermissionRequestParent::~ContentPermissionRequestParent()
michael@0 65 {
michael@0 66 MOZ_COUNT_DTOR(ContentPermissionRequestParent);
michael@0 67 }
michael@0 68
michael@0 69 bool
michael@0 70 ContentPermissionRequestParent::Recvprompt()
michael@0 71 {
michael@0 72 mProxy = new nsContentPermissionRequestProxy();
michael@0 73 NS_ASSERTION(mProxy, "Alloc of request proxy failed");
michael@0 74 if (NS_FAILED(mProxy->Init(mRequests, this))) {
michael@0 75 mProxy->Cancel();
michael@0 76 }
michael@0 77 return true;
michael@0 78 }
michael@0 79
michael@0 80 void
michael@0 81 ContentPermissionRequestParent::ActorDestroy(ActorDestroyReason why)
michael@0 82 {
michael@0 83 if (mProxy) {
michael@0 84 mProxy->OnParentDestroyed();
michael@0 85 }
michael@0 86 }
michael@0 87
michael@0 88 bool
michael@0 89 ContentPermissionRequestParent::IsBeingDestroyed()
michael@0 90 {
michael@0 91 // When TabParent::Destroy() is called, we are being destroyed. It's unsafe
michael@0 92 // to send out any message now.
michael@0 93 TabParent* tabParent = static_cast<TabParent*>(Manager());
michael@0 94 return tabParent->IsDestroyed();
michael@0 95 }
michael@0 96
michael@0 97 NS_IMPL_ISUPPORTS(ContentPermissionType, nsIContentPermissionType)
michael@0 98
michael@0 99 ContentPermissionType::ContentPermissionType(const nsACString& aType,
michael@0 100 const nsACString& aAccess,
michael@0 101 const nsTArray<nsString>& aOptions)
michael@0 102 {
michael@0 103 mType = aType;
michael@0 104 mAccess = aAccess;
michael@0 105 mOptions = aOptions;
michael@0 106 }
michael@0 107
michael@0 108 ContentPermissionType::~ContentPermissionType()
michael@0 109 {
michael@0 110 }
michael@0 111
michael@0 112 NS_IMETHODIMP
michael@0 113 ContentPermissionType::GetType(nsACString& aType)
michael@0 114 {
michael@0 115 aType = mType;
michael@0 116 return NS_OK;
michael@0 117 }
michael@0 118
michael@0 119 NS_IMETHODIMP
michael@0 120 ContentPermissionType::GetAccess(nsACString& aAccess)
michael@0 121 {
michael@0 122 aAccess = mAccess;
michael@0 123 return NS_OK;
michael@0 124 }
michael@0 125
michael@0 126 NS_IMETHODIMP
michael@0 127 ContentPermissionType::GetOptions(nsIArray** aOptions)
michael@0 128 {
michael@0 129 NS_ENSURE_ARG_POINTER(aOptions);
michael@0 130
michael@0 131 *aOptions = nullptr;
michael@0 132
michael@0 133 nsresult rv;
michael@0 134 nsCOMPtr<nsIMutableArray> options =
michael@0 135 do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
michael@0 136 NS_ENSURE_SUCCESS(rv, rv);
michael@0 137
michael@0 138 // copy options into JS array
michael@0 139 for (uint32_t i = 0; i < mOptions.Length(); ++i) {
michael@0 140 nsCOMPtr<nsISupportsString> isupportsString =
michael@0 141 do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
michael@0 142 NS_ENSURE_SUCCESS(rv, rv);
michael@0 143
michael@0 144 rv = isupportsString->SetData(mOptions[i]);
michael@0 145 NS_ENSURE_SUCCESS(rv, rv);
michael@0 146
michael@0 147 rv = options->AppendElement(isupportsString, false);
michael@0 148 NS_ENSURE_SUCCESS(rv, rv);
michael@0 149 }
michael@0 150
michael@0 151 NS_ADDREF(*aOptions = options);
michael@0 152 return NS_OK;
michael@0 153 }
michael@0 154
michael@0 155 uint32_t
michael@0 156 ConvertPermissionRequestToArray(nsTArray<PermissionRequest>& aSrcArray,
michael@0 157 nsIMutableArray* aDesArray)
michael@0 158 {
michael@0 159 uint32_t len = aSrcArray.Length();
michael@0 160 for (uint32_t i = 0; i < len; i++) {
michael@0 161 nsRefPtr<ContentPermissionType> cpt =
michael@0 162 new ContentPermissionType(aSrcArray[i].type(),
michael@0 163 aSrcArray[i].access(),
michael@0 164 aSrcArray[i].options());
michael@0 165 aDesArray->AppendElement(cpt, false);
michael@0 166 }
michael@0 167 return len;
michael@0 168 }
michael@0 169
michael@0 170 nsresult
michael@0 171 CreatePermissionArray(const nsACString& aType,
michael@0 172 const nsACString& aAccess,
michael@0 173 const nsTArray<nsString>& aOptions,
michael@0 174 nsIArray** aTypesArray)
michael@0 175 {
michael@0 176 nsCOMPtr<nsIMutableArray> types = do_CreateInstance(NS_ARRAY_CONTRACTID);
michael@0 177 nsRefPtr<ContentPermissionType> permType = new ContentPermissionType(aType,
michael@0 178 aAccess,
michael@0 179 aOptions);
michael@0 180 types->AppendElement(permType, false);
michael@0 181 types.forget(aTypesArray);
michael@0 182
michael@0 183 return NS_OK;
michael@0 184 }
michael@0 185
michael@0 186 PContentPermissionRequestParent*
michael@0 187 CreateContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequests,
michael@0 188 Element* element,
michael@0 189 const IPC::Principal& principal)
michael@0 190 {
michael@0 191 return new ContentPermissionRequestParent(aRequests, element, principal);
michael@0 192 }
michael@0 193
michael@0 194 } // namespace dom
michael@0 195 } // namespace mozilla
michael@0 196
michael@0 197 nsContentPermissionRequestProxy::nsContentPermissionRequestProxy()
michael@0 198 {
michael@0 199 MOZ_COUNT_CTOR(nsContentPermissionRequestProxy);
michael@0 200 }
michael@0 201
michael@0 202 nsContentPermissionRequestProxy::~nsContentPermissionRequestProxy()
michael@0 203 {
michael@0 204 MOZ_COUNT_DTOR(nsContentPermissionRequestProxy);
michael@0 205 }
michael@0 206
michael@0 207 nsresult
michael@0 208 nsContentPermissionRequestProxy::Init(const nsTArray<PermissionRequest>& requests,
michael@0 209 ContentPermissionRequestParent* parent)
michael@0 210 {
michael@0 211 NS_ASSERTION(parent, "null parent");
michael@0 212 mParent = parent;
michael@0 213 mPermissionRequests = requests;
michael@0 214
michael@0 215 nsCOMPtr<nsIContentPermissionPrompt> prompt = do_CreateInstance(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
michael@0 216 if (!prompt) {
michael@0 217 return NS_ERROR_FAILURE;
michael@0 218 }
michael@0 219
michael@0 220 prompt->Prompt(this);
michael@0 221 return NS_OK;
michael@0 222 }
michael@0 223
michael@0 224 void
michael@0 225 nsContentPermissionRequestProxy::OnParentDestroyed()
michael@0 226 {
michael@0 227 mParent = nullptr;
michael@0 228 }
michael@0 229
michael@0 230 NS_IMPL_ISUPPORTS(nsContentPermissionRequestProxy, nsIContentPermissionRequest)
michael@0 231
michael@0 232 NS_IMETHODIMP
michael@0 233 nsContentPermissionRequestProxy::GetTypes(nsIArray** aTypes)
michael@0 234 {
michael@0 235 nsCOMPtr<nsIMutableArray> types = do_CreateInstance(NS_ARRAY_CONTRACTID);
michael@0 236 if (ConvertPermissionRequestToArray(mPermissionRequests, types)) {
michael@0 237 types.forget(aTypes);
michael@0 238 return NS_OK;
michael@0 239 }
michael@0 240 return NS_ERROR_FAILURE;
michael@0 241 }
michael@0 242
michael@0 243 NS_IMETHODIMP
michael@0 244 nsContentPermissionRequestProxy::GetWindow(nsIDOMWindow * *aRequestingWindow)
michael@0 245 {
michael@0 246 NS_ENSURE_ARG_POINTER(aRequestingWindow);
michael@0 247 *aRequestingWindow = nullptr; // ipc doesn't have a window
michael@0 248 return NS_OK;
michael@0 249 }
michael@0 250
michael@0 251 NS_IMETHODIMP
michael@0 252 nsContentPermissionRequestProxy::GetPrincipal(nsIPrincipal * *aRequestingPrincipal)
michael@0 253 {
michael@0 254 NS_ENSURE_ARG_POINTER(aRequestingPrincipal);
michael@0 255 if (mParent == nullptr) {
michael@0 256 return NS_ERROR_FAILURE;
michael@0 257 }
michael@0 258
michael@0 259 NS_ADDREF(*aRequestingPrincipal = mParent->mPrincipal);
michael@0 260 return NS_OK;
michael@0 261 }
michael@0 262
michael@0 263 NS_IMETHODIMP
michael@0 264 nsContentPermissionRequestProxy::GetElement(nsIDOMElement * *aRequestingElement)
michael@0 265 {
michael@0 266 NS_ENSURE_ARG_POINTER(aRequestingElement);
michael@0 267 if (mParent == nullptr) {
michael@0 268 return NS_ERROR_FAILURE;
michael@0 269 }
michael@0 270
michael@0 271 nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(mParent->mElement);
michael@0 272 elem.forget(aRequestingElement);
michael@0 273 return NS_OK;
michael@0 274 }
michael@0 275
michael@0 276 NS_IMETHODIMP
michael@0 277 nsContentPermissionRequestProxy::Cancel()
michael@0 278 {
michael@0 279 if (mParent == nullptr) {
michael@0 280 return NS_ERROR_FAILURE;
michael@0 281 }
michael@0 282
michael@0 283 // Don't send out the delete message when the managing protocol (PBrowser) is
michael@0 284 // being destroyed and PContentPermissionRequest will soon be.
michael@0 285 if (mParent->IsBeingDestroyed()) {
michael@0 286 return NS_ERROR_FAILURE;
michael@0 287 }
michael@0 288
michael@0 289 nsTArray<PermissionChoice> emptyChoices;
michael@0 290
michael@0 291 unused << ContentPermissionRequestParent::Send__delete__(mParent, false, emptyChoices);
michael@0 292 mParent = nullptr;
michael@0 293 return NS_OK;
michael@0 294 }
michael@0 295
michael@0 296 NS_IMETHODIMP
michael@0 297 nsContentPermissionRequestProxy::Allow(JS::HandleValue aChoices)
michael@0 298 {
michael@0 299 if (mParent == nullptr) {
michael@0 300 return NS_ERROR_FAILURE;
michael@0 301 }
michael@0 302
michael@0 303 // Don't send out the delete message when the managing protocol (PBrowser) is
michael@0 304 // being destroyed and PContentPermissionRequest will soon be.
michael@0 305 if (mParent->IsBeingDestroyed()) {
michael@0 306 return NS_ERROR_FAILURE;
michael@0 307 }
michael@0 308
michael@0 309 #ifdef MOZ_WIDGET_GONK
michael@0 310 uint32_t len = mPermissionRequests.Length();
michael@0 311 for (uint32_t i = 0; i < len; i++) {
michael@0 312 if (mPermissionRequests[i].type().Equals("audio-capture")) {
michael@0 313 GonkPermissionService::GetInstance()->addGrantInfo(
michael@0 314 "android.permission.RECORD_AUDIO",
michael@0 315 static_cast<TabParent*>(mParent->Manager())->Manager()->Pid());
michael@0 316 }
michael@0 317 if (mPermissionRequests[i].type().Equals("video-capture")) {
michael@0 318 GonkPermissionService::GetInstance()->addGrantInfo(
michael@0 319 "android.permission.CAMERA",
michael@0 320 static_cast<TabParent*>(mParent->Manager())->Manager()->Pid());
michael@0 321 }
michael@0 322 }
michael@0 323 #endif
michael@0 324
michael@0 325 nsTArray<PermissionChoice> choices;
michael@0 326 if (aChoices.isNullOrUndefined()) {
michael@0 327 // No choice is specified.
michael@0 328 } else if (aChoices.isObject()) {
michael@0 329 // Iterate through all permission types.
michael@0 330 for (uint32_t i = 0; i < mPermissionRequests.Length(); ++i) {
michael@0 331 nsCString type = mPermissionRequests[i].type();
michael@0 332
michael@0 333 mozilla::AutoSafeJSContext cx;
michael@0 334 JS::Rooted<JSObject*> obj(cx, &aChoices.toObject());
michael@0 335 JSAutoCompartment ac(cx, obj);
michael@0 336
michael@0 337 JS::Rooted<JS::Value> val(cx);
michael@0 338
michael@0 339 if (!JS_GetProperty(cx, obj, type.BeginReading(), &val) ||
michael@0 340 !val.isString()) {
michael@0 341 // no setting for the permission type, skip it
michael@0 342 } else {
michael@0 343 nsDependentJSString choice;
michael@0 344 if (!choice.init(cx, val)) {
michael@0 345 return NS_ERROR_FAILURE;
michael@0 346 }
michael@0 347 choices.AppendElement(PermissionChoice(type, choice));
michael@0 348 }
michael@0 349 }
michael@0 350 } else {
michael@0 351 MOZ_ASSERT(false, "SelectedChoices should be undefined or an JS object");
michael@0 352 return NS_ERROR_FAILURE;
michael@0 353 }
michael@0 354
michael@0 355 unused << ContentPermissionRequestParent::Send__delete__(mParent, true, choices);
michael@0 356 mParent = nullptr;
michael@0 357 return NS_OK;
michael@0 358 }

mercurial