Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  LNAPermissionRequest.cpp

  Sprache: C
 

/* 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 "LNAPermissionRequest.h"
#include "mozilla/dom/ClientInfo.h"
#include "nsGlobalWindowInner.h"
#include "mozilla/dom/Document.h"
#include "nsPIDOMWindow.h"
#include "mozilla/Preferences.h"
#include "nsContentUtils.h"
#include "mozilla/glean/NetwerkMetrics.h"

#include "mozilla/dom/WindowGlobalParent.h"
#include "nsIIOService.h"
#include "nsIOService.h"
#include "mozilla/dom/CanonicalBrowsingContext.h"
#include "mozilla/dom/FeaturePolicy.h"
#include "mozilla/Components.h"
#include "nsIConsoleService.h"
#include "nsIPermissionManager.h"
#include "xpcpublic.h"

namespace mozilla::net {

//-------------------------------------------------
// LNA Permission Requests
//-------------------------------------------------

NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(LNAPermissionRequest,
                                               ContentPermissionRequestBase)

NS_IMPL_CYCLE_COLLECTION_INHERITED(LNAPermissionRequest,
                                   ContentPermissionRequestBase,
                                   mBrowsingContext)

LNAPermissionRequest::LNAPermissionRequest(PermissionPromptCallback&& aCallback,
                                           nsILoadInfo* aLoadInfo,
                                           const nsACString& aType)
    : dom::ContentPermissionRequestBase(
          aLoadInfo->GetLoadingPrincipal(), nullptr,
          (aType.Equals(LOOPBACK_NETWORK_PERMISSION_KEY)
               ? "network.loopback-network"_ns
               : "network.localnetwork"_ns),
          aType),
      mPermissionPromptCallback(std::move(aCallback)) {
  MOZ_ASSERT(aLoadInfo);

  aLoadInfo->GetTriggeringPrincipal(getter_AddRefs(mPrincipal));

  aLoadInfo->GetBrowsingContext(getter_AddRefs(mBrowsingContext));
  // For worker-initiated requests, the browsing context is null.
  // Fall back to the associated browsing context which points to the
  // worker's parent document's BC.
  if (!mBrowsingContext) {
    Maybe<dom::ClientInfo> clientInfo = aLoadInfo->GetClientInfo();
    if (clientInfo.isSome() && clientInfo->Type() != dom::ClientType::Window) {
      aLoadInfo->GetAssociatedBrowsingContext(getter_AddRefs(mBrowsingContext));
    }
  }
  if (mBrowsingContext && mBrowsingContext->Top()) {
    if (mBrowsingContext->Top()->Canonical()) {
      RefPtr<mozilla::dom::WindowGlobalParent> topWindowGlobal =
          mBrowsingContext->Top()->Canonical()->GetCurrentWindowGlobal();
      if (topWindowGlobal) {
        mTopLevelPrincipal = topWindowGlobal->DocumentPrincipal();
      }
    }
  }

  if (!mTopLevelPrincipal && xpc::IsInAutomation()) {
    // In test environments, the browsing context may not be fully set up.
    // Fall back to triggering principal to allow tests to proceed.
    mTopLevelPrincipal = mPrincipal;
  }

  mLoadInfo = aLoadInfo;

  MOZ_ASSERT(mPrincipal);
}

NS_IMETHODIMP
LNAPermissionRequest::GetElement(mozilla::dom::Element** aElement) {
  NS_ENSURE_ARG_POINTER(aElement);
  if (!mBrowsingContext) {
    return NS_ERROR_FAILURE;
  }

  return mBrowsingContext->GetTopFrameElement(aElement);
}

// callback when the permission request is denied
NS_IMETHODIMP
LNAPermissionRequest::Cancel() {
  // callback to the http channel on the prompt failure result
  mPermissionPromptCallback(false, mType, mPromptWasShown);
  return NS_OK;
}

// callback when the permission request is allowed
NS_IMETHODIMP
LNAPermissionRequest::Allow(JS::Handle<JS::Value> aChoices) {
  // callback to the http channel on the prompt success result
  mPermissionPromptCallback(true, mType, mPromptWasShown);
  return NS_OK;
}

// callback when the permission prompt is shown
NS_IMETHODIMP
LNAPermissionRequest::NotifyShown() {
  // Mark that the prompt was shown to the user
  mPromptWasShown = true;

  // Record telemetry for permission prompts shown to users
  // Skip telemetry if we don't have both principals (e.g., in test
  // environments)
  if (!mPrincipal || !mTopLevelPrincipal) {
    return NS_OK;
  }

  // Check if this is a cross-origin request
  bool isCrossOrigin = !mPrincipal->Equals(mTopLevelPrincipal);
  if (mType.Equals(LOOPBACK_NETWORK_PERMISSION_KEY)) {
    if (isCrossOrigin) {
      mozilla::glean::networking::local_network_access_prompts_shown
          .Get("localhost_cross_site"_ns)
          .Add(1);
    } else {
      mozilla::glean::networking::local_network_access_prompts_shown
          .Get("localhost"_ns)
          .Add(1);
    }
  } else if (mType.Equals(LOCAL_NETWORK_PERMISSION_KEY)) {
    if (isCrossOrigin) {
      mozilla::glean::networking::local_network_access_prompts_shown
          .Get("local_network_cross_site"_ns)
          .Add(1);
    } else {
      mozilla::glean::networking::local_network_access_prompts_shown
          .Get("local_network"_ns)
          .Add(1);
    }
  }

  return NS_OK;
}

nsresult LNAPermissionRequest::RequestPermission() {
  MOZ_ASSERT(NS_IsMainThread());

  // Enforce Feature Policy for Local Network Access (Bug 1978550)
  if (!mLoadInfo) {
    NS_WARNING("LNA permission request without load info");
    return Cancel();
  }

  // Retrieve the canonical browsing context for feature policy checks
  RefPtr<dom::CanonicalBrowsingContext> bc;
  if (mBrowsingContext) {
    bc = mBrowsingContext->Canonical();
  }

  if (!bc) {
    // for unit tests, we may not have a browsing context, so we dont treat this
    // as hard error for automation
    if (!xpc::IsInAutomation()) {
      NS_WARNING("local network access without browsing context");
      return Cancel();
    }
  } else {
    Maybe<dom::FeaturePolicyInfo> fpInfo = bc->GetContainerFeaturePolicy();
    // Feature Policy is populated in the canonical browsing context via
    // HTMLIFrameElement::MaybeStoreCrossOriginFeaturePolicy() (for <iframe>)
    // nsObjectLoadingContent::MaybeStoreCrossOriginFeaturePolicy() (for
    // <object>/<embed>)
    // Hence, it's safe to ignore feature policy when it's missing as that
    // would only mean the request is from a top-level document, which should
    // be allowed to request local network access without being blocked by
    // feature policy.
    if (fpInfo.isSome()) {
      nsAutoString featureName;
      if (mType.Equals(LOOPBACK_NETWORK_PERMISSION_KEY)) {
        featureName = u"loopback-network"_ns;
      } else {
        featureName = u"local-network"_ns;
      }

      if (fpInfo->mInheritedDeniedFeatureNames.Contains(featureName)) {
        NS_WARNING("Feature policy denying the request");
        return Cancel();
      }
    }
  }

  // Check if the domain should skip LNA checks
  if (mPrincipal && gIOService) {
    nsAutoCString origin;
    nsresult rv = mPrincipal->GetAsciiHost(origin);
    if (NS_SUCCEEDED(rv) && !origin.IsEmpty()) {
      if (gIOService->ShouldSkipDomainForLNA(origin)) {
        // Domain is in the skip list, grant permission automatically
        return Allow(JS::UndefinedHandleValue);
      }
    }
  }

  PromptResult pr = CheckPromptPrefs();
  if (pr == PromptResult::Granted) {
    return Allow(JS::UndefinedHandleValue);
  }

  if (pr == PromptResult::Denied) {
    return Cancel();
  }

  // For shared and service workers, do not show a permission prompt.
  // Only grant access if the origin already has a persistent LNA permission.
  Maybe<dom::ClientInfo> clientInfo = mLoadInfo->GetClientInfo();
  if (clientInfo.isSome() &&
      (clientInfo->Type() == dom::ClientType::Sharedworker ||
       clientInfo->Type() == dom::ClientType::Serviceworker)) {
    nsCOMPtr<nsIPermissionManager> permMgr =
        mozilla::components::PermissionManager::Service();
    if (!permMgr || !mPrincipal) {
      NS_WARNING(
          "LNA worker permission check failed: no permission manager or "
          "principal");
      return Cancel();
    }
    uint32_t permission = nsIPermissionManager::UNKNOWN_ACTION;
    nsresult rv =
        permMgr->TestPermissionFromPrincipal(mPrincipal, mType, &permission);
    if (NS_SUCCEEDED(rv) && permission == nsIPermissionManager::ALLOW_ACTION) {
      return Allow(JS::UndefinedHandleValue);
    }
    // Log the denial to the browser console so developers can diagnose why
    // worker fetch requests are being blocked.
    nsCOMPtr<nsIConsoleService> console =
        do_GetService(NS_CONSOLESERVICE_CONTRACTID);
    if (console && mPrincipal) {
      nsAutoCString origin;
      mPrincipal->GetOrigin(origin);
      nsAutoString msg;
      msg.AppendLiteral("Local Network Access blocked: worker from origin ");
      msg.Append(NS_ConvertUTF8toUTF16(origin));
      msg.AppendLiteral(" attempted ");
      msg.Append(NS_ConvertUTF8toUTF16(mType));
      msg.AppendLiteral(" access but no persistent permission was granted.");
      console->LogStringMessage(msg.get());
    }
    return Cancel();
  }

  // Ensure we have a top-level principal before showing the permission prompt
  if (!mTopLevelPrincipal) {
    NS_WARNING("Cannot show permission prompt without top-level principal");
    return Cancel();
  }

  if (NS_SUCCEEDED(
          dom::nsContentPermissionUtils::AskPermission(this, mWindow))) {
    // Here we could be getting synchronous callback from the prompts depending
    // on whether there is already a permission for this or not. If we have a
    // permission, we will get a synchronous callback Allow/Deny and async if
    // we don't have a permission yet and waiting for user permission.
    return NS_OK;
  }

  return Cancel();
}

}  // namespace mozilla::net

Messung V0.5 in Prozent
C=91 H=92 G=91

¤ Dauer der Verarbeitung: 0.31 Sekunden  (vorverarbeitet am  2026-08-25) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

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.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=141584
#Domains=752002