tor-browser

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

Client.cpp (7208B)


      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 "Client.h"
      8 
      9 #include "ClientDOMUtil.h"
     10 #include "mozilla/dom/ClientHandle.h"
     11 #include "mozilla/dom/ClientIPCTypes.h"
     12 #include "mozilla/dom/ClientManager.h"
     13 #include "mozilla/dom/ClientState.h"
     14 #include "mozilla/dom/DOMMozPromiseRequestHolder.h"
     15 #include "mozilla/dom/MessagePortBinding.h"
     16 #include "mozilla/dom/Promise.h"
     17 #include "mozilla/dom/WorkerScope.h"
     18 #include "nsIDUtils.h"
     19 #include "nsIGlobalObject.h"
     20 
     21 namespace mozilla::dom {
     22 
     23 using mozilla::dom::ipc::StructuredCloneData;
     24 
     25 NS_IMPL_CYCLE_COLLECTING_ADDREF(mozilla::dom::Client);
     26 NS_IMPL_CYCLE_COLLECTING_RELEASE(mozilla::dom::Client);
     27 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(mozilla::dom::Client, mGlobal);
     28 
     29 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(mozilla::dom::Client)
     30  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
     31  NS_INTERFACE_MAP_ENTRY(nsISupports)
     32 NS_INTERFACE_MAP_END
     33 
     34 void Client::EnsureHandle() {
     35  NS_ASSERT_OWNINGTHREAD(mozilla::dom::Client);
     36  if (!mHandle) {
     37    mHandle = ClientManager::CreateHandle(ClientInfo(mData->info()),
     38                                          mGlobal->SerialEventTarget());
     39  }
     40 }
     41 
     42 Client::Client(nsIGlobalObject* aGlobal, const ClientInfoAndState& aData)
     43    : mGlobal(aGlobal), mData(MakeUnique<ClientInfoAndState>(aData)) {
     44  MOZ_DIAGNOSTIC_ASSERT(mGlobal);
     45 }
     46 
     47 TimeStamp Client::CreationTime() const { return mData->info().creationTime(); }
     48 
     49 TimeStamp Client::LastFocusTime() const {
     50  if (mData->info().type() != ClientType::Window) {
     51    return TimeStamp();
     52  }
     53  return mData->state().get_IPCClientWindowState().lastFocusTime();
     54 }
     55 
     56 StorageAccess Client::GetStorageAccess() const {
     57  ClientState state(ClientState::FromIPC(mData->state()));
     58  return state.GetStorageAccess();
     59 }
     60 
     61 JSObject* Client::WrapObject(JSContext* aCx,
     62                             JS::Handle<JSObject*> aGivenProto) {
     63  if (mData->info().type() == ClientType::Window) {
     64    return WindowClient_Binding::Wrap(aCx, this, aGivenProto);
     65  }
     66  return Client_Binding::Wrap(aCx, this, aGivenProto);
     67 }
     68 
     69 nsIGlobalObject* Client::GetParentObject() const { return mGlobal; }
     70 
     71 void Client::GetUrl(nsAString& aUrlOut) const {
     72  CopyUTF8toUTF16(mData->info().url(), aUrlOut);
     73 }
     74 
     75 void Client::GetId(nsAString& aIdOut) const {
     76  aIdOut = NSID_TrimBracketsUTF16(mData->info().id());
     77 }
     78 
     79 ClientType Client::Type() const { return mData->info().type(); }
     80 
     81 FrameType Client::GetFrameType() const { return mData->info().frameType(); }
     82 
     83 void Client::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
     84                         const Sequence<JSObject*>& aTransferable,
     85                         ErrorResult& aRv) {
     86  MOZ_ASSERT(!NS_IsMainThread());
     87  WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
     88  MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
     89  MOZ_DIAGNOSTIC_ASSERT(workerPrivate->IsServiceWorker());
     90  workerPrivate->AssertIsOnWorkerThread();
     91 
     92  JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
     93  aRv = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx, aTransferable,
     94                                                          &transferable);
     95  if (aRv.Failed()) {
     96    return;
     97  }
     98 
     99  StructuredCloneData data;
    100  data.Write(aCx, aMessage, transferable, JS::CloneDataPolicy(), aRv);
    101  if (aRv.Failed()) {
    102    return;
    103  }
    104 
    105  EnsureHandle();
    106  mHandle->PostMessage(data, workerPrivate->GetServiceWorkerDescriptor());
    107 }
    108 
    109 void Client::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
    110                         const StructuredSerializeOptions& aOptions,
    111                         ErrorResult& aRv) {
    112  PostMessage(aCx, aMessage, aOptions.mTransfer, aRv);
    113 }
    114 
    115 VisibilityState Client::GetVisibilityState() const {
    116  return mData->state().get_IPCClientWindowState().visibilityState();
    117 }
    118 
    119 bool Client::Focused() const {
    120  return mData->state().get_IPCClientWindowState().focused();
    121 }
    122 
    123 already_AddRefed<Promise> Client::Focus(CallerType aCallerType,
    124                                        ErrorResult& aRv) {
    125  MOZ_ASSERT(!NS_IsMainThread());
    126  WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
    127  MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
    128  MOZ_DIAGNOSTIC_ASSERT(workerPrivate->IsServiceWorker());
    129  workerPrivate->AssertIsOnWorkerThread();
    130 
    131  RefPtr<Promise> outerPromise = Promise::Create(mGlobal, aRv);
    132  if (aRv.Failed()) {
    133    return outerPromise.forget();
    134  }
    135 
    136  if (!workerPrivate->GlobalScope()->WindowInteractionAllowed()) {
    137    outerPromise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
    138    return outerPromise.forget();
    139  }
    140 
    141  EnsureHandle();
    142 
    143  IPCClientInfo ipcClientInfo(mData->info());
    144  auto holder =
    145      MakeRefPtr<DOMMozPromiseRequestHolder<ClientStatePromise>>(mGlobal);
    146 
    147  mHandle->Focus(aCallerType)
    148      ->Then(
    149          mGlobal->SerialEventTarget(), __func__,
    150          [ipcClientInfo, holder, outerPromise](const ClientState& aResult) {
    151            holder->Complete();
    152            NS_ENSURE_TRUE_VOID(holder->GetParentObject());
    153            RefPtr<Client> newClient =
    154                new Client(holder->GetParentObject(),
    155                           ClientInfoAndState(ipcClientInfo, aResult.ToIPC()));
    156            outerPromise->MaybeResolve(newClient);
    157          },
    158          [holder, outerPromise](const CopyableErrorResult& aResult) {
    159            holder->Complete();
    160            // MaybeReject needs a non-const-ref result, so make a copy.
    161            outerPromise->MaybeReject(CopyableErrorResult(aResult));
    162          })
    163      ->Track(*holder);
    164 
    165  return outerPromise.forget();
    166 }
    167 
    168 already_AddRefed<Promise> Client::Navigate(const nsAString& aURL,
    169                                           ErrorResult& aRv) {
    170  MOZ_ASSERT(!NS_IsMainThread());
    171  WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
    172  MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
    173  MOZ_DIAGNOSTIC_ASSERT(workerPrivate->IsServiceWorker());
    174  workerPrivate->AssertIsOnWorkerThread();
    175 
    176  RefPtr<Promise> outerPromise = Promise::Create(mGlobal, aRv);
    177  if (aRv.Failed()) {
    178    return outerPromise.forget();
    179  }
    180 
    181  ClientNavigateArgs args(mData->info(), NS_ConvertUTF16toUTF8(aURL),
    182                          workerPrivate->GetLocationInfo().mHref,
    183                          workerPrivate->GetServiceWorkerDescriptor().ToIPC());
    184  RefPtr<Client> self = this;
    185 
    186  StartClientManagerOp(
    187      &ClientManager::Navigate, args, mGlobal,
    188      [self, outerPromise](const ClientOpResult& aResult) {
    189        if (aResult.type() != ClientOpResult::TClientInfoAndState) {
    190          outerPromise->MaybeResolve(JS::NullHandleValue);
    191          return;
    192        }
    193        RefPtr<Client> newClient =
    194            new Client(self->mGlobal, aResult.get_ClientInfoAndState());
    195        outerPromise->MaybeResolve(newClient);
    196      },
    197      [self, outerPromise](const CopyableErrorResult& aResult) {
    198        // MaybeReject needs a non-const-ref result, so make a copy.
    199        outerPromise->MaybeReject(CopyableErrorResult(aResult));
    200      });
    201 
    202  return outerPromise.forget();
    203 }
    204 
    205 }  // namespace mozilla::dom