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

Quelle  JSWindowActorProtocol.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/ContentParent.h"
#include "mozilla/dom/Event.h"
#include "mozilla/dom/JSActorBinding.h"
#include "mozilla/dom/JSActorService.h"
#include "mozilla/dom/JSWindowActorBinding.h"
#include "mozilla/dom/JSWindowActorChild.h"
#include "mozilla/dom/JSWindowActorProtocol.h"
#include "mozilla/dom/PContent.h"
#include "mozilla/dom/WindowGlobalChild.h"

#include "mozilla/extensions/MatchPattern.h"
#include "nsContentUtils.h"
#include "JSActorProtocolUtils.h"

namespace mozilla::dom {

NS_IMPL_CYCLE_COLLECTING_ADDREF(JSWindowActorProtocol)
NS_IMPL_CYCLE_COLLECTING_RELEASE(JSWindowActorProtocol)

NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(JSWindowActorProtocol)
  NS_INTERFACE_MAP_ENTRY(nsIObserver)
  NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
NS_INTERFACE_MAP_END

NS_IMPL_CYCLE_COLLECTION(JSWindowActorProtocol)

/* static */ already_AddRefed<JSWindowActorProtocol>
JSWindowActorProtocol::FromIPC(const JSWindowActorInfo& aInfo) {
  MOZ_DIAGNOSTIC_ASSERT(XRE_IsContentProcess());

  RefPtr<JSWindowActorProtocol> proto = new JSWindowActorProtocol(aInfo.name());
  JSActorProtocolUtils::FromIPCShared(proto, aInfo);

  // Content processes cannot load chrome browsing contexts, so this flag is
  // irrelevant and not propagated.
  proto->mIncludeChrome = false;
  proto->mAllFrames = aInfo.allFrames();
  proto->mMatches = aInfo.matches().Clone();
  proto->mMessageManagerGroups = aInfo.messageManagerGroups().Clone();

  proto->mChild.mEvents.SetCapacity(aInfo.events().Length());
  for (auto& ipc : aInfo.events()) {
    auto event = proto->mChild.mEvents.AppendElement();
    event->mName.Assign(ipc.name());
    event->mFlags.mCapture = ipc.capture();
    event->mFlags.mInSystemGroup = ipc.systemGroup();
    event->mFlags.mAllowUntrustedEvents = ipc.allowUntrusted();
    if (ipc.passive()) {
      event->mPassive.Construct(ipc.passive().value());
    }
    event->mCreateActor = ipc.createActor();
  }

  return proto.forget();
}

JSWindowActorInfo JSWindowActorProtocol::ToIPC() {
  MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess());

  JSWindowActorInfo info;
  JSActorProtocolUtils::ToIPCShared(info, this);

  info.allFrames() = mAllFrames;
  info.matches() = mMatches.Clone();
  info.messageManagerGroups() = mMessageManagerGroups.Clone();

  info.events().SetCapacity(mChild.mEvents.Length());
  for (auto& event : mChild.mEvents) {
    auto ipc = info.events().AppendElement();
    ipc->name().Assign(event.mName);
    ipc->capture() = event.mFlags.mCapture;
    ipc->systemGroup() = event.mFlags.mInSystemGroup;
    ipc->allowUntrusted() = event.mFlags.mAllowUntrustedEvents;
    if (event.mPassive.WasPassed()) {
      ipc->passive() = Some(event.mPassive.Value());
    }
    ipc->createActor() = event.mCreateActor;
  }

  return info;
}

already_AddRefed<JSWindowActorProtocol>
JSWindowActorProtocol::FromWebIDLOptions(const nsACString& aName,
                                         const WindowActorOptions& aOptions,
                                         ErrorResult& aRv) {
  MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess());

  RefPtr<JSWindowActorProtocol> proto = new JSWindowActorProtocol(aName);
  if (!JSActorProtocolUtils::FromWebIDLOptionsShared(proto, aOptions, aRv)) {
    return nullptr;
  }

  proto->mAllFrames = aOptions.mAllFrames;
  proto->mIncludeChrome = aOptions.mIncludeChrome;

  if (aOptions.mMatches.WasPassed()) {
    MOZ_ASSERT(aOptions.mMatches.Value().Length());
    proto->mMatches = aOptions.mMatches.Value();
  }

  if (aOptions.mMessageManagerGroups.WasPassed()) {
    proto->mMessageManagerGroups = aOptions.mMessageManagerGroups.Value();
  }

  // For each event declared in the source dictionary, initialize the
  // corresponding event declaration entry in the JSWindowActorProtocol.
  if (aOptions.mChild.WasPassed() &&
      aOptions.mChild.Value().mEvents.WasPassed()) {
    auto& entries = aOptions.mChild.Value().mEvents.Value().Entries();
    proto->mChild.mEvents.SetCapacity(entries.Length());

    for (auto& entry : entries) {
      // We don't support the mOnce field, as it doesn't work well in this
      // environment. For now, throw an error in that case.
      if (entry.mValue.mOnce) {
        aRv.ThrowNotSupportedError("mOnce is not supported");
        return nullptr;
      }

      // Add the EventDecl to our list of events.
      EventDecl* evt = proto->mChild.mEvents.AppendElement();
      evt->mName = entry.mKey;
      evt->mFlags.mCapture = entry.mValue.mCapture;
      evt->mFlags.mInSystemGroup = entry.mValue.mMozSystemGroup;
      evt->mFlags.mAllowUntrustedEvents =
          entry.mValue.mWantUntrusted.WasPassed()
              ? entry.mValue.mWantUntrusted.Value()
              : false;
      if (entry.mValue.mPassive.WasPassed()) {
        evt->mPassive.Construct(entry.mValue.mPassive.Value());
      }
      evt->mCreateActor = entry.mValue.mCreateActor;
    }
  }

  return proto.forget();
}

