tor-browser

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

WebIdentityHandler.cpp (8907B)


      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 #include "mozilla/dom/WebIdentityHandler.h"
      8 
      9 #include "mozilla/dom/IdentityCredential.h"
     10 #include "mozilla/dom/WindowGlobalChild.h"
     11 #include "nsCycleCollectionParticipant.h"
     12 
     13 namespace mozilla::dom {
     14 
     15 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebIdentityHandler)
     16  NS_INTERFACE_MAP_ENTRY(nsISupports)
     17 NS_INTERFACE_MAP_END
     18 
     19 NS_IMPL_CYCLE_COLLECTION(WebIdentityHandler, mWindow, mGetPromise)
     20 
     21 NS_IMPL_CYCLE_COLLECTING_ADDREF(WebIdentityHandler)
     22 NS_IMPL_CYCLE_COLLECTING_RELEASE(WebIdentityHandler)
     23 
     24 WebIdentityHandler::~WebIdentityHandler() {
     25  MOZ_ASSERT(NS_IsMainThread());
     26  if (mActor) {
     27    if (mGetPromise) {
     28      mGetPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
     29      mGetPromise = nullptr;
     30      Unfollow();
     31    }
     32    mActor->SetHandler(nullptr);
     33    mWindow = nullptr;
     34  }
     35 }
     36 
     37 bool WebIdentityHandler::MaybeCreateActor() {
     38  if (mActor) {
     39    return true;
     40  }
     41 
     42  RefPtr<WebIdentityChild> actor = new WebIdentityChild();
     43  WindowGlobalChild* windowGlobalChild = mWindow->GetWindowGlobalChild();
     44 
     45  if (!windowGlobalChild ||
     46      !windowGlobalChild->SendPWebIdentityConstructor(actor)) {
     47    return false;
     48  }
     49 
     50  mActor = actor;
     51  mActor->SetHandler(this);
     52  return true;
     53 }
     54 
     55 void WebIdentityHandler::GetCredential(const CredentialRequestOptions& aOptions,
     56                                       bool aSameOriginWithAncestors,
     57                                       const RefPtr<Promise>& aPromise) {
     58  MOZ_ASSERT(XRE_IsContentProcess());
     59  MOZ_ASSERT(mWindow);
     60  MOZ_ASSERT(aPromise);
     61  MOZ_ASSERT(aOptions.mIdentity.WasPassed());
     62  // Prevent origin confusion by requiring no cross domain iframes
     63  // in this one's ancestry
     64  if (!aSameOriginWithAncestors) {
     65    aPromise->MaybeRejectWithNotAllowedError("Same origin ancestors only.");
     66    return;
     67  }
     68 
     69  if (!mActor) {
     70    aPromise->MaybeRejectWithUnknownError("Unknown failure");
     71    return;
     72  }
     73 
     74  if (mGetPromise) {
     75    aPromise->MaybeRejectWithNotAllowedError(
     76        "Concurrent requests not allowed.");
     77    return;
     78  }
     79  mGetPromise = aPromise;
     80 
     81  RefPtr<WebIdentityHandler> self(this);
     82  mActor
     83      ->SendGetIdentityCredential(
     84          aOptions.mIdentity.Value(), aOptions.mMediation,
     85          mWindow->GetWindowContext() &&
     86              mWindow->GetWindowContext()
     87                  ->HasValidTransientUserGestureActivation())
     88      ->Then(
     89          GetCurrentSerialEventTarget(), __func__,
     90          [self](const WebIdentityChild::GetIdentityCredentialPromise::
     91                     ResolveValueType& aResult) {
     92            if (self->mGetPromise) {
     93              if (aResult.type() ==
     94                  WebIdentityGetCredentialResponse::TIPCIdentityCredential) {
     95                const IPCIdentityCredential& result =
     96                    aResult.get_IPCIdentityCredential();
     97                self->mGetPromise->MaybeResolve(
     98                    new IdentityCredential(self->mWindow, result));
     99                self->mGetPromise = nullptr;
    100                self->Unfollow();
    101              } else {
    102                self->mGetPromise->MaybeRejectWithNetworkError(
    103                    "Failure to gather the credential");
    104                self->mGetPromise = nullptr;
    105                self->Unfollow();
    106              }
    107            }
    108          },
    109          [self](const WebIdentityChild::GetIdentityCredentialPromise::
    110                     RejectValueType& aResult) {
    111            if (self->mGetPromise) {
    112              self->mGetPromise->MaybeRejectWithOperationError("");
    113              self->mGetPromise = nullptr;
    114              self->Unfollow();
    115            }
    116          });
    117 }
    118 
    119 void WebIdentityHandler::PreventSilentAccess(const RefPtr<Promise>& aPromise) {
    120  if (!mActor) {
    121    aPromise->MaybeRejectWithUnknownError("Unknown failure");
    122    return;
    123  }
    124  mActor->SendPreventSilentAccess()->Then(
    125      GetCurrentSerialEventTarget(), __func__,
    126      [aPromise](const WebIdentityChild::PreventSilentAccessPromise::
    127                     ResolveOrRejectValue& unused) {
    128        aPromise->MaybeResolveWithUndefined();
    129      });
    130 }
    131 
    132 void WebIdentityHandler::Disconnect(
    133    const IdentityCredentialDisconnectOptions& aOptions,
    134    const RefPtr<Promise>& aPromise) {
    135  if (!mActor) {
    136    aPromise->MaybeRejectWithUnknownError("Unknown failure");
    137    return;
    138  }
    139  mActor->SendDisconnectIdentityCredential(aOptions)->Then(
    140      GetCurrentSerialEventTarget(), __func__,
    141      [aPromise](nsresult aResult) {
    142        if (aResult == NS_ERROR_DOM_MALFORMED_URI) {
    143          aPromise->MaybeRejectWithInvalidStateError(
    144              "Error parsing the provided URI");
    145        } else if (NS_FAILED(aResult)) {
    146          aPromise->MaybeRejectWithNetworkError(
    147              "Error sending disconnect request");
    148        } else {
    149          aPromise->MaybeResolveWithUndefined();
    150        }
    151      },
    152      [aPromise](mozilla::ipc::ResponseRejectReason aError) {
    153        aPromise->MaybeRejectWithUnknownError("Unknown failure");
    154      });
    155 }
    156 
    157 void WebIdentityHandler::SetLoginStatus(const LoginStatus& aStatus,
    158                                        const RefPtr<Promise>& aPromise) {
    159  const RefPtr<Promise>& promise = aPromise;
    160  if (!mActor) {
    161    promise->MaybeRejectWithUnknownError(
    162        "navigator.login.setStatus had an unexpected internal error");
    163    return;
    164  }
    165  mActor->SendSetLoginStatus(aStatus)->Then(
    166      GetCurrentSerialEventTarget(), __func__,
    167      [promise](const WebIdentityChild::SetLoginStatusPromise::ResolveValueType&
    168                    aResult) {
    169        if (NS_SUCCEEDED(aResult)) {
    170          promise->MaybeResolveWithUndefined();
    171        } else {
    172          promise->MaybeRejectWithUnknownError(
    173              "navigator.login.setStatus had an unexpected internal error");
    174        }
    175      },
    176      [promise](const WebIdentityChild::SetLoginStatusPromise::RejectValueType&
    177                    aResult) {
    178        promise->MaybeRejectWithUnknownError(
    179            "navigator.login.setStatus had an unexpected internal error");
    180      });
    181 }
    182 
    183 RefPtr<MozPromise<nsresult, nsresult, true>>
    184 WebIdentityHandler::ResolveContinuationWindow(
    185    const nsACString& aToken, const IdentityResolveOptions& aOptions) {
    186  if (!mActor) {
    187    return MozPromise<nsresult, nsresult, true>::CreateAndReject(
    188        NS_ERROR_UNEXPECTED, __func__);
    189  }
    190  // Tell the parent process that we want to resolve with a given token and
    191  // options. The main process will infer what popup we are, and find the
    192  // pending promise.
    193  RefPtr<MozPromise<nsresult, nsresult, true>::Private> promise =
    194      new MozPromise<nsresult, nsresult, true>::Private(__func__);
    195  mActor->SendResolveContinuationWindow(aToken, aOptions)
    196      ->Then(
    197          GetCurrentSerialEventTarget(), __func__,
    198          [promise](const WebIdentityChild::ResolveContinuationWindowPromise::
    199                        ResolveValueType& aResult) {
    200            // Only resolve on success
    201            if (NS_SUCCEEDED(aResult)) {
    202              promise->Resolve(aResult, __func__);
    203            } else {
    204              promise->Reject(aResult, __func__);
    205            }
    206          },
    207          [promise](const WebIdentityChild::ResolveContinuationWindowPromise::
    208                        RejectValueType& aResult) {
    209            // Fall back to a not allowed error when IPC fails.
    210            promise->Reject(nsresult::NS_ERROR_DOM_NOT_ALLOWED_ERR, __func__);
    211          });
    212  return promise.forget();
    213 }
    214 
    215 RefPtr<MozPromise<bool, nsresult, true>>
    216 WebIdentityHandler::IsContinuationWindow() {
    217  if (!mActor) {
    218    return MozPromise<bool, nsresult, true>::CreateAndReject(
    219        NS_ERROR_UNEXPECTED, __func__);
    220  }
    221  RefPtr<MozPromise<bool, nsresult, true>::Private> promise =
    222      new MozPromise<bool, nsresult, true>::Private(__func__);
    223  mActor->SendIsActiveContinuationWindow()->Then(
    224      GetCurrentSerialEventTarget(), __func__,
    225      [promise](bool result) { promise->Resolve(result, __func__); },
    226      [promise](mozilla::ipc::ResponseRejectReason reject) {
    227        promise->Resolve(false, __func__);
    228      });
    229  return promise.forget();
    230 }
    231 
    232 void WebIdentityHandler::ActorDestroyed() {
    233  MOZ_ASSERT(NS_IsMainThread());
    234  mActor = nullptr;
    235 }
    236 
    237 void WebIdentityHandler::RunAbortAlgorithm() {
    238  if (!mGetPromise) {
    239    return;
    240  }
    241 
    242  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mWindow);
    243 
    244  AutoJSAPI jsapi;
    245  if (!jsapi.Init(global)) {
    246    mGetPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
    247    mGetPromise = nullptr;
    248    Unfollow();
    249    return;
    250  }
    251  JSContext* cx = jsapi.cx();
    252  JS::Rooted<JS::Value> reason(cx);
    253  Signal()->GetReason(cx, &reason);
    254  mGetPromise->MaybeReject(reason);
    255  mGetPromise = nullptr;
    256  Unfollow();
    257 }
    258 
    259 }  // namespace mozilla::dom