dom/camera/DOMCameraManager.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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 file,
     3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "DOMCameraManager.h"
     6 #include "nsDebug.h"
     7 #include "jsapi.h"
     8 #include "Navigator.h"
     9 #include "nsPIDOMWindow.h"
    10 #include "mozilla/Services.h"
    11 #include "nsContentPermissionHelper.h"
    12 #include "nsIObserverService.h"
    13 #include "nsIPermissionManager.h"
    14 #include "DOMCameraControl.h"
    15 #include "nsDOMClassInfo.h"
    16 #include "CameraCommon.h"
    17 #include "mozilla/dom/BindingUtils.h"
    18 #include "mozilla/dom/CameraManagerBinding.h"
    19 #include "mozilla/dom/PermissionMessageUtils.h"
    20 #include "mozilla/dom/TabChild.h"
    21 #include "PCOMContentPermissionRequestChild.h"
    23 using namespace mozilla;
    24 using namespace mozilla::dom;
    26 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(nsDOMCameraManager, mWindow)
    28 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMCameraManager)
    29   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
    30   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
    31   NS_INTERFACE_MAP_ENTRY(nsIObserver)
    32   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
    33 NS_INTERFACE_MAP_END
    35 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMCameraManager)
    36 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMCameraManager)
    38 /**
    39  * Global camera logging object
    40  *
    41  * Set the NSPR_LOG_MODULES environment variable to enable logging
    42  * in a debug build, e.g. NSPR_LOG_MODULES=Camera:5
    43  */
    44 PRLogModuleInfo*
    45 GetCameraLog()
    46 {
    47   static PRLogModuleInfo *sLog;
    48   if (!sLog) {
    49     sLog = PR_NewLogModule("Camera");
    50   }
    51   return sLog;
    52 }
    54 WindowTable* nsDOMCameraManager::sActiveWindows = nullptr;
    56 nsDOMCameraManager::nsDOMCameraManager(nsPIDOMWindow* aWindow)
    57   : mWindowId(aWindow->WindowID())
    58   , mPermission(nsIPermissionManager::DENY_ACTION)
    59   , mWindow(aWindow)
    60 {
    61   /* member initializers and constructor code */
    62   DOM_CAMERA_LOGT("%s:%d : this=%p, windowId=%llx\n", __func__, __LINE__, this, mWindowId);
    63   MOZ_COUNT_CTOR(nsDOMCameraManager);
    64   SetIsDOMBinding();
    65 }
    67 nsDOMCameraManager::~nsDOMCameraManager()
    68 {
    69   /* destructor code */
    70   MOZ_COUNT_DTOR(nsDOMCameraManager);
    71   DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
    72 }
    74 /* static */
    75 void
    76 nsDOMCameraManager::GetListOfCameras(nsTArray<nsString>& aList, ErrorResult& aRv)
    77 {
    78   aRv = ICameraControl::GetListOfCameras(aList);
    79 }
    81 /* static */
    82 bool
    83 nsDOMCameraManager::HasSupport(JSContext* aCx, JSObject* aGlobal)
    84 {
    85   return Navigator::HasCameraSupport(aCx, aGlobal);
    86 }
    88 /* static */
    89 bool
    90 nsDOMCameraManager::CheckPermission(nsPIDOMWindow* aWindow)
    91 {
    92   nsCOMPtr<nsIPermissionManager> permMgr =
    93     do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
    94   NS_ENSURE_TRUE(permMgr, false);
    96   uint32_t permission = nsIPermissionManager::DENY_ACTION;
    97   permMgr->TestPermissionFromWindow(aWindow, "camera", &permission);
    98   if (permission != nsIPermissionManager::ALLOW_ACTION &&
    99       permission != nsIPermissionManager::PROMPT_ACTION) {
   100     return false;
   101   }
   103   return true;
   104 }
   106 /* static */
   107 already_AddRefed<nsDOMCameraManager>
   108 nsDOMCameraManager::CreateInstance(nsPIDOMWindow* aWindow)
   109 {
   110   // Initialize the shared active window tracker
   111   if (!sActiveWindows) {
   112     sActiveWindows = new WindowTable();
   113   }
   115   nsRefPtr<nsDOMCameraManager> cameraManager =
   116     new nsDOMCameraManager(aWindow);
   118   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   119   obs->AddObserver(cameraManager, "xpcom-shutdown", true);
   121   return cameraManager.forget();
   122 }
   124 class CameraPermissionRequest : public nsIContentPermissionRequest
   125                               , public PCOMContentPermissionRequestChild
   126                               , public nsIRunnable
   127 {
   128 public:
   129   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   130   NS_DECL_NSICONTENTPERMISSIONREQUEST
   131   NS_DECL_NSIRUNNABLE
   132   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(CameraPermissionRequest,
   133                                            nsIContentPermissionRequest)
   135   CameraPermissionRequest(nsIPrincipal* aPrincipal,
   136                           nsPIDOMWindow* aWindow,
   137                           nsRefPtr<nsDOMCameraManager> aManager,
   138                           uint32_t aCameraId,
   139                           const CameraConfiguration& aInitialConfig,
   140                           nsRefPtr<GetCameraCallback> aOnSuccess,
   141                           nsRefPtr<CameraErrorCallback> aOnError)
   142     : mPrincipal(aPrincipal)
   143     , mWindow(aWindow)
   144     , mCameraManager(aManager)
   145     , mCameraId(aCameraId)
   146     , mInitialConfig(aInitialConfig)
   147     , mOnSuccess(aOnSuccess)
   148     , mOnError(aOnError)
   149   {
   150   }
   152   virtual ~CameraPermissionRequest()
   153   {
   154   }
   156   bool Recv__delete__(const bool& aAllow,
   157                       const InfallibleTArray<PermissionChoice>& choices);
   159   void IPDLRelease()
   160   {
   161     Release();
   162   }
   164 protected:
   165   nsresult DispatchCallback(uint32_t aPermission);
   166   void CallAllow();
   167   void CallCancel();
   168   nsCOMPtr<nsIPrincipal> mPrincipal;
   169   nsCOMPtr<nsPIDOMWindow> mWindow;
   170   nsRefPtr<nsDOMCameraManager> mCameraManager;
   171   uint32_t mCameraId;
   172   CameraConfiguration mInitialConfig;
   173   nsRefPtr<GetCameraCallback> mOnSuccess;
   174   nsRefPtr<CameraErrorCallback> mOnError;
   175 };
   177 NS_IMPL_CYCLE_COLLECTION(CameraPermissionRequest, mWindow, mOnSuccess, mOnError)
   179 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CameraPermissionRequest)
   180   NS_INTERFACE_MAP_ENTRY(nsIContentPermissionRequest)
   181   NS_INTERFACE_MAP_ENTRY(nsIRunnable)
   182   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentPermissionRequest)
   183 NS_INTERFACE_MAP_END
   185 NS_IMPL_CYCLE_COLLECTING_ADDREF(CameraPermissionRequest)
   186 NS_IMPL_CYCLE_COLLECTING_RELEASE(CameraPermissionRequest)
   188 NS_IMETHODIMP
   189 CameraPermissionRequest::Run()
   190 {
   191   if (XRE_GetProcessType() == GeckoProcessType_Content) {
   192     TabChild* child = TabChild::GetFrom(mWindow->GetDocShell());
   193     if (!child) {
   194       return NS_ERROR_NOT_AVAILABLE;
   195     }
   197     // Retain a reference so the object isn't deleted without IPDL's knowledge.
   198     // Corresponding release occurs in DeallocPContentPermissionRequest.
   199     AddRef();
   201     nsTArray<PermissionRequest> permArray;
   202     nsTArray<nsString> emptyOptions;
   203     permArray.AppendElement(PermissionRequest(
   204                             NS_LITERAL_CSTRING("camera"),
   205                             NS_LITERAL_CSTRING("unused"),
   206                             emptyOptions));
   207     child->SendPContentPermissionRequestConstructor(this, permArray,
   208                                                     IPC::Principal(mPrincipal));
   210     Sendprompt();
   211     return NS_OK;
   212   }
   214   nsCOMPtr<nsIContentPermissionPrompt> prompt =
   215     do_GetService(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
   216   if (prompt) {
   217     prompt->Prompt(this);
   218   }
   220   return NS_OK;
   221 }
   223 bool
   224 CameraPermissionRequest::Recv__delete__(const bool& aAllow,
   225                                         const InfallibleTArray<PermissionChoice>& choices)
   226 {
   227   if (aAllow) {
   228     Allow(JS::UndefinedHandleValue);
   229   } else {
   230     Cancel();
   231   }
   232   return true;
   233 }
   235 NS_IMETHODIMP
   236 CameraPermissionRequest::GetPrincipal(nsIPrincipal** aRequestingPrincipal)
   237 {
   238   NS_ADDREF(*aRequestingPrincipal = mPrincipal);
   239   return NS_OK;
   240 }
   242 NS_IMETHODIMP
   243 CameraPermissionRequest::GetWindow(nsIDOMWindow** aRequestingWindow)
   244 {
   245   NS_ADDREF(*aRequestingWindow = mWindow);
   246   return NS_OK;
   247 }
   249 NS_IMETHODIMP
   250 CameraPermissionRequest::GetElement(nsIDOMElement** aElement)
   251 {
   252   *aElement = nullptr;
   253   return NS_OK;
   254 }
   256 NS_IMETHODIMP
   257 CameraPermissionRequest::Cancel()
   258 {
   259   return DispatchCallback(nsIPermissionManager::DENY_ACTION);
   260 }
   262 NS_IMETHODIMP
   263 CameraPermissionRequest::Allow(JS::HandleValue aChoices)
   264 {
   265   MOZ_ASSERT(aChoices.isUndefined());
   266   return DispatchCallback(nsIPermissionManager::ALLOW_ACTION);
   267 }
   269 nsresult
   270 CameraPermissionRequest::DispatchCallback(uint32_t aPermission)
   271 {
   272   nsCOMPtr<nsIRunnable> callbackRunnable;
   273   if (aPermission == nsIPermissionManager::ALLOW_ACTION) {
   274     callbackRunnable = NS_NewRunnableMethod(this, &CameraPermissionRequest::CallAllow);
   275   } else {
   276     callbackRunnable = NS_NewRunnableMethod(this, &CameraPermissionRequest::CallCancel);
   277   }
   278   return NS_DispatchToMainThread(callbackRunnable);
   279 }
   281 void
   282 CameraPermissionRequest::CallAllow()
   283 {
   284   mCameraManager->PermissionAllowed(mCameraId, mInitialConfig, mOnSuccess, mOnError);
   285 }
   287 void
   288 CameraPermissionRequest::CallCancel()
   289 {
   290   mCameraManager->PermissionCancelled(mCameraId, mInitialConfig, mOnSuccess, mOnError);
   291 }
   293 NS_IMETHODIMP
   294 CameraPermissionRequest::GetTypes(nsIArray** aTypes)
   295 {
   296   nsTArray<nsString> emptyOptions;
   297   return CreatePermissionArray(NS_LITERAL_CSTRING("camera"),
   298                                NS_LITERAL_CSTRING("unused"),
   299                                emptyOptions,
   300                                aTypes);
   301 }
   303 void
   304 nsDOMCameraManager::GetCamera(const nsAString& aCamera,
   305                               const CameraConfiguration& aInitialConfig,
   306                               GetCameraCallback& aOnSuccess,
   307                               const OptionalNonNullCameraErrorCallback& aOnError,
   308                               ErrorResult& aRv)
   309 {
   310   DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
   312   uint32_t cameraId = 0;  // back (or forward-facing) camera by default
   313   if (aCamera.EqualsLiteral("front")) {
   314     cameraId = 1;
   315   }
   317   nsRefPtr<CameraErrorCallback> errorCallback = nullptr;
   318   if (aOnError.WasPassed()) {
   319     errorCallback = &aOnError.Value();
   320   }
   322   if (mPermission == nsIPermissionManager::ALLOW_ACTION) {
   323     PermissionAllowed(cameraId, aInitialConfig, &aOnSuccess, errorCallback);
   324     return;
   325   }
   327   nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(mWindow);
   328   if (!sop) {
   329     aRv.Throw(NS_ERROR_UNEXPECTED);
   330     return;
   331   }
   333   nsCOMPtr<nsIPrincipal> principal = sop->GetPrincipal();
   335   nsCOMPtr<nsIRunnable> permissionRequest =
   336     new CameraPermissionRequest(principal, mWindow, this, cameraId, aInitialConfig,
   337                                 &aOnSuccess, errorCallback);
   339   NS_DispatchToMainThread(permissionRequest);
   340 }
   342 void
   343 nsDOMCameraManager::PermissionAllowed(uint32_t aCameraId,
   344                                       const CameraConfiguration& aInitialConfig,
   345                                       GetCameraCallback* aOnSuccess,
   346                                       CameraErrorCallback* aOnError)
   347 {
   348   mPermission = nsIPermissionManager::ALLOW_ACTION;
   350   // Creating this object will trigger the aOnSuccess callback
   351   //  (or the aOnError one, if it fails).
   352   nsRefPtr<nsDOMCameraControl> cameraControl =
   353     new nsDOMCameraControl(aCameraId, aInitialConfig, aOnSuccess, aOnError, mWindow);
   355   Register(cameraControl);
   356 }
   358 void
   359 nsDOMCameraManager::PermissionCancelled(uint32_t aCameraId,
   360                                         const CameraConfiguration& aInitialConfig,
   361                                         GetCameraCallback* aOnSuccess,
   362                                         CameraErrorCallback* aOnError)
   363 {
   364   mPermission = nsIPermissionManager::DENY_ACTION;
   366   if (aOnError) {
   367     ErrorResult ignored;
   368     aOnError->Call(NS_LITERAL_STRING("Permission denied."), ignored);
   369   }
   370 }
   372 void
   373 nsDOMCameraManager::Register(nsDOMCameraControl* aDOMCameraControl)
   374 {
   375   DOM_CAMERA_LOGI(">>> Register( aDOMCameraControl = %p ) mWindowId = 0x%llx\n", aDOMCameraControl, mWindowId);
   376   MOZ_ASSERT(NS_IsMainThread());
   378   // Put the camera control into the hash table
   379   CameraControls* controls = sActiveWindows->Get(mWindowId);
   380   if (!controls) {
   381     controls = new CameraControls;
   382     sActiveWindows->Put(mWindowId, controls);
   383   }
   384   controls->AppendElement(aDOMCameraControl);
   385 }
   387 void
   388 nsDOMCameraManager::Shutdown(uint64_t aWindowId)
   389 {
   390   DOM_CAMERA_LOGI(">>> Shutdown( aWindowId = 0x%llx )\n", aWindowId);
   391   MOZ_ASSERT(NS_IsMainThread());
   393   CameraControls* controls = sActiveWindows->Get(aWindowId);
   394   if (!controls) {
   395     return;
   396   }
   398   uint32_t length = controls->Length();
   399   for (uint32_t i = 0; i < length; i++) {
   400     nsRefPtr<nsDOMCameraControl> cameraControl = controls->ElementAt(i);
   401     cameraControl->Shutdown();
   402   }
   403   controls->Clear();
   405   sActiveWindows->Remove(aWindowId);
   406 }
   408 void
   409 nsDOMCameraManager::XpComShutdown()
   410 {
   411   DOM_CAMERA_LOGI(">>> XPCOM Shutdown\n");
   412   MOZ_ASSERT(NS_IsMainThread());
   414   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   415   obs->RemoveObserver(this, "xpcom-shutdown");
   417   delete sActiveWindows;
   418   sActiveWindows = nullptr;
   419 }
   421 nsresult
   422 nsDOMCameraManager::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
   423 {
   424   if (strcmp(aTopic, "xpcom-shutdown") == 0) {
   425     XpComShutdown();
   426   }
   427   return NS_OK;
   428 }
   430 void
   431 nsDOMCameraManager::OnNavigation(uint64_t aWindowId)
   432 {
   433   DOM_CAMERA_LOGI(">>> OnNavigation event\n");
   434   Shutdown(aWindowId);
   435 }
   437 bool
   438 nsDOMCameraManager::IsWindowStillActive(uint64_t aWindowId)
   439 {
   440   MOZ_ASSERT(NS_IsMainThread());
   442   if (!sActiveWindows) {
   443     return false;
   444   }
   446   return !!sActiveWindows->Get(aWindowId);
   447 }
   449 JSObject*
   450 nsDOMCameraManager::WrapObject(JSContext* aCx)
   451 {
   452   return CameraManagerBinding::Wrap(aCx, this);
   453 }

mercurial