/**
 * This listener only listens for events for the child side of the protocol.
 * This will work in both content and parent processes.
 */

NS_IMETHODIMP JSWindowActorProtocol::HandleEvent(Event* aEvent) {
  MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());

  // Determine which inner window we're associated with, and get its
  // WindowGlobalChild actor.
  EventTarget* target = aEvent->GetOriginalTarget();
  if (NS_WARN_IF(!target)) {
    return NS_ERROR_FAILURE;
  }

  nsCOMPtr<nsPIDOMWindowInner> inner =
      do_QueryInterface(target->GetOwnerGlobal());
  if (!inner) {
    return NS_ERROR_FAILURE;
  }

  RefPtr<WindowGlobalChild> wgc = inner->GetWindowGlobalChild();
  if (NS_WARN_IF(!wgc)) {
    return NS_ERROR_FAILURE;
  }

  if (aEvent->ShouldIgnoreChromeEventTargetListener()) {
    return NS_OK;
  }

  // Ensure our actor is present.
  RefPtr<JSActor> actor = wgc->GetExistingActor(mName);
  if (!actor) {
    // Check if we're supposed to create the actor when this event is fired.
    bool createActor = true;
    nsAutoString typeStr;
    aEvent->GetType(typeStr);
    for (auto& event : mChild.mEvents) {
      if (event.mName == typeStr) {
        createActor = event.mCreateActor;
        break;
      }
    }

    // If we're supposed to create the actor, call GetActor to cause it to be
    // created.
    if (createActor) {
      AutoJSAPI jsapi;
      jsapi.Init();
      actor = wgc->GetActor(jsapi.cx(), mName, IgnoreErrors());
    }
  }
  if (!actor || NS_WARN_IF(!actor->GetWrapperPreserveColor())) {
    return NS_OK;
  }

  // Build our event listener & call it.
  JS::Rooted<JSObject*> global(RootingCx(),
                               JS::GetNonCCWObjectGlobal(actor->GetWrapper()));
  RefPtr<EventListener> eventListener =
      new EventListener(actor->GetWrapper(), global, nullptr, nullptr);
  eventListener->HandleEvent(*aEvent, "JSWindowActorProtocol::HandleEvent");
  return NS_OK;
}

NS_IMETHODIMP JSWindowActorProtocol::Observe(nsISupports* aSubject,
                                             const char* aTopic,
                                             const char16_t* aData) {
  MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());

  nsCOMPtr<nsPIDOMWindowInner> inner = do_QueryInterface(aSubject);
  RefPtr<WindowGlobalChild> wgc;

  if (!inner) {
    nsCOMPtr<nsPIDOMWindowOuter> outer = do_QueryInterface(aSubject);
    if (NS_WARN_IF(!outer)) {
      nsContentUtils::LogSimpleConsoleError(
          NS_ConvertUTF8toUTF16(nsPrintfCString(
              "JSWindowActor %s: expected window subject for topic '%s'.",
              mName.get(), aTopic)),
          "JSActor"_ns,
          /* aFromPrivateWindow */ false,
          /* aFromChromeContext */ true);
      return NS_ERROR_FAILURE;
    }
    if (NS_WARN_IF(!outer->GetCurrentInnerWindow())) {
      return NS_ERROR_FAILURE;
    }
    wgc = outer->GetCurrentInnerWindow()->GetWindowGlobalChild();
  } else {
    wgc = inner->GetWindowGlobalChild();
  }

  if (NS_WARN_IF(!wgc)) {
    return NS_ERROR_FAILURE;
  }

  // Ensure our actor is present.
  AutoJSAPI jsapi;
  jsapi.Init();
  RefPtr<JSActor> actor = wgc->GetActor(jsapi.cx(), mName, IgnoreErrors());
  if (!actor || NS_WARN_IF(!actor->GetWrapperPreserveColor())) {
    return NS_OK;
  }

  // Build a observer callback.
  JS::Rooted<JSObject*> global(jsapi.cx(),
                               JS::GetNonCCWObjectGlobal(actor->GetWrapper()));
  RefPtr<MozObserverCallback> observerCallback =
      new MozObserverCallback(actor->GetWrapper(), global, nullptr, nullptr);
  observerCallback->Observe(aSubject, nsDependentCString(aTopic),
                            aData ? nsDependentString(aData) : VoidString());
  return NS_OK;
}

