tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

StorageAccessPermissionRequest.cpp (5716B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
      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 #include "StorageAccessPermissionRequest.h"
      8 
      9 #include <cstdlib>
     10 
     11 #include "mozilla/StaticPrefs_dom.h"
     12 #include "nsGlobalWindowInner.h"
     13 
     14 namespace mozilla::dom {
     15 
     16 NS_IMPL_CYCLE_COLLECTION_INHERITED(StorageAccessPermissionRequest,
     17                                   ContentPermissionRequestBase)
     18 
     19 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(StorageAccessPermissionRequest,
     20                                               ContentPermissionRequestBase)
     21 
     22 StorageAccessPermissionRequest::StorageAccessPermissionRequest(
     23    nsPIDOMWindowInner* aWindow, nsIPrincipal* aNodePrincipal,
     24    const Maybe<nsCString>& aTopLevelBaseDomain, bool aFrameOnly,
     25    AllowCallback&& aAllowCallback, CancelCallback&& aCancelCallback)
     26    : ContentPermissionRequestBase(aNodePrincipal, aWindow,
     27                                   "dom.storage_access"_ns,
     28                                   "storage-access"_ns),
     29      mAllowCallback(std::move(aAllowCallback)),
     30      mCancelCallback(std::move(aCancelCallback)),
     31      mCallbackCalled(false) {
     32  mOptions.SetLength(2);
     33  if (aTopLevelBaseDomain.isSome()) {
     34    nsCString option = aTopLevelBaseDomain.value();
     35    mOptions.ElementAt(0) = NS_ConvertUTF8toUTF16(option);
     36  }
     37  if (aFrameOnly) {
     38    mOptions.ElementAt(1) = u"1"_ns;
     39  }
     40  mPermissionRequests.AppendElement(PermissionRequest(mType, mOptions));
     41 }
     42 
     43 NS_IMETHODIMP
     44 StorageAccessPermissionRequest::Cancel() {
     45  if (!mCallbackCalled) {
     46    mCallbackCalled = true;
     47    mCancelCallback();
     48  }
     49  return NS_OK;
     50 }
     51 
     52 NS_IMETHODIMP
     53 StorageAccessPermissionRequest::Allow(JS::Handle<JS::Value> aChoices) {
     54  nsTArray<PermissionChoice> choices;
     55  nsresult rv = TranslateChoices(aChoices, mPermissionRequests, choices);
     56  if (NS_FAILED(rv)) {
     57    return rv;
     58  }
     59 
     60  // There is no support to allow grants automatically from the prompting code
     61  // path.
     62 
     63  if (!mCallbackCalled) {
     64    mCallbackCalled = true;
     65    if (choices.Length() == 1 && choices[0].choice().EqualsLiteral("allow")) {
     66      mAllowCallback();
     67    }
     68  }
     69  return NS_OK;
     70 }
     71 
     72 NS_IMETHODIMP
     73 StorageAccessPermissionRequest::GetTypes(nsIArray** aTypes) {
     74  return nsContentPermissionUtils::CreatePermissionArray(mType, mOptions,
     75                                                         aTypes);
     76 }
     77 
     78 RefPtr<StorageAccessPermissionRequest::AutoGrantDelayPromise>
     79 StorageAccessPermissionRequest::MaybeDelayAutomaticGrants() {
     80  RefPtr<AutoGrantDelayPromise::Private> p =
     81      new AutoGrantDelayPromise::Private(__func__);
     82 
     83  unsigned simulatedDelay = CalculateSimulatedDelay();
     84  if (simulatedDelay) {
     85    nsCOMPtr<nsITimer> timer;
     86    RefPtr<AutoGrantDelayPromise::Private> promise = p;
     87    nsresult rv = NS_NewTimerWithFuncCallback(
     88        getter_AddRefs(timer),
     89        [](nsITimer* aTimer, void* aClosure) -> void {
     90          auto* promise =
     91              static_cast<AutoGrantDelayPromise::Private*>(aClosure);
     92          promise->Resolve(true, __func__);
     93          NS_RELEASE(aTimer);
     94          NS_RELEASE(promise);
     95        },
     96        promise, simulatedDelay, nsITimer::TYPE_ONE_SHOT,
     97        "DelayedAllowAutoGrantCallback"_ns);
     98    if (NS_WARN_IF(NS_FAILED(rv))) {
     99      p->Reject(false, __func__);
    100    } else {
    101      // Leak the references here! We'll release them inside the callback.
    102      timer.forget().leak();
    103      promise.forget().leak();
    104    }
    105  } else {
    106    p->Resolve(false, __func__);
    107  }
    108  return p;
    109 }
    110 
    111 already_AddRefed<StorageAccessPermissionRequest>
    112 StorageAccessPermissionRequest::Create(nsPIDOMWindowInner* aWindow,
    113                                       AllowCallback&& aAllowCallback,
    114                                       CancelCallback&& aCancelCallback) {
    115  if (!aWindow) {
    116    return nullptr;
    117  }
    118  nsGlobalWindowInner* win = nsGlobalWindowInner::Cast(aWindow);
    119 
    120  return Create(aWindow, win->GetPrincipal(), std::move(aAllowCallback),
    121                std::move(aCancelCallback));
    122 }
    123 
    124 already_AddRefed<StorageAccessPermissionRequest>
    125 StorageAccessPermissionRequest::Create(nsPIDOMWindowInner* aWindow,
    126                                       nsIPrincipal* aPrincipal,
    127                                       AllowCallback&& aAllowCallback,
    128                                       CancelCallback&& aCancelCallback) {
    129  return Create(aWindow, aPrincipal, Nothing(), true, std::move(aAllowCallback),
    130                std::move(aCancelCallback));
    131 }
    132 
    133 already_AddRefed<StorageAccessPermissionRequest>
    134 StorageAccessPermissionRequest::Create(
    135    nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal,
    136    const Maybe<nsCString>& aTopLevelBaseDomain, bool aFrameOnly,
    137    AllowCallback&& aAllowCallback, CancelCallback&& aCancelCallback) {
    138  if (!aWindow) {
    139    return nullptr;
    140  }
    141 
    142  if (!aPrincipal) {
    143    return nullptr;
    144  }
    145 
    146  RefPtr<StorageAccessPermissionRequest> request =
    147      new StorageAccessPermissionRequest(
    148          aWindow, aPrincipal, aTopLevelBaseDomain, aFrameOnly,
    149          std::move(aAllowCallback), std::move(aCancelCallback));
    150  return request.forget();
    151 }
    152 
    153 unsigned StorageAccessPermissionRequest::CalculateSimulatedDelay() {
    154  if (!StaticPrefs::dom_storage_access_auto_grants_delayed()) {
    155    return 0;
    156  }
    157 
    158  // Generate a random time value that is at least 0 and and most 3 seconds.
    159  std::srand(static_cast<unsigned>(PR_Now()));
    160 
    161  const unsigned kMin = 0;
    162  const unsigned kMax = 3000;
    163  const unsigned random = std::abs(std::rand());
    164 
    165  return kMin + random % (kMax - kMin);
    166 }
    167 
    168 }  // namespace mozilla::dom