/* 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/FOG.h"
#include "mozilla/AppShutdown.h"
#include "mozilla/Atomics.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/FOGIPC.h"
#include "mozilla/glean/bindings/Common.h"
#include "mozilla/glean/bindings/jog/jog_ffi_generated.h"
#include "mozilla/glean/bindings/jog/JOG.h"
#include "mozilla/glean/fog_ffi_generated.h"
#include "mozilla/glean/GleanMetrics.h"
#include "mozilla/HelperMacros.h"
#include "mozilla/Logging.h"
#include "mozilla/MozPromise.h"
#include "mozilla/ProfilerMarkers.h"
#include "mozilla/ShutdownPhase.h"
#include "nsContentUtils.h"
#include "nsDirectoryServiceDefs.h"
#include "nsDirectoryServiceUtils.h"
#include "nsIFOG.h"
#include "nsIFile.h"
#include "nsIUserIdleService.h"
#include "nsServiceManagerUtils.h"
#include "xpcpublic.h"
namespace mozilla {
using mozilla::LogLevel;
static mozilla::LazyLogModule sLog(
"fog");
using glean::LogToBrowserConsole;
#ifdef MOZ_GLEAN_ANDROID
// Defined by `glean-core`. We reexport it here for later use.
extern "C" NS_EXPORT
void glean_enable_logging(
void);
// Workaround to force a re-export of the `no_mangle` symbols from `glean-core`
//
// Due to how linking works and hides symbols the symbols from `glean-core`
// might not be re-exported and thus not usable. By forcing use of _at least
// one_ symbol in an exported function the functions will also be rexported.
//
// See also https://github.com/rust-lang/rust/issues/50007
extern "C" NS_EXPORT
void _fog_force_reexport_donotcall(
void) {
glean_enable_logging();
}
#endif
static StaticRefPtr<FOG> gFOG;
static mozilla::Atomic<
bool> gInitializeCalled(
false);
// We wait for 5s of idle before dumping IPC and flushing ping data to disk.
// This number hasn't been tuned, so if you have a reason to change it,
// please by all means do.
const uint32_t kIdleSecs =
5;
// static
void FOG::SetApplicationID(
const nsACString& aAppId) {
MOZ_ASSERT(XRE_IsParentProcess());
glean::impl::fog_set_application_id(PromiseFlatCString(aAppId).get());
}
// static
already_AddRefed<FOG> FOG::GetSingleton() {
if (gFOG) {
return do_AddRef(gFOG);
}
MOZ_LOG(sLog, LogLevel::Debug, (
"FOG::GetSingleton()"));
gFOG =
new FOG();
gFOG->InitMemoryReporter();
if (XRE_IsParentProcess()) {
nsresult rv;
nsCOMPtr<nsIUserIdleService> idleService =
do_GetService(
"@mozilla.org/widget/useridleservice;1", &rv);
if (NS_FAILED(rv) && xpc::IsInAutomation()) {
// bug 1955429: In some tests the idle service is unavailable.
// They aren't even testing FOG, so let it slide.
return do_AddRef(gFOG);
}
NS_ENSURE_SUCCESS(rv, nullptr);
MOZ_ASSERT(idleService);
if (NS_WARN_IF(NS_FAILED(idleService->AddIdleObserver(gFOG, kIdleSecs)))) {
glean::fog::failed_idle_registration.Set(true);
}
RunOnShutdown(
[&] {
nsresult rv;
nsCOMPtr<nsIUserIdleService> idleService =
do_GetService(
"@mozilla.org/widget/useridleservice;1", &rv);
if (NS_SUCCEEDED(rv)) {
MOZ_ASSERT(idleService);
(
void)idleService->RemoveIdleObserver(gFOG, kIdleSecs);
}
bool initOnShutdown =
Preferences::GetBool(
"telemetry.fog.init_on_shutdown", true);
if (initOnShutdown && !gInitializeCalled) {
gInitializeCalled = true;
// Assuming default data path and application id.
// Consumers using non defaults _must_ initialize FOG explicitly.
MOZ_LOG(sLog, LogLevel::Debug,
(
"Init not called. Init-ing in shutdown"));
glean::fog::inits_during_shutdown.Add(
1);
// It's enough to call init before shutting down.
// We don't need to (and can't) wait for it to complete.
glean::impl::fog_init(&VoidCString(), &VoidCString(),
false);
}
gFOG->Shutdown();
gFOG = nullptr;
},
ShutdownPhase::XPCOMShutdown);
}
return do_AddRef(gFOG);
}
void FOG::Shutdown() {
MOZ_ASSERT(XRE_IsParentProcess());
UnregisterWeakMemoryReporter(this);
glean::impl::fog_shutdown();
}
// This allows us to know it's too late to submit a ping in Rust.
extern "C" bool FOG_TooLateToSend(
void) {
MOZ_ASSERT(XRE_IsParentProcess());
return AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownNetTeardown);
}
// This allows us to pass the configurable maximum ping limit (in pings per
// minute) to Rust. Default value is 15.
extern "C" uint32_t FOG_MaxPingLimit(
void) {
return Preferences::GetInt(
"telemetry.glean.internal.maxPingsPerMinute",
15);
}
// Called when knowing if we're in automation is necessary.
extern "C" bool FOG_IPCIsInAutomation(
void) {
return xpc::IsInAutomation(); }
NS_IMETHODIMP
FOG::InitializeFOG(
const nsACString& aDataPathOverride,
const nsACString& aAppIdOverride,
const bool aDisableInternalPings) {
MOZ_ASSERT(XRE_IsParentProcess());
gInitializeCalled = true;
RunOnShutdown(
[&] {
if (Preferences::GetBool(
"telemetry.glean.internal.finalInactive",
false)) {
glean::impl::fog_internal_glean_handle_client_inactive();
}
},
ShutdownPhase::AppShutdownConfirmed);
nsresult rv = glean::impl::fog_init(&aDataPathOverride, &aAppIdOverride,
aDisableInternalPings);
NS_ENSURE_SUCCESS(rv, rv);
#ifndef MOZ_BUILD_APP_IS_BROWSER
if (xpc::IsInAutomation()) {
ApplyInterestingServerKnobs();
}
#endif
return rv;
}
/**
* Enable desired metrics, so that tests work even if some metrics were
* disabled.
* @see JOG::EnsureRuntimeMetricsRegistered()
*/
// static
bool FOG::ApplyInterestingServerKnobs() {
// The config we need to process were placed in GreD in
// interesting_serverknobs.json.
// That file was generated by
// toolkit/components/glean/build_scripts/glean_parser_ext/interesting_serverknobs.py
nsCOMPtr<nsIFile> knobsFile;
if (NS_WARN_IF(NS_FAILED(
NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(knobsFile))))) {
return false;
}
if (NS_WARN_IF(
NS_FAILED(knobsFile->Append(u
"interesting_serverknobs.json"_ns)))) {
return false;
}
// We _could_ read the file and apply it here in C++ land,
// but let's use Rust because (among other reasons) it's more fun.
nsAutoString knobsfileString;
if (NS_WARN_IF(NS_FAILED(knobsFile->GetPath(knobsfileString)))) {
return false;
}
if (!glean::impl::fog_apply_serverknobs(&knobsfileString)) {
return false;
}
return true;
}
// Expose MOZ_APP_VERSION_DISPLAY to Rust
extern "C" const char* FOG_MozAppVersionDisplay(
void) {
return MOZ_STRINGIFY(MOZ_APP_VERSION_DISPLAY);
}
NS_IMETHODIMP
FOG::RegisterCustomPings() {
MOZ_ASSERT(XRE_IsParentProcess());
glean::impl::fog_register_pings();
return NS_OK;
}
NS_IMETHODIMP
FOG::SetLogPings(
bool aEnableLogPings) {
#ifdef MOZ_GLEAN_ANDROID
return NS_OK;
#else
MOZ_ASSERT(XRE_IsParentProcess());
return glean::impl::fog_set_log_pings(aEnableLogPings);
#endif
}
NS_IMETHODIMP
FOG::SetTagPings(
const nsACString& aDebugTag) {
#ifdef MOZ_GLEAN_ANDROID
return NS_OK;
#else
MOZ_ASSERT(XRE_IsParentProcess());
return glean::impl::fog_set_debug_view_tag(&aDebugTag);
#endif
}
NS_IMETHODIMP
FOG::SendPing(
const nsACString& aPingName) {
#ifdef MOZ_GLEAN_ANDROID
return NS_OK;
#else
MOZ_ASSERT(XRE_IsParentProcess());
return glean::impl::fog_submit_ping(&aPingName);
#endif
}
NS_IMETHODIMP
FOG::SetExperimentActive(
const nsACString& aExperimentId,
const nsACString& aBranch, JS::HandleValue aExtra,
JSContext* aCx) {
#ifdef MOZ_GLEAN_ANDROID
NS_WARNING(
"Don't set experiments from Gecko in Android. Ignoring.");
return NS_OK;
#else
MOZ_ASSERT(XRE_IsParentProcess());
nsTArray<nsCString> extraKeys;
nsTArray<nsCString> extraValues;
if (!aExtra.isNullOrUndefined()) {
JS::RootedObject obj(aCx, &aExtra.toObject());
JS::Rooted<JS::IdVector> keys(aCx, JS::IdVector(aCx));
if (!JS_Enumerate(aCx, obj, &keys)) {
LogToBrowserConsole(nsIScriptError::warningFlag,
u
"Failed to enumerate experiment extras object."_ns);
return NS_OK;
}
for (size_t i =
0, n = keys.length(); i < n; i++) {
nsAutoJSCString jsKey;
if (!jsKey.init(aCx, keys[i])) {
LogToBrowserConsole(
nsIScriptError::warningFlag,
u
"Extra dictionary should only contain string keys."_ns);
return NS_OK;
}
JS::Rooted<JS::Value> value(aCx);
if (!JS_GetPropertyById(aCx, obj, keys[i], &value)) {
LogToBrowserConsole(nsIScriptError::warningFlag,
u
"Failed to get experiment extra property."_ns);
return NS_OK;
}
nsAutoJSCString jsValue;
if (!value.isString()) {
LogToBrowserConsole(
nsIScriptError::warningFlag,
u
"Experiment extra properties must have string values."_ns);
return NS_OK;
}
if (!jsValue.init(aCx, value)) {
LogToBrowserConsole(nsIScriptError::warningFlag,
u
"Can't extract experiment extra property"_ns);
return NS_OK;
}
extraKeys.AppendElement(jsKey);
extraValues.AppendElement(jsValue);
}
}
glean::impl::fog_set_experiment_active(&aExperimentId, &aBranch, &extraKeys,
&extraValues);
return NS_OK;
#endif
}
NS_IMETHODIMP
FOG::SetExperimentInactive(
const nsACString& aExperimentId) {
#ifdef MOZ_GLEAN_ANDROID
NS_WARNING(
"Don't unset experiments from Gecko in Android. Ignoring.");
return NS_OK;
#else
MOZ_ASSERT(XRE_IsParentProcess());
glean::impl::fog_set_experiment_inactive(&aExperimentId);
return NS_OK;
#endif
}
NS_IMETHODIMP
FOG::TestGetExperimentData(
const nsACString& aExperimentId, JSContext* aCx,
JS::MutableHandleValue aResult) {
#ifdef MOZ_GLEAN_ANDROID
NS_WARNING(
"Don't test experiments from Gecko in Android. Throwing.");
aResult.set(JS::UndefinedValue());
return NS_ERROR_FAILURE;
#else
MOZ_ASSERT(XRE_IsParentProcess());
if (!glean::impl::fog_test_is_experiment_active(&aExperimentId)) {
aResult.set(JS::UndefinedValue());
return NS_OK;
}
// We could struct-up the branch and extras and do what
// EventMetric::TestGetValue does... but keeping allocation on this side feels
// cleaner to me at the moment.
nsCString branch;
nsTArray<nsCString> extraKeys;
nsTArray<nsCString> extraValues;
glean::impl::fog_test_get_experiment_data(&aExperimentId, &branch, &extraKeys,
&extraValues);
MOZ_ASSERT(extraKeys.Length() == extraValues.Length());
JS::RootedObject jsExperimentDataObj(aCx, JS_NewPlainObject(aCx));
if (NS_WARN_IF(!jsExperimentDataObj)) {
return NS_ERROR_FAILURE;
}
JS::RootedValue jsBranchStr(aCx);
if (!dom::ToJSValue(aCx, branch, &jsBranchStr) ||
!JS_DefineProperty(aCx, jsExperimentDataObj,
"branch", jsBranchStr,
JSPROP_ENUMERATE)) {
NS_WARNING(
"Failed to define branch for experiment data object.");
return NS_ERROR_FAILURE;
}
JS::RootedObject jsExtraObj(aCx, JS_NewPlainObject(aCx));
if (!JS_DefineProperty(aCx, jsExperimentDataObj,
"extra", jsExtraObj,
JSPROP_ENUMERATE)) {
NS_WARNING(
"Failed to define extra for experiment data object.");
return NS_ERROR_FAILURE;
}
for (
unsigned int i =
0; i < extraKeys.Length(); i++) {
JS::RootedValue jsValueStr(aCx);
if (!dom::ToJSValue(aCx, extraValues[i], &jsValueStr) ||
!JS_DefineProperty(aCx, jsExtraObj, extraKeys[i].get(), jsValueStr,
JSPROP_ENUMERATE)) {
NS_WARNING(
"Failed to define extra property for experiment data object.");
return NS_ERROR_FAILURE;
}
}
aResult.setObject(*jsExperimentDataObj);
return NS_OK;
#endif
}
NS_IMETHODIMP
FOG::ApplyServerKnobsConfig(
const nsACString& aJsonConfig) {
#ifdef MOZ_GLEAN_ANDROID
NS_WARNING(
"Don't set metric feature configs from Gecko in Android. Ignoring.");
return NS_OK;
#else
MOZ_ASSERT(XRE_IsParentProcess());
glean::impl::fog_apply_server_knobs_config(&aJsonConfig);
return NS_OK;
#endif
}
NS_IMETHODIMP
FOG::TestFlushAllChildren(JSContext* aCx, mozilla::dom::Promise** aOutPromise) {
MOZ_LOG(sLog, LogLevel::Verbose, (
"FOG::TestFlushAllChildren start"));
TimeStamp before = TimeStamp::Now();
MOZ_ASSERT(XRE_IsParentProcess());
NS_ENSURE_ARG(aOutPromise);
*aOutPromise = nullptr;
nsIGlobalObject* global = xpc::CurrentNativeGlobal(aCx);
if (NS_WARN_IF(!global)) {
MOZ_LOG(sLog, LogLevel::Verbose, (
"Could not get current global"));
return NS_ERROR_FAILURE;
}
ErrorResult erv;
RefPtr<dom::Promise> promise = dom::Promise::Create(global, erv);
if (NS_WARN_IF(erv.Failed())) {
MOZ_LOG(sLog, LogLevel::Debug, (
"Error creating promise"));
return erv.StealNSResult();
}
glean::FlushAndUseFOGData()->Then(
GetCurrentSerialEventTarget(), __func__, [promise, before]() {
MOZ_LOG(sLog, LogLevel::Verbose,
(
"glean::FlushAndUseFOGData completed"));
PROFILER_MARKER_UNTYPED(
"fog.testFlushAllChildren", TEST,
MarkerTiming::IntervalUntilNowFrom(before));
promise->MaybeResolveWithUndefined();
});
promise.forget(aOutPromise);
MOZ_LOG(sLog, LogLevel::Verbose, (
"FOG::TestFlushAllChildren end"));
return NS_OK;
}
NS_IMETHODIMP
FOG::Observe(nsISupports* aSubject,
const char* aTopic,
const char16_t* aData) {
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
// On idle, opportunistically flush child process data to the parent,
// then persist ping-lifetime data to the db.
if (!strcmp(aTopic, OBSERVER_TOPIC_IDLE)) {
glean::FlushAndUseFOGData();
#ifndef MOZ_GLEAN_ANDROID
(
void)glean::impl::fog_persist_ping_lifetime_data();
#endif
}
return NS_OK;
}
NS_IMETHODIMP
FOG::TestResetFOG(
const nsACString& aDataPathOverride,
const nsACString& aAppIdOverride) {
MOZ_ASSERT(XRE_IsParentProcess());
PROFILER_MARKER_UNTYPED(
"fog.testResetFOG", TEST);
nsresult rv =
glean::impl::fog_test_reset(&aDataPathOverride, &aAppIdOverride);
NS_ENSURE_SUCCESS(rv, rv);
#ifndef MOZ_BUILD_APP_IS_BROWSER
if (xpc::IsInAutomation()) {
ApplyInterestingServerKnobs();
}
#endif
return rv;
}
NS_IMETHODIMP
FOG::TestTriggerMetrics(uint32_t aProcessType, JSContext* aCx,
mozilla::dom::Promise** aOutPromise) {
MOZ_ASSERT(XRE_IsParentProcess());
NS_ENSURE_ARG(aOutPromise);
*aOutPromise = nullptr;
nsIGlobalObject* global = xpc::CurrentNativeGlobal(aCx);
if (NS_WARN_IF(!global)) {
return NS_ERROR_FAILURE;
}
ErrorResult erv;
RefPtr<dom::Promise> promise = dom::Promise::Create(global, erv);
if (NS_WARN_IF(erv.Failed())) {
return erv.StealNSResult();
}
glean::TestTriggerMetrics(aProcessType, promise);
promise.forget(aOutPromise);
return NS_OK;
}
NS_IMETHODIMP
FOG::TestRegisterRuntimeMetric(
const nsACString& aType,
const nsACString& aCategory,
const nsACString& aName,
const nsTArray<nsCString>& aPings,
const nsACString& aLifetime,
const bool aDisabled,
const nsACString& aExtraArgs, uint32_t* aMetricIdOut) {
*aMetricIdOut =
0;
*aMetricIdOut = glean::jog::jog_test_register_metric(
&aType, &aCategory, &aName, &aPings, &aLifetime, aDisabled, &aExtraArgs);
return NS_OK;
}
NS_IMETHODIMP
FOG::RegisterRuntimeMetric(
const nsACString& aType,
const nsACString& aCatego
ry,
const nsACString& aName,
const nsTArray<nsCString>& aPings,
const nsACString& aLifetime, const bool aDisabled,
const nsACString& aExtraArgs) {
MOZ_ASSERT(XRE_IsParentProcess());
return glean::jog::jog_register_metric(&aType, &aCategory, &aName, &aPings,
&aLifetime, aDisabled, &aExtraArgs);
}
NS_IMETHODIMP
FOG::TestRegisterRuntimePing(
const nsACString& aName, const bool aIncludeClientId,
const bool aSendIfEmpty, const bool aPreciseTimestamps,
const bool aIncludeInfoSections, const bool aEnabled,
const nsTArray<nsCString>& aSchedulesPings,
const nsTArray<nsCString>& aReasonCodes,
const bool aFollowsCollectionEnabled,
const nsTArray<nsCString>& aUploaderCapabilities, uint32_t* aPingIdOut) {
*aPingIdOut = 0;
*aPingIdOut = glean::jog::jog_test_register_ping(
&aName, aIncludeClientId, aSendIfEmpty, aPreciseTimestamps,
aIncludeInfoSections, aEnabled, &aSchedulesPings, &aReasonCodes,
aFollowsCollectionEnabled, &aUploaderCapabilities);
return NS_OK;
}
NS_IMETHODIMP
FOG::RegisterRuntimePing(const nsACString& aName, const bool aIncludeClientId,
const bool aSendIfEmpty, const bool aPreciseTimestamps,
const bool aIncludeInfoSections, const bool aEnabled,
const nsTArray<nsCString>& aSchedulesPings,
const nsTArray<nsCString>& aReasonCodes,
const bool aFollowsCollectionEnabled,
const nsTArray<nsCString>& aUploaderCapabilities) {
MOZ_ASSERT(XRE_IsParentProcess());
return glean::jog::jog_register_ping(
&aName, aIncludeClientId, aSendIfEmpty, aPreciseTimestamps,
aIncludeInfoSections, aEnabled, &aSchedulesPings, &aReasonCodes,
aFollowsCollectionEnabled, &aUploaderCapabilities);
}
NS_IMETHODIMP
FOG::UpdateAttribution(const nsACString& aSource, const nsACString& aMedium,
constnsACString&aCampaign, const nsACString& aTerm,
const nsACString& aContent) {
MOZ_ASSERT(XRE_IsParentProcess());
glean::impl::FogAttributionMetrics attr{.source = nsCString( *file, You can obtain one at java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 0
. =nsCString(),
.campaign = nsCString(aCampaign),
.term=nsCString(aTerm,
.content = nsCString(aContent)};
glean:impl:fog_update_attributionattr;
return NS_OK;
}
NS_IMETHODIMP
:TestGetAttribution( aCx,JS:utableHandleValue java.lang.StringIndexOutOfBoundsException: Index 73 out of bounds for length 73
#ifdef MOZ_GLEAN_ANDROID
NS_WARNING("'t test Gecko Android .";
aResult.#include "moz/.h"
return;
#else
MOZ_ASSERT(XRE_IsParentProcess());
gleanimpl:FogAttributionMetrics attr;
glean::impl::fog_test_get_attribution".hjava.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 35
JS:RootedObject (,J();
jsAttr,NS_ERROR_FAILURE;
JS:RootedValuejsSourcea)java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32
attr.sourceIsEmpty) java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30
NS_ENSURE_TRUEJS_DefinePropertya source" :NullHandleValue,
JSPROP_ENUMERATE// Defined by `glean-core`. We extern "C" NS_EXPORT void glean_enable_logging(void);
// might not be re-exported and thus not usable. By forcing// one_ symbol in an exported function the functions will also be rexported.
if!::oJSValuea,attrsource,&)|java.lang.StringIndexOutOfBoundsException: Index 60 out of bounds for length 60
aCx ,"" ,
JSPROP_ENUMERATE)) {
NS_WARNING(Failedtodefineattributionsource.;
return NS_ERROR_FAILURE;
}
JS::RootedValue jsMedium
if (attr.medium.IsEmpty()) {
NS_ENSURE_TRUE// This number hasn't been tuned, so if you have a reason to change it,
// please by all means do.
NS_ERROR_FAILURE);
} else if (!dom::ToJSValue(aCx, attr.medium, &java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
!, m"jsMedium,
JSPROP_ENUMERATE)) {
attribution.medium.");
returnjava.lang.StringIndexOutOfBoundsException: Range [1, 2) out of bounds for length 1
}
JS::RootedValue jsCampaign(java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 27
f(attr.campaignIsEmpty()) {
NS_ENSURE_TRUE(JS_DefineProperty(aCx, jsAttr, "campaign",
::NullHandleValue, JSPROP_ENUMERATE),
NS_ERROR_FAILURE);
(aCx, ., &sCampaign)||
!JS_DefineProperty(Cx , "" jsCampaign,
java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 16
"aileddefine ..);
return (NS_FAILED() & xpc:())
}
JS::RootedValue return do_AddRef(gFOG
ifattrterm.IsEmpty(){
(S_DefinePropertyaCx ,"" JS:NullHandleValue
JSPROP_ENUMERATE),
NS_ERROR_FAILURE);
} else if ::fog:failed_idle_registration.Set(true);
!JS_DefineProperty(aCx, jsAttr, "term", jsTerm }
JSPROP_ENUMERATE))){
NS_WARNING" define attribution.term."java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53
return NS_ERROR_FAILURE;
}
JS::RootedValue
ifa.(){
N((,,"ontent,
JS::NullHandleValue, JSPROP_ENUMERATE),
;
if(dom:a,attr..content,&)||
!java.lang.StringIndexOutOfBoundsException: Range [35, 31) out of bounds for length 66
) java.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 52
NS_WARNING(Failed to java.lang.StringIndexOutOfBoundsException: Range [45, 44) out of bounds for length 56
;
}
.(;
return NS_OK,
e/
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
// This allows us to know it's too late to submit a extern"C" bool FOG_TooLateToSend(() {
r AppShutdown:IsInOrBeyond(ShutdownPhase:ppShutdownNetTeardown)
// This allows us to pass the configurable maximum ping limit (in pings per
glean::impl::externC"uint32_t FOG_MaxPingLimit(void){
glean::impl::fog_update_distribution(&dist);
return NS_OK;
}
NS_IMETHODIMP
FOG::java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 1
#MOZ_GLEAN_ANDROID
java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
java.lang.StringIndexOutOfBoundsException: Range [32, 9) out of bounds for length 36
return ;
#lse
MOZ_ASSERT MOZ_ASSERT(XRE_IsParentProcess());
glean::impl:ogDistributionMetrics dist;
glean:impl:fog_test_get_distribution(&dist);
JS::RootedObject jsDist(aCx, JS_NewPlainObject(aCx));
NS_ENSURE_TRUE(jsDist,NS_ERROR_FAILURE);
JS::RootedValue [& {
if (..() {
false {
JSPROP_ENUMERATE,
NS_ERROR_FAILURE);
} else if (!dom::java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 9
!JS_DefineProperty(aCx, jsDist, "name", jsName,
JSPROP_ENUMERATE)) {
.name.");
return NS_ERROR_FAILURE;
}
aResult.setObject(*jsDist);
#ifndef
#endif // MOZ_GLEAN_ANDROID
}
FOG:InitMemoryReporter() { RegisterWeakMemoryReporter(this); }
ALLOC_SIZE_OFjava.lang.StringIndexOutOfBoundsException: Index 42 out of bounds for length 42
MOZ_DEFINE_MALLOC_ENCLOSING_SIZE_OF(FOGMallocEnclosingSizeOf)
// Rust doesn't support weak-linking, so MFBT_API functions like
// moz_malloc_size_of need a C++ wrapper that uses the regular ABI
//
// We're re-using the previously MOZ_DEFINE_MALLOC(_ENCLOSING)_SIZE_OF-defined
// functions here to create symbol visible outside this file (the define creates
// a static function).
extern "C" size_t fog_malloc_size_of(const void* aPtr) {
/
}
extern "C" size_t fog_malloc_enclosing_size_of(const void* aPtr) {
return FOGMallocEnclosingSizeOf(aPtr);
}
NS_IMETHODIMP
FOG: / That file was generated by
bool aAnonymize){
mozilla::MallocSizeOf aMallocSizeOf<> java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30
("xplicit/impl",KIND_HEAP,UNITS_BYTES,
aMallocSizeOf(this),
"Memory used return false;
glean::impl: }
java.lang.StringIndexOutOfBoundsException: Range [15, 8) out of bounds for length 15
}
if(S_WARN_IF(S_FAILED(->etPathknobsfileString)){
/java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24