void JSWindowActorProtocol::RegisterListenersFor(EventTarget* aTarget) {
  EventListenerManager* elm = aTarget->GetOrCreateListenerManager();

  for (auto& event : mChild.mEvents) {
    elm->AddEventListenerByType(EventListenerHolder(this), event.mName,
                                event.mFlags, event.mPassive);
  }
}

void JSWindowActorProtocol::UnregisterListenersFor(EventTarget* aTarget) {
  EventListenerManager* elm = aTarget->GetOrCreateListenerManager();

  for (auto& event : mChild.mEvents) {
    elm->RemoveEventListenerByType(EventListenerHolder(this), event.mName,
                                   event.mFlags);
  }
}

void JSWindowActorProtocol::AddObservers() {
  nsCOMPtr<nsIObserverService> os = services::GetObserverService();
  for (auto& topic : mChild.mObservers) {
    // This makes the observer service hold an owning reference to the
    // JSWindowActorProtocol. The JSWindowActorProtocol objects will be living
    // for the full lifetime of the content process, thus the extra strong
    // referencec doesn't have a negative impact.
    os->AddObserver(this, topic.get(), false);
  }
}

void JSWindowActorProtocol::RemoveObservers() {
  nsCOMPtr<nsIObserverService> os = services::GetObserverService();
  for (auto& topic : mChild.mObservers) {
    os->RemoveObserver(this, topic.get());
  }
}

extensions::MatchPatternSetCore* JSWindowActorProtocol::GetURIMatcher() {
  // If we've already created the pattern set, return it.
  if (mURIMatcher || mMatches.IsEmpty()) {
    return mURIMatcher;
  }

  nsTArray<RefPtr<extensions::MatchPatternCore>> patterns(mMatches.Length());
  for (const nsString& pattern : mMatches) {
    patterns.AppendElement(new extensions::MatchPatternCore(
        pattern, falsefalse, IgnoreErrors()));
  }
  mURIMatcher = new extensions::MatchPatternSetCore(std::move(patterns));
  return mURIMatcher;
}

bool JSWindowActorProtocol::RemoteTypePrefixMatches(
    const nsDependentCSubstring& aRemoteType) {
  for (auto& remoteType : mRemoteTypes) {
    if (StringBeginsWith(aRemoteType, remoteType)) {
      return true;
    }
  }
  return false;
}

bool JSWindowActorProtocol::MessageManagerGroupMatches(
    BrowsingContext* aBrowsingContext) {
  BrowsingContext* top = aBrowsingContext->Top();
  for (auto& group : mMessageManagerGroups) {
    if (group == top->GetMessageManagerGroup()) {
      return true;
    }
  }
  return false;
}

bool JSWindowActorProtocol::Matches(BrowsingContext* aBrowsingContext,
                                    nsIURI* aURI, const nsACString& aRemoteType,
                                    ErrorResult& aRv) {
  MOZ_ASSERT(aBrowsingContext, "DocShell without a BrowsingContext!");
  MOZ_ASSERT(aURI, "Must have URI!");

  if (!mAllFrames && aBrowsingContext->GetParent()) {
    aRv.ThrowNotSupportedError(nsPrintfCString(
        "Window protocol '%s' doesn't match subframes", mName.get()));
    return false;
  }

  if (!mIncludeChrome && !aBrowsingContext->IsContent()) {
    aRv.ThrowNotSupportedError(nsPrintfCString(
        "Window protocol '%s' doesn't match chrome browsing contexts",
        mName.get()));
    return false;
  }

  if (!mRemoteTypes.IsEmpty() &&
      !RemoteTypePrefixMatches(RemoteTypePrefix(aRemoteType))) {
    aRv.ThrowNotSupportedError(
        nsPrintfCString("Window protocol '%s' doesn't match remote type '%s'",
                        mName.get(), PromiseFlatCString(aRemoteType).get()));
    return false;
  }

  if (!mMessageManagerGroups.IsEmpty() &&
      !MessageManagerGroupMatches(aBrowsingContext)) {
    aRv.ThrowNotSupportedError(nsPrintfCString(
        "Window protocol '%s' doesn't match message manager group",
        mName.get()));
    return false;
  }

  if (extensions::MatchPatternSetCore* uriMatcher = GetURIMatcher()) {
    if (!uriMatcher->Matches(aURI)) {
      aRv.ThrowNotSupportedError(nsPrintfCString(
          "Window protocol '%s' doesn't match uri %s", mName.get(),
          nsContentUtils::TruncatedURLForDisplay(aURI).get()));
      return false;
    }
  }

  return true;
}

}  // namespace mozilla::dom

Messung V0.5
C=93 H=83 G=87

¤ Dauer der Verarbeitung: 0.11 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.