dom/base/nsContentPermissionHelper.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial