Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/dom/ipc/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 9 kB image not shown  

Quelle  InProcessImpl.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "mozilla/dom/InProcessParent.h"
#include "mozilla/dom/InProcessChild.h"
#include "mozilla/dom/JSProcessActorBinding.h"
#include "nsIObserverService.h"
#include "mozilla/Services.h"

using namespace mozilla::ipc;

// This file contains the implementation of core InProcess lifecycle management
// facilities.

namespace mozilla::dom {

StaticRefPtr<InProcessParent> InProcessParent::sSingleton;
StaticRefPtr<InProcessChild> InProcessChild::sSingleton;
bool InProcessParent::sShutdown = false;

//////////////////////////////////////////
// InProcess actor lifecycle management //
//////////////////////////////////////////

/* static */
InProcessChild* InProcessChild::Singleton() {
  MOZ_ASSERT(NS_IsMainThread());

  if (!sSingleton) {
    InProcessParent::Startup();
  }
  return sSingleton;
}

/* static */
InProcessParent* InProcessParent::Singleton() {
  MOZ_ASSERT(NS_IsMainThread());

  if (!sSingleton) {
    InProcessParent::Startup();
  }
  return sSingleton;
}

/* static */
void InProcessParent::Startup() {
  MOZ_ASSERT(NS_IsMainThread());

  if (sShutdown) {
    NS_WARNING("Could not get in-process actor while shutting down!");
    return;
  }

  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
  if (!obs) {
    sShutdown = true;
    NS_WARNING("Failed to get nsIObserverService for in-process actor");
    return;
  }

  RefPtr<InProcessParent> parent = new InProcessParent();
  RefPtr<InProcessChild> child = new InProcessChild();

  // Observe the shutdown event to close & clean up after ourselves.
  nsresult rv = obs->AddObserver(parent, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return;
  }

  // Link the two actors
  if (!child->OpenOnSameThread(parent, ChildSide)) {
    MOZ_CRASH("Failed to open InProcessChild!");
  }

  parent->SetOtherEndpointProcInfo(EndpointProcInfo::Current());

  // Stash global references to fetch the other side of the reference.
  InProcessParent::sSingleton = std::move(parent);
  InProcessChild::sSingleton = std::move(child);
}

/* static */
void InProcessParent::Shutdown() {
  MOZ_ASSERT(NS_IsMainThread());

  if (!sSingleton || sShutdown) {
    return;
  }

  sShutdown = true;

  RefPtr<InProcessParent> parent = sSingleton;
  InProcessParent::sSingleton = nullptr;
  InProcessChild::sSingleton = nullptr;

  // Calling `Close` on the actor will cause the `Dealloc` methods to be called,
  // freeing the remaining references.
  parent->Close();
}

NS_IMETHODIMP
InProcessParent::Observe(nsISupports* aSubject, const char* aTopic,
                         const char16_t* aData) {
  MOZ_ASSERT(!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID));
  InProcessParent::Shutdown();
  return NS_OK;
}

void InProcessParent::ActorDestroy(ActorDestroyReason aWhy) {
  JSActorDidDestroy();
  InProcessParent::Shutdown();
}

void InProcessChild::ActorDestroy(ActorDestroyReason aWhy) {
  JSActorDidDestroy();
  InProcessParent::Shutdown();
}

/////////////////////////
// nsIDOMProcessParent //
/////////////////////////

NS_IMETHODIMP
InProcessParent::GetChildID(uint64_t* aChildID) {
  *aChildID = 0;
  return NS_OK;
}

NS_IMETHODIMP
InProcessParent::GetOsPid(int32_t* aOsPid) {
  // InProcessParent always run in the parent process,
  // so we can return the current process id.
  *aOsPid = base::GetCurrentProcId();
  return NS_OK;
}

NS_IMETHODIMP InProcessParent::GetRemoteType(nsACString& aRemoteType) {
  aRemoteType = NOT_REMOTE_TYPE;
  return NS_OK;
}

NS_IMETHODIMP
InProcessParent::GetActor(const nsACString& aName, JSContext* aCx,
                          JSProcessActorParent** aActor) {
  ErrorResult error;
  RefPtr<JSProcessActorParent> actor =
      JSActorManager::GetActor(aCx, aName, error)
          .downcast<JSProcessActorParent>();
  if (error.MaybeSetPendingException(aCx)) {
    return NS_ERROR_FAILURE;
  }
  actor.forget(aActor);
  return NS_OK;
}

NS_IMETHODIMP
InProcessParent::GetExistingActor(const nsACString& aName,
                                  JSProcessActorParent** aActor) {
  RefPtr<JSProcessActorParent> actor =
      JSActorManager::GetExistingActor(aName).downcast<JSProcessActorParent>();
  actor.forget(aActor);
  return NS_OK;
}

already_AddRefed<JSActor> InProcessParent::InitJSActor(
    JS::Handle<JSObject*> aMaybeActor, const nsACString& aName,
    ErrorResult& aRv) {
  RefPtr<JSProcessActorParent> actor;
  if (aMaybeActor.get()) {
    aRv = UNWRAP_OBJECT(JSProcessActorParent, aMaybeActor.get(), actor);
    if (aRv.Failed()) {
      return nullptr;
    }
  } else {
    actor = new JSProcessActorParent();
  }

  MOZ_RELEASE_ASSERT(!actor->Manager(),
                     "mManager was already initialized once!");
  actor->Init(aName, this);
  return actor.forget();
}

NS_IMETHODIMP
InProcessParent::GetCanSend(bool* aCanSend) {
  *aCanSend = CanSend();
  return NS_OK;
}

ContentParent* InProcessParent::AsContentParent() { return nullptr; }

JSActorManager* InProcessParent::AsJSActorManager() { return this; }

////////////////////////
// nsIDOMProcessChild //
////////////////////////

NS_IMETHODIMP
InProcessChild::GetChildID(uint64_t* aChildID) {
  *aChildID = 0;
  return NS_OK;
}

NS_IMETHODIMP
InProcessChild::GetActor(const nsACString& aName, JSContext* aCx,
                         JSProcessActorChild** aActor) {
  ErrorResult error;
  RefPtr<JSProcessActorChild> actor =
      JSActorManager::GetActor(aCx, aName, error)
          .downcast<JSProcessActorChild>();
  if (error.MaybeSetPendingException(aCx)) {
    return NS_ERROR_FAILURE;
  }
  actor.forget(aActor);
  return NS_OK;
}

NS_IMETHODIMP
InProcessChild::GetExistingActor(const nsACString& aName,
                                 JSProcessActorChild** aActor) {
  RefPtr<JSProcessActorChild> actor =
      JSActorManager::GetExistingActor(aName).downcast<JSProcessActorChild>();
  actor.forget(aActor);
  return NS_OK;
}

already_AddRefed<JSActor> InProcessChild::InitJSActor(
    JS::Handle<JSObject*> aMaybeActor, const nsACString& aName,
    ErrorResult& aRv) {
  RefPtr<JSProcessActorChild> actor;
  if (aMaybeActor.get()) {
    aRv = UNWRAP_OBJECT(JSProcessActorChild, aMaybeActor.get(), actor);
    if (aRv.Failed()) {
      return nullptr;
    }
  } else {
    actor = new JSProcessActorChild();
  }

  MOZ_RELEASE_ASSERT(!actor->Manager(),
                     "mManager was already initialized once!");
  actor->Init(aName, this);
  return actor.forget();
}

NS_IMETHODIMP
InProcessChild::GetCanSend(bool* aCanSend) {
  *aCanSend = CanSend();
  return NS_OK;
}

ContentChild* InProcessChild::AsContentChild() { return nullptr; }

JSActorManager* InProcessChild::AsJSActorManager() { return this; }

////////////////////////////////
// In-Process Actor Utilities //
////////////////////////////////

// Helper method for implementing ParentActorFor and ChildActorFor.
static IProtocol* GetOtherInProcessActor(IProtocol* aActor) {
  MOZ_ASSERT(aActor->GetSide() != UnknownSide, "bad unknown side");

  // Discover the manager of aActor which is PInProcess.
  IProtocol* current = aActor;
  while (current && current->CanRecv()) {
    if (current->GetProtocolId() == PInProcessMsgStart) {
      break;  // Found the correct actor.
    }
    current = current->Manager();
  }
  if (!current || !current->CanRecv()) {
    return nullptr;  // Not a live PInProcess actor, return |nullptr|
  }

  MOZ_ASSERT(current->GetSide() == aActor->GetSide(), "side changed?");
  MOZ_ASSERT_IF(aActor->GetSide() == ParentSide,
                current == InProcessParent::Singleton());
  MOZ_ASSERT_IF(aActor->GetSide() == ChildSide,
                current == InProcessChild::Singleton());

  // Check whether this is InProcessParent or InProcessChild, and get the other
  // side's toplevel actor.
  IProtocol* otherRoot = nullptr;
  if (aActor->GetSide() == ParentSide) {
    otherRoot = InProcessChild::Singleton();
  } else {
    otherRoot = InProcessParent::Singleton();
  }
  if (NS_WARN_IF(!otherRoot)) {
    return nullptr;
  }

  // Look up the actor on the other side, and return it.
  IProtocol* otherActor = otherRoot->Lookup(aActor->Id());
  if (otherActor) {
    MOZ_ASSERT(otherActor->GetSide() != UnknownSide, "bad unknown side");
    MOZ_ASSERT(otherActor->GetSide() != aActor->GetSide(), "Wrong side!");
    MOZ_ASSERT(otherActor->GetProtocolId() == aActor->GetProtocolId(),
               "Wrong type of protocol!");
  }

  return otherActor;
}

/* static */
IProtocol* InProcessParent::ChildActorFor(IProtocol* aActor) {
  MOZ_ASSERT(aActor && aActor->GetSide() == ParentSide);
  return GetOtherInProcessActor(aActor);
}

/* static */
IProtocol* InProcessChild::ParentActorFor(IProtocol* aActor) {
  MOZ_ASSERT(aActor && aActor->GetSide() == ChildSide);
  return GetOtherInProcessActor(aActor);
}

NS_IMPL_ISUPPORTS(InProcessParent, nsIDOMProcessParent, nsIObserver)
NS_IMPL_ISUPPORTS(InProcessChild, nsIDOMProcessChild)

}  // namespace mozilla::dom

Messung V0.5
C=91 H=98 G=94

¤ Dauer der Verarbeitung: 0.32 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.