1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
/* -*- 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/Glean.h"
#include "bindings/private/Common.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/dom/DOMJSClass.h"
#include "mozilla/dom/GleanBinding.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/glean/bindings/Category.h"
#include "mozilla/glean/bindings/GleanJSMetricsLookup.h"
#include "mozilla/glean/bindings/jog/jog_ffi_generated.h"
#include "mozilla/glean/bindings/jog/JOG.h"
#include "MainThreadUtils.h"
#include "nsContentUtils.h"
#include "js/PropertyAndElement.h" // JS_DefineProperty
namespace mozilla::dom {
bool GleanWebidlEnabled(JSContext* aCx, JSObject* aObj) {
// Glean is needed in ChromeOnly contexts and also in privileged about pages.
nsIPrincipal* principal = nsContentUtils::SubjectPrincipal(aCx);
if (principal->IsSystemPrincipal()) {
return true;
}
uint32_t flags = 0;
if (NS_FAILED(principal->GetAboutModuleFlags(&flags))) {
return false;
}
return flags & nsIAboutModule::IS_SECURE_CHROME_UI;
}
} // namespace mozilla::dom
namespace mozilla::glean {
// Whether the runtime-registered metrics should be treated as comprehensive,
// or additive. If comprehensive, a metric not registered at runtime is a
// metric that doesn't exist. If additive, a metric not registered at runtime
// may still exist if it was registered at compile time.
// If we're supporting Artefact Builds, we treat them as comprehensive.
// Threading: Must only be read or written to on the main thread.
static bool gRuntimeMetricsComprehensive = false;
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Glean, mParent)
NS_IMPL_CYCLE_COLLECTING_ADDREF(Glean)
NS_IMPL_CYCLE_COLLECTING_RELEASE(Glean)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Glean)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
JSObject* Glean::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
return dom::GleanImpl_Binding::Wrap(aCx, this, aGivenProto);
}
Glean::Glean(nsIGlobalObject* aGlobal) : mParent(aGlobal) {}
// static
bool Glean::DefineGlean(JSContext* aCx, JS::Handle<JSObject*> aGlobal) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(JS::GetClass(aGlobal)->flags & JSCLASS_DOM_GLOBAL,
"Passed object is not a global object!");
nsIGlobalObject* global = xpc::CurrentNativeGlobal(aCx);
if (NS_WARN_IF(!global)) {
return false;
}
JS::Rooted<JS::Value> glean(aCx);
js::AssertSameCompartment(aCx, aGlobal);
auto impl = MakeRefPtr<Glean>(global);
if (!dom::GetOrCreateDOMReflector(aCx, impl.get(), &glean)) {
return false;
}
return JS_DefineProperty(aCx, aGlobal, "Glean", glean, JSPROP_ENUMERATE);
}
already_AddRefed<Category> Glean::NamedGetter(const nsAString& aName,
bool& aFound) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(IsCamelCase(aName), "NamedGetter expects CamelCase");
JOG::EnsureRuntimeMetricsRegistered();
NS_ConvertUTF16toUTF8 categoryName(aName);
if (JOG::HasCategory(categoryName)) {
aFound = true;
return MakeAndAddRef<Category>(std::move(categoryName), mParent);
}
if (gRuntimeMetricsComprehensive) {
// This category might be built-in, but since the runtime metrics are
// comprehensive, that just signals that the category was removed locally.
aFound = false;
return nullptr;
}
Maybe<uint32_t> categoryIdx = CategoryByNameLookup(categoryName);
if (categoryIdx.isNothing()) {
aFound = false;
return nullptr;
}
aFound = true;
nsDependentCString name(GetCategoryName(categoryIdx.value()));
return MakeAndAddRef<Category>(std::move(name), mParent);
}
bool Glean::NameIsEnumerable(const nsAString& aName) { return false; }
void Glean::GetSupportedNames(nsTArray<nsString>& aNames) {
JOG::GetCategoryNames(aNames);
if (!JOG::AreRuntimeMetricsComprehensive()) {
for (category_entry_t entry : sCategoryByNameLookupEntries) {
const char* categoryName = GetCategoryName(entry);
aNames.AppendElement()->AssignASCII(categoryName);
}
}
}
// static
void Glean::TestSetRuntimeMetricsComprehensive(bool aIsComprehensive) {
MOZ_ASSERT(NS_IsMainThread());
gRuntimeMetricsComprehensive = aIsComprehensive;
}
} // namespace mozilla::glean
|