JSBool JSHistogram_Snapshot(JSContext *cx, unsigned argc, jsval *vp) { JSObject *obj = JS_THIS_OBJECT(cx, vp); if (!obj) { return JS_FALSE; } Histogram *h = static_cast<Histogram*>(JS_GetPrivate(obj)); JSObject *snapshot = JS_NewObject(cx, nullptr, nullptr, nullptr); if (!snapshot) return JS_FALSE; JS::AutoObjectRooter sroot(cx, snapshot); switch (ReflectHistogramSnapshot(cx, snapshot, h)) { case REFLECT_FAILURE: return JS_FALSE; case REFLECT_CORRUPT: JS_ReportError(cx, "Histogram is corrupt"); return JS_FALSE; case REFLECT_OK: JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(snapshot)); return JS_TRUE; default: MOZ_NOT_REACHED("unhandled reflection status"); return JS_FALSE; } }
NS_IMETHODIMP TelemetryImpl::GetHistogramSnapshots(JSContext *cx, jsval *ret) { JSObject *root_obj = JS_NewObject(cx, NULL, NULL, NULL); if (!root_obj) return NS_ERROR_FAILURE; *ret = OBJECT_TO_JSVAL(root_obj); StatisticsRecorder::Histograms h; StatisticsRecorder::GetHistograms(&h); for (StatisticsRecorder::Histograms::iterator it = h.begin(); it != h.end();++it) { Histogram *h = *it; JSObject *hobj = JS_NewObject(cx, NULL, NULL, NULL); if (!(hobj && JS_DefineProperty(cx, root_obj, h->histogram_name().c_str(), OBJECT_TO_JSVAL(hobj), NULL, NULL, JSPROP_ENUMERATE) && ReflectHistogramSnapshot(cx, hobj, h))) { return NS_ERROR_FAILURE; } } MutexAutoLock hashMutex(mHashMutex); // Add info about slow SQL queries on the main thread if (!AddSlowSQLInfo(cx, root_obj, true)) return NS_ERROR_FAILURE; // Add info about slow SQL queries on other threads if (!AddSlowSQLInfo(cx, root_obj, false)) return NS_ERROR_FAILURE; return NS_OK; }
bool TelemetryImpl::AddonHistogramReflector(AddonHistogramEntryType *entry, JSContext *cx, JSObject *obj) { // Never even accessed the histogram. if (!entry->mData.h) { return true; } JSObject *snapshot = JS_NewObject(cx, NULL, NULL, NULL); js::AutoObjectRooter r(cx, snapshot); switch (ReflectHistogramSnapshot(cx, snapshot, entry->mData.h)) { case REFLECT_FAILURE: case REFLECT_CORRUPT: return false; case REFLECT_OK: const nsACString &histogramName = entry->GetKey(); if (!JS_DefineProperty(cx, obj, PromiseFlatCString(histogramName).get(), OBJECT_TO_JSVAL(snapshot), NULL, NULL, JSPROP_ENUMERATE)) { return false; } break; } return true; }
NS_IMETHODIMP TelemetryImpl::GetHistogramSnapshots(JSContext *cx, jsval *ret) { JSObject *root_obj = JS_NewObject(cx, NULL, NULL, NULL); if (!root_obj) return NS_ERROR_FAILURE; *ret = OBJECT_TO_JSVAL(root_obj); // Ensure that all the HISTOGRAM_FLAG histograms have been created, so // that their values are snapshotted. for (size_t i = 0; i < Telemetry::HistogramCount; ++i) { if (gHistograms[i].histogramType == nsITelemetry::HISTOGRAM_FLAG) { Histogram *h; DebugOnly<nsresult> rv = GetHistogramByEnumId(Telemetry::ID(i), &h); MOZ_ASSERT(NS_SUCCEEDED(rv)); } }; StatisticsRecorder::Histograms hs; StatisticsRecorder::GetHistograms(&hs); // We identify corrupt histograms first, rather than interspersing it // in the loop below, to ensure that our corruption statistics don't // depend on histogram enumeration order. // // Of course, we hope that all of these corruption-statistics // histograms are not themselves corrupt... IdentifyCorruptHistograms(hs); // OK, now we can actually reflect things. for (HistogramIterator it = hs.begin(); it != hs.end(); ++it) { Histogram *h = *it; if (!ShouldReflectHistogram(h) || IsEmpty(h)) { continue; } JSObject *hobj = JS_NewObject(cx, NULL, NULL, NULL); if (!hobj) { return NS_ERROR_FAILURE; } JS::AutoObjectRooter root(cx, hobj); switch (ReflectHistogramSnapshot(cx, hobj, h)) { case REFLECT_CORRUPT: // We can still hit this case even if ShouldReflectHistograms // returns true. The histogram lies outside of our control // somehow; just skip it. continue; case REFLECT_FAILURE: return NS_ERROR_FAILURE; case REFLECT_OK: if (!JS_DefineProperty(cx, root_obj, h->histogram_name().c_str(), OBJECT_TO_JSVAL(hobj), NULL, NULL, JSPROP_ENUMERATE)) { return NS_ERROR_FAILURE; } } } return NS_OK; }
JSBool JSHistogram_Snapshot(JSContext *cx, uintN argc, jsval *vp) { JSObject *obj = JS_THIS_OBJECT(cx, vp); Histogram *h = static_cast<Histogram*>(JS_GetPrivate(cx, obj)); JSObject *snapshot = JS_NewObject(cx, NULL, NULL, NULL); if (!snapshot) return JS_FALSE; JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(snapshot)); return ReflectHistogramSnapshot(cx, snapshot, h); }
NS_IMETHODIMP TelemetryImpl::GetHistogramSnapshots(JSContext *cx, jsval *ret) { JSObject *root_obj = JS_NewObject(cx, NULL, NULL, NULL); if (!root_obj) return NS_ERROR_FAILURE; *ret = OBJECT_TO_JSVAL(root_obj); StatisticsRecorder::Histograms hs; StatisticsRecorder::GetHistograms(&hs); // We identify corrupt histograms first, rather than interspersing it // in the loop below, to ensure that our corruption statistics don't // depend on histogram enumeration order. // // Of course, we hope that all of these corruption-statistics // histograms are not themselves corrupt... IdentifyCorruptHistograms(hs); // OK, now we can actually reflect things. for (HistogramIterator it = hs.begin(); it != hs.end(); ++it) { Histogram *h = *it; if (!ShouldReflectHistogram(h)) { continue; } JSObject *hobj = JS_NewObject(cx, NULL, NULL, NULL); if (!hobj) { return NS_ERROR_FAILURE; } switch (ReflectHistogramSnapshot(cx, hobj, h)) { case REFLECT_CORRUPT: // We can still hit this case even if ShouldReflectHistograms // returns true. The histogram lies outside of our control // somehow; just skip it. continue; case REFLECT_FAILURE: return NS_ERROR_FAILURE; case REFLECT_OK: if (!JS_DefineProperty(cx, root_obj, h->histogram_name().c_str(), OBJECT_TO_JSVAL(hobj), NULL, NULL, JSPROP_ENUMERATE)) { return NS_ERROR_FAILURE; } } } return NS_OK; }
bool TelemetryImpl::AddonHistogramReflector(AddonHistogramEntryType *entry, JSContext *cx, JSObject *obj) { AddonHistogramInfo &info = entry->mData; // Never even accessed the histogram. if (!info.h) { // Have to force creation of HISTOGRAM_FLAG histograms. if (info.histogramType != nsITelemetry::HISTOGRAM_FLAG) return true; if (!CreateHistogramForAddon(entry->GetKey(), info)) { return false; } } if (IsEmpty(info.h)) { return true; } JSObject *snapshot = JS_NewObject(cx, NULL, NULL, NULL); if (!snapshot) { // Just consider this to be skippable. return true; } JS::AutoObjectRooter r(cx, snapshot); switch (ReflectHistogramSnapshot(cx, snapshot, info.h)) { case REFLECT_FAILURE: case REFLECT_CORRUPT: return false; case REFLECT_OK: const nsACString &histogramName = entry->GetKey(); if (!JS_DefineProperty(cx, obj, PromiseFlatCString(histogramName).get(), OBJECT_TO_JSVAL(snapshot), NULL, NULL, JSPROP_ENUMERATE)) { return false; } break; } return true; }
NS_IMETHODIMP TelemetryImpl::GetHistogramSnapshots(JSContext *cx, jsval *ret) { JSObject *root_obj = JS_NewObject(cx, NULL, NULL, NULL); if (!root_obj) return NS_ERROR_FAILURE; *ret = OBJECT_TO_JSVAL(root_obj); StatisticsRecorder::Histograms h; StatisticsRecorder::GetHistograms(&h); for (StatisticsRecorder::Histograms::iterator it = h.begin(); it != h.end();++it) { Histogram *h = *it; JSObject *hobj = JS_NewObject(cx, NULL, NULL, NULL); if (!(hobj && JS_DefineProperty(cx, root_obj, h->histogram_name().c_str(), OBJECT_TO_JSVAL(hobj), NULL, NULL, JSPROP_ENUMERATE) && ReflectHistogramSnapshot(cx, hobj, h))) { return NS_ERROR_FAILURE; } } return NS_OK; }