Eine aufbereitete Darstellung der Quelle

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

Benutzer

Quelle  Ping.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 "mozilla/glean/bindings/Ping.h"

#include "jsapi.h"
#include "mozilla/AppShutdown.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/Components.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/Promise-inl.h"
#include "nsIClassInfoImpl.h"
#include "nsTHashMap.h"
#include "nsString.h"

#include <memory>

namespace mozilla::glean {

namespace impl {

using CallbackMapType =
    nsTHashMap<NoMemMoveKey<nsUint32HashKey>, FalliblePingTestCallback>;
using MetricIdToCallbackMutex = StaticDataMutex<UniquePtr<CallbackMapType>>;
static Maybe<MetricIdToCallbackMutex::AutoLock> GetCallbackMapLock() {
  static MetricIdToCallbackMutex sCallbacks("sCallbacks");
  auto lock = sCallbacks.Lock();
  // Test callbacks will continue to work until the end of AppShutdownTelemetry
  if (AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMWillShutdown)) {
    return Nothing();
  }
  if (!*lock) {
    *lock = MakeUnique<CallbackMapType>();
    RunOnShutdown(
        [&] {
          auto lock = sCallbacks.Lock();
          *lock = nullptr;  // deletes, see UniquePtr.h
        },
        ShutdownPhase::XPCOMWillShutdown);
  }
  return Some(std::move(lock));
}

void Ping::Submit(const nsACString& aReason) const {
  (void)SubmitInternal(aReason);
}

nsresult Ping::SubmitInternal(const nsACString& aReason) const {
  nsresult rv = NS_OK;
  {
    auto callback = Maybe<FalliblePingTestCallback>();
    GetCallbackMapLock().apply(
        [&](const auto& lock) { callback = lock.ref()->Extract(mId); });
    // Calling the callback outside of the lock allows it to register a new
    // callback itself.
    if (callback) {
      rv = callback.extract()(aReason);
    }
  }
  fog_submit_ping_by_id(mId, &aReason);
  return rv;
}

void Ping::SetEnabled(bool aValue) const {
  fog_set_ping_enabled_by_id(mId, aValue);
}

void Ping::TestBeforeNextSubmit(PingTestCallback&& aCallback) const {
  TestBeforeNextSubmitFallible(
      [callback = std::move(aCallback)](const nsACString& aReason) -> nsresult {
        callback(aReason);
        return NS_OK;
      });
}

void Ping::TestBeforeNextSubmitFallible(
    FalliblePingTestCallback&& aCallback) const {
  {
    GetCallbackMapLock().apply(
        [&](const auto& lock) { lock.ref()->InsertOrUpdate(mId, aCallback); });
  }
}

bool Ping::TestSubmission(PingTestCallback&& aTestCallback,
                          PingSubmitCallback&& aSubmitCallback) const {
  // We could probably get away with passing a reference to the callbacks, but
  // if aSubmitCallback does not actually submit the ping, then we will have
  // created a reference to stack memory that will persist after this function
  // returns.
  auto didCall = std::make_shared<bool>(false);

  TestBeforeNextSubmit([callback = std::move(aTestCallback),
                        didCall](const nsACString& aReason) {
    *didCall = true;
    callback(aReason);
  });

  aSubmitCallback();

  return *didCall;
}

}  // namespace impl

NS_IMPL_CLASSINFO(GleanPing, nullptr, 0, {0})
NS_IMPL_ISUPPORTS_CI(GleanPing, nsIGleanPing)

NS_IMETHODIMP
GleanPing::Submit(const nsACString& aReason) {
  return mPing.SubmitInternal(aReason);
}

NS_IMETHODIMP
GleanPing::SetEnabled(bool aValue) {
  mPing.SetEnabled(aValue);
  return NS_OK;
}

NS_IMETHODIMP
GleanPing::TestBeforeNextSubmit(nsIGleanPingTestCallback* aCallback) {
  if (NS_WARN_IF(!aCallback)) {
    return NS_ERROR_INVALID_ARG;
  }
  // Throw the bare ptr into a COM ptr to keep it around in the lambda.
  mPing.TestBeforeNextSubmitFallible(
      [callback = nsCOMPtr(aCallback)](const nsACString& aReason) -> nsresult {
        return callback->Call(aReason);
      });
  return NS_OK;
}

NS_IMETHODIMP
GleanPing::TestSubmission(nsIGleanPingTestCallback* aTestCallback,
                          nsIGleanPingSubmitCallback* aSubmitCallback,
                          uint32_t aSubmitTimeoutMs, JSContext* aCx,
                          dom::Promise** aOutPromise) {
  if (NS_WARN_IF(!aTestCallback || !aSubmitCallback)) {
    return NS_ERROR_INVALID_ARG;
  }

  IgnoredErrorResult err;
  // This promise will be resolved if `aTestCallback` is called (i.e., the ping
  // is submitted) and doesn't throw.
  RefPtr<dom::Promise> submittedPromise =
      dom::Promise::Create(xpc::CurrentNativeGlobal(aCx), err);
  if (err.Failed()) {
    return err.StealNSResult();
  }

  // Wrap the callback with one that will resolve or reject `submittedPromise`.
  mPing.TestBeforeNextSubmit([testCallback = nsCOMPtr{aTestCallback},
                              submittedPromise](const nsACString& aReason) {
    nsresult rv = testCallback->Call(aReason);
    if (NS_SUCCEEDED(rv)) {
      submittedPromise->MaybeResolveWithUndefined();
    } else {
      // If the callback threw we need to pass that along as a promise
      // rejection.
      submittedPromise->MaybeReject(rv);
    }
  });

  // Call `aSubmitCallback` to trigger ping submission. This function may or may
  // not be async, but becuase it *can* be, XPConnect will always promise wrap
  // its return value.
  RefPtr<dom::Promise> submitPromise;
  MOZ_TRY(aSubmitCallback->Call(getter_AddRefs(submitPromise)));

  RefPtr<dom::Promise> thenPromise =
      MOZ_TRY(submitPromise->ThenWithCycleCollectedArgs(
          [aSubmitTimeoutMs](JSContext*, JS::Handle<JS::Value>,
                             ErrorResult& aRv,
                             RefPtr<dom::Promise> aSubmittedPromise)
              -> already_AddRefed<dom::Promise> {
            // The submit callback has finished successfully now
            // (whether or not it was async).
            if (aSubmitTimeoutMs) {
              // We have a submit timeout, which means that
              // `aSubmitCallback` has triggered the submission through
              // some async means that does not complete before it
              // returns (e.g., idle dispatch from c++). Reject
              // `submittedPromise` after the given timeout to make sure
              // we don't hang forever waiting for a submission that
              // might not happen.
              nsresult rv = NS_DelayedDispatchToCurrentThread(
                  NS_NewRunnableFunction(
                      __func__,
                      [submittedPromise = RefPtr(aSubmittedPromise)]() {
                        submittedPromise->MaybeRejectWithTimeoutError(
                            "Ping was not submitted after timeout");
                      }),
                  aSubmitTimeoutMs);

              if (NS_FAILED(rv)) {
                aSubmittedPromise->MaybeReject(rv);
              }
            } else {
              // If there is no timeout then the ping should have been
              // submitted already. We attempt to reject the promise,
              // which will have no affect if the promise is already
              // settled.
              aSubmittedPromise->MaybeRejectWithOperationError(
                  "Ping did not submit immediately");
            }

            // Chain into `submittedPromise` so that we will
            // resolve/reject appropriately.
            return aSubmittedPromise.forget();
          },
          std::move(submittedPromise)));

  thenPromise.forget(aOutPromise);
  return NS_OK;
}

}  // namespace mozilla::glean

Messung V0.5 in Prozent
C=86 H=95 G=90

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© 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=277311
#Domains=655579