Files
tubestation/toolkit/components/glean/bindings/private/Ping.cpp
Chris H-C 0b70e659ac Bug 1763593 - GIFFT mirroring is now fallible r=janerik
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
2022-04-14 15:17:29 +00:00

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