Bug 1262008 - Add WebGL failure causes to telemetry ping. r=dvander
MozReview-Commit-ID: 9IVhVNGmaAP
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -760,16 +760,20 @@ gfxPlatform::Init()
uint32_t skiaCacheSize = GetSkiaGlyphCacheSize();
if (skiaCacheSize != kDefaultGlyphCacheSize) {
SkGraphics::SetFontCacheLimit(skiaCacheSize);
}
#endif
ScrollMetadata::sNullMetadata = new ScrollMetadata();
ClearOnShutdown(&ScrollMetadata::sNullMetadata);
+
+ if (obs) {
+ obs->NotifyObservers(nullptr, "gfx-features-ready", nullptr);
+ }
}
static bool sLayersIPCIsUp = false;
void
gfxPlatform::Shutdown()
{
if (!gPlatform) {
--- a/toolkit/components/telemetry/TelemetryEnvironment.jsm
+++ b/toolkit/components/telemetry/TelemetryEnvironment.jsm
@@ -176,21 +176,22 @@ const PREF_DISTRIBUTOR_CHANNEL = "app.di
const PREF_HOTFIX_LASTVERSION = "extensions.hotfix.lastVersion";
const PREF_APP_PARTNER_BRANCH = "app.partner.";
const PREF_PARTNER_ID = "mozilla.partner.id";
const PREF_UPDATE_ENABLED = "app.update.enabled";
const PREF_UPDATE_AUTODOWNLOAD = "app.update.auto";
const PREF_SEARCH_COHORT = "browser.search.cohort";
const PREF_E10S_COHORT = "e10s.rollout.cohort";
+const COMPOSITOR_CREATED_TOPIC = "compositor:created";
+const DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC = "distribution-customization-complete";
const EXPERIMENTS_CHANGED_TOPIC = "experiments-changed";
+const GFX_FEATURES_READY_TOPIC = "gfx-features-ready";
const SEARCH_ENGINE_MODIFIED_TOPIC = "browser-search-engine-modified";
const SEARCH_SERVICE_TOPIC = "browser-search-service";
-const COMPOSITOR_CREATED_TOPIC = "compositor:created";
-const DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC = "distribution-customization-complete";
/**
* Enforces the parameter to a boolean value.
* @param aValue The input value.
* @return {Boolean|Object} If aValue is a boolean or a number, returns its truthfulness
* value. Otherwise, return null.
*/
function enforceBoolean(aValue) {
@@ -897,30 +898,31 @@ EnvironmentCache.prototype = {
if(!("requiresRestart" in options) || !options.requiresRestart) {
Preferences.ignore(pref, this._onPrefChanged, this);
}
}
},
_addObservers: function () {
// Watch the search engine change and service topics.
+ Services.obs.addObserver(this, COMPOSITOR_CREATED_TOPIC, false);
+ Services.obs.addObserver(this, DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC, false);
+ Services.obs.addObserver(this, GFX_FEATURES_READY_TOPIC, false);
Services.obs.addObserver(this, SEARCH_ENGINE_MODIFIED_TOPIC, false);
Services.obs.addObserver(this, SEARCH_SERVICE_TOPIC, false);
- Services.obs.addObserver(this, COMPOSITOR_CREATED_TOPIC, false);
- Services.obs.addObserver(this, DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC, false);
},
_removeObservers: function () {
- // Remove the search engine change and service observers.
- Services.obs.removeObserver(this, SEARCH_ENGINE_MODIFIED_TOPIC);
- Services.obs.removeObserver(this, SEARCH_SERVICE_TOPIC);
Services.obs.removeObserver(this, COMPOSITOR_CREATED_TOPIC);
try {
Services.obs.removeObserver(this, DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC);
} catch(ex) {}
+ Services.obs.removeObserver(this, GFX_FEATURES_READY_TOPIC);
+ Services.obs.removeObserver(this, SEARCH_ENGINE_MODIFIED_TOPIC);
+ Services.obs.removeObserver(this, SEARCH_SERVICE_TOPIC);
},
observe: function (aSubject, aTopic, aData) {
this._log.trace("observe - aTopic: " + aTopic + ", aData: " + aData);
switch (aTopic) {
case SEARCH_ENGINE_MODIFIED_TOPIC:
if (aData != "engine-current") {
return;
@@ -930,16 +932,17 @@ EnvironmentCache.prototype = {
break;
case SEARCH_SERVICE_TOPIC:
if (aData != "init-complete") {
return;
}
// Now that the search engine init is complete, record the default search choice.
this._updateSearchEngine();
break;
+ case GFX_FEATURES_READY_TOPIC:
case COMPOSITOR_CREATED_TOPIC:
// Full graphics information is not available until we have created at
// least one off-main-thread-composited window. Thus we wait for the
// first compositor to be created and then query nsIGfxInfo again.
this._updateGraphicsFeatures();
break;
case DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC:
// Distribution customizations are applied after final-ui-startup. query
--- a/toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js
+++ b/toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js
@@ -576,16 +576,18 @@ function checkSystemSection(data) {
if (gIsWindows || gIsMac) {
Assert.equal(GFX_VENDOR_ID, gfxData.adapters[0].vendorID);
Assert.equal(GFX_DEVICE_ID, gfxData.adapters[0].deviceID);
}
let features = gfxInfo.getFeatures();
Assert.equal(features.compositor, gfxData.features.compositor);
+ Assert.equal(features.opengl, gfxData.features.opengl);
+ Assert.equal(features.webgl, gfxData.features.webgl);
}
catch (e) {}
}
function checkActiveAddon(data){
let signedState = mozinfo.addon_signing ? "number" : "undefined";
// system add-ons have an undefined signState
if (data.isSystem)
--- a/widget/GfxInfoBase.cpp
+++ b/widget/GfxInfoBase.cpp
@@ -1280,41 +1280,58 @@ GfxInfoBase::BuildFeatureStateLog(JSCont
return;
}
});
return true;
}
void
-GfxInfoBase::DescribeFeatures(JSContext* cx, JS::Handle<JSObject*> aOut)
+GfxInfoBase::DescribeFeatures(JSContext* aCx, JS::Handle<JSObject*> aObj)
{
+ JS::Rooted<JSObject*> obj(aCx);
+
+ InitFeatureObject(aCx, aObj, "opengl", nsIGfxInfo::FEATURE_OPENGL_LAYERS, Nothing(), &obj);
+ InitFeatureObject(aCx, aObj, "webgl", nsIGfxInfo::FEATURE_WEBGL_OPENGL, Nothing(), &obj);
}
bool
GfxInfoBase::InitFeatureObject(JSContext* aCx,
JS::Handle<JSObject*> aContainer,
const char* aName,
- mozilla::gfx::FeatureStatus aFeatureStatus,
+ int32_t aFeature,
+ Maybe<mozilla::gfx::FeatureStatus> aFeatureStatus,
JS::MutableHandle<JSObject*> aOutObj)
{
JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
if (!obj) {
return false;
}
- const char* status = FeatureStatusToString(aFeatureStatus);
+ nsCString failureId = NS_LITERAL_CSTRING("OK");
+ int32_t unused;
+ if (!NS_SUCCEEDED(GetFeatureStatus(aFeature, failureId, &unused))) {
+ return false;
+ }
// Set "status".
- {
+ if (aFeatureStatus) {
+ const char* status = FeatureStatusToString(aFeatureStatus.value());
+
JS::Rooted<JSString*> str(aCx, JS_NewStringCopyZ(aCx, status));
JS::Rooted<JS::Value> val(aCx, JS::StringValue(str));
JS_SetProperty(aCx, obj, "status", val);
}
+ if (!failureId.IsEmpty()) {
+ JS::Rooted<JSString*> str(aCx, JS_NewStringCopyZ(aCx, failureId.get()));
+ JS::Rooted<JS::Value> val(aCx, JS::StringValue(str));
+ JS_SetProperty(aCx, obj, "failureId", val);
+ }
+
// Add the feature object to the container.
{
JS::Rooted<JS::Value> val(aCx, JS::ObjectValue(*obj));
JS_SetProperty(aCx, aContainer, aName, val);
}
aOutObj.set(obj);
return true;
--- a/widget/GfxInfoBase.h
+++ b/widget/GfxInfoBase.h
@@ -3,30 +3,31 @@
*
* 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/. */
#ifndef __mozilla_widget_GfxInfoBase_h__
#define __mozilla_widget_GfxInfoBase_h__
-#include "nsIGfxInfo.h"
-#include "nsCOMPtr.h"
-#include "nsIObserver.h"
-#include "nsWeakReference.h"
#include "GfxDriverInfo.h"
-#include "nsTArray.h"
-#include "nsString.h"
#include "GfxInfoCollector.h"
+#include "gfxFeature.h"
#include "gfxTelemetry.h"
-#include "gfxFeature.h"
-#include "nsIGfxInfoDebug.h"
-#include "mozilla/Mutex.h"
#include "js/Value.h"
#include "mozilla/Attributes.h"
+#include "mozilla/Maybe.h"
+#include "mozilla/Mutex.h"
+#include "nsCOMPtr.h"
+#include "nsIGfxInfo.h"
+#include "nsIGfxInfoDebug.h"
+#include "nsIObserver.h"
+#include "nsString.h"
+#include "nsTArray.h"
+#include "nsWeakReference.h"
namespace mozilla {
namespace widget {
class GfxInfoBase : public nsIGfxInfo,
public nsIObserver,
public nsSupportsWeakReference
#ifdef DEBUG
@@ -102,17 +103,18 @@ protected:
// (while subclasses check for more specific ones).
virtual const nsTArray<GfxDriverInfo>& GetGfxDriverInfo() = 0;
virtual void DescribeFeatures(JSContext* aCx, JS::Handle<JSObject*> obj);
bool InitFeatureObject(
JSContext* aCx,
JS::Handle<JSObject*> aContainer,
const char* aName,
- mozilla::gfx::FeatureStatus aFeatureStatus,
+ int32_t aFeature,
+ Maybe<mozilla::gfx::FeatureStatus> aKnownStatus,
JS::MutableHandle<JSObject*> aOutObj);
private:
virtual int32_t FindBlocklistedDeviceInList(const nsTArray<GfxDriverInfo>& aDriverInfo,
nsAString& aSuggestedVersion,
int32_t aFeature,
nsACString &aFailureId,
OperatingSystem os);
--- a/widget/nsIGfxInfo.idl
+++ b/widget/nsIGfxInfo.idl
@@ -162,16 +162,17 @@ interface nsIGfxInfo : nsISupports
// Return an object describing all features that have been configured:
//
// "features": [
// // For each feature:
// {
// "name": <string>,
// "description": <string>,
// "status": <string>,
+ // "failureId": <string>, // optional, only covers static failure currently.
// "log": [
// // One or more log entries, the first denotes the default value.
// {
// "type": <string>, // "base", "user", "env", or "runtime"
// "status": <string>,
// "message": <string> // Set unless type is "base" and status is "available".
// }
// ]
--- a/widget/windows/GfxInfo.cpp
+++ b/widget/windows/GfxInfo.cpp
@@ -1253,22 +1253,26 @@ GfxInfo::FindMonitors(JSContext* aCx, JS
JS_SetElement(aCx, aOutArray, deviceCount++, element);
}
return NS_OK;
}
void
GfxInfo::DescribeFeatures(JSContext* aCx, JS::Handle<JSObject*> aObj)
{
+ // Add the platform neutral features
+ GfxInfoBase::DescribeFeatures(aCx, aObj);
+
JS::Rooted<JSObject*> obj(aCx);
gfxWindowsPlatform* platform = gfxWindowsPlatform::GetPlatform();
gfx::FeatureStatus d3d11 = gfxConfig::GetValue(Feature::D3D11_COMPOSITING);
- if (!InitFeatureObject(aCx, aObj, "d3d11", d3d11, &obj)) {
+ if (!InitFeatureObject(aCx, aObj, "d3d11", FEATURE_DIRECT3D_11_ANGLE,
+ Some(d3d11), &obj)) {
return;
}
if (d3d11 == gfx::FeatureStatus::Available) {
JS::Rooted<JS::Value> val(aCx, JS::Int32Value(platform->GetD3D11Version()));
JS_SetProperty(aCx, obj, "version", val);
val = JS::BooleanValue(platform->IsWARP());
JS_SetProperty(aCx, obj, "warp", val);
@@ -1285,17 +1289,18 @@ GfxInfo::DescribeFeatures(JSContext* aCx
}
}
val = JS::BooleanValue(blacklisted);
JS_SetProperty(aCx, obj, "blacklisted", val);
}
gfx::FeatureStatus d2d = gfxConfig::GetValue(Feature::DIRECT2D);
- if (!InitFeatureObject(aCx, aObj, "d2d", d2d, &obj)) {
+ if (!InitFeatureObject(aCx, aObj, "d2d", nsIGfxInfo::FEATURE_DIRECT2D,
+ Some(d2d), &obj)) {
return;
}
{
const char* version = "1.1";
JS::Rooted<JSString*> str(aCx, JS_NewStringCopyZ(aCx, version));
JS::Rooted<JS::Value> val(aCx, JS::StringValue(str));
JS_SetProperty(aCx, obj, "version", val);
}