We need to clear state at shutdown that we hold for GIFFT mirroring purposes. However, more data can come in even later (there's nothing stopping it. Plus, Glean can meaningfully record later given its shutdown happens in a later phase), so the naive approach of lazy-instantiate and RunOnShutdown-clear doesn't work. Since Telemetry is only good to AppShutdownTelemetry, we now fail to mirror to it after AppShutdownTelemetry and clear state in the immediately-next phase. Also, data can come in earlier than we have a main thread to dispatch to, requiring some careful finagling of threads to ensure our cleanup routine is appropriately registered. Differential Revision: https://phabricator.services.mozilla.com/D143522
95 lines
2.6 KiB
C++
95 lines
2.6 KiB
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/glean/bindings/Ping.h"
|
|
|
|
#ifndef MOZ_GLEAN_ANDROID
|
|
# include "mozilla/AppShutdown.h"
|
|
# include "mozilla/ClearOnShutdown.h"
|
|
#endif
|
|
#include "mozilla/Components.h"
|
|
#include "nsIClassInfoImpl.h"
|
|
#include "nsString.h"
|
|
|
|
namespace mozilla::glean {
|
|
|
|
namespace impl {
|
|
|
|
#ifndef MOZ_GLEAN_ANDROID
|
|
using CallbackMapType = nsTHashMap<uint32_t, PingTestCallback>;
|
|
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));
|
|
}
|
|
#endif
|
|
|
|
void Ping::Submit(const nsACString& aReason) const {
|
|
#ifdef MOZ_GLEAN_ANDROID
|
|
Unused << mId;
|
|
#else
|
|
{
|
|
GetCallbackMapLock().apply([&](auto& lock) {
|
|
auto callback = lock.ref()->Extract(mId);
|
|
if (callback) {
|
|
callback.extract()(aReason);
|
|
}
|
|
});
|
|
}
|
|
fog_submit_ping_by_id(mId, &aReason);
|
|
#endif
|
|
}
|
|
|
|
void Ping::TestBeforeNextSubmit(PingTestCallback&& aCallback) const {
|
|
#ifdef MOZ_GLEAN_ANDROID
|
|
return;
|
|
#else
|
|
{
|
|
GetCallbackMapLock().apply(
|
|
[&](auto& lock) { lock.ref()->InsertOrUpdate(mId, aCallback); });
|
|
}
|
|
#endif
|
|
}
|
|
|
|
} // namespace impl
|
|
|
|
NS_IMPL_CLASSINFO(GleanPing, nullptr, 0, {0})
|
|
NS_IMPL_ISUPPORTS_CI(GleanPing, nsIGleanPing)
|
|
|
|
NS_IMETHODIMP
|
|
GleanPing::Submit(const nsACString& aReason) {
|
|
mPing.Submit(aReason);
|
|
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.
|
|
nsCOMPtr<nsIGleanPingTestCallback> callback = aCallback;
|
|
mPing.TestBeforeNextSubmit(
|
|
[callback](const nsACString& aReason) { callback->Call(aReason); });
|
|
return NS_OK;
|
|
}
|
|
|
|
} // namespace mozilla::glean
|