mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 932092 - Part 2: support natively sending UI telemetry events from Java. r=mfinkle
This commit is contained in:
parent
7a2f204cff
commit
fb6845b990
@ -429,7 +429,7 @@ abstract public class BrowserApp extends GeckoApp
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
mAboutHomeStartupTimer = new Telemetry.Timer("FENNEC_STARTUP_TIME_ABOUTHOME");
|
||||
mAboutHomeStartupTimer = new Telemetry.UptimeTimer("FENNEC_STARTUP_TIME_ABOUTHOME");
|
||||
|
||||
final Intent intent = getIntent();
|
||||
|
||||
|
@ -1153,8 +1153,8 @@ public abstract class GeckoApp
|
||||
}
|
||||
|
||||
// The clock starts...now. Better hurry!
|
||||
mJavaUiStartupTimer = new Telemetry.Timer("FENNEC_STARTUP_TIME_JAVAUI");
|
||||
mGeckoReadyStartupTimer = new Telemetry.Timer("FENNEC_STARTUP_TIME_GECKOREADY");
|
||||
mJavaUiStartupTimer = new Telemetry.UptimeTimer("FENNEC_STARTUP_TIME_JAVAUI");
|
||||
mGeckoReadyStartupTimer = new Telemetry.UptimeTimer("FENNEC_STARTUP_TIME_GECKOREADY");
|
||||
|
||||
Intent intent = getIntent();
|
||||
String args = intent.getStringExtra("args");
|
||||
|
@ -43,7 +43,7 @@ public class GeckoEvent {
|
||||
private static final String LOGTAG = "GeckoEvent";
|
||||
|
||||
// Make sure to keep these values in sync with the enum in
|
||||
// AndroidGeckoEvent in widget/android/AndroidJavaWrapper.h
|
||||
// AndroidGeckoEvent in widget/android/AndroidJavaWrappers.h
|
||||
@JNITarget
|
||||
private enum NativeGeckoEvent {
|
||||
NATIVE_POKE(0),
|
||||
@ -76,13 +76,16 @@ public class GeckoEvent {
|
||||
TELEMETRY_HISTOGRAM_ADD(37),
|
||||
PREFERENCES_OBSERVE(39),
|
||||
PREFERENCES_GET(40),
|
||||
PREFERENCES_REMOVE_OBSERVERS(41);
|
||||
PREFERENCES_REMOVE_OBSERVERS(41),
|
||||
TELEMETRY_UI_SESSION_START(42),
|
||||
TELEMETRY_UI_SESSION_STOP(43),
|
||||
TELEMETRY_UI_EVENT(44);
|
||||
|
||||
public final int value;
|
||||
|
||||
private NativeGeckoEvent(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -747,6 +750,30 @@ public class GeckoEvent {
|
||||
return event;
|
||||
}
|
||||
|
||||
public static GeckoEvent createTelemetryUISessionStartEvent(String session, long timestamp) {
|
||||
GeckoEvent event = new GeckoEvent(NativeGeckoEvent.TELEMETRY_UI_SESSION_START);
|
||||
event.mCharacters = session;
|
||||
event.mTime = timestamp;
|
||||
return event;
|
||||
}
|
||||
|
||||
public static GeckoEvent createTelemetryUISessionStopEvent(String session, String reason, long timestamp) {
|
||||
GeckoEvent event = new GeckoEvent(NativeGeckoEvent.TELEMETRY_UI_SESSION_STOP);
|
||||
event.mCharacters = session;
|
||||
event.mCharactersExtra = reason;
|
||||
event.mTime = timestamp;
|
||||
return event;
|
||||
}
|
||||
|
||||
public static GeckoEvent createTelemetryUIEvent(String action, String method, long timestamp, String extras) {
|
||||
GeckoEvent event = new GeckoEvent(NativeGeckoEvent.TELEMETRY_UI_EVENT);
|
||||
event.mData = action;
|
||||
event.mCharacters = method;
|
||||
event.mCharactersExtra = extras;
|
||||
event.mTime = timestamp;
|
||||
return event;
|
||||
}
|
||||
|
||||
public void setAckNeeded(boolean ackNeeded) {
|
||||
mAckNeeded = ackNeeded;
|
||||
}
|
||||
|
@ -5,31 +5,52 @@
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* All telemetry times are relative to one of two clocks:
|
||||
*
|
||||
* * Real time since the device was booted, including deep sleep. Use this
|
||||
* as a substitute for wall clock.
|
||||
* * Uptime since the device was booted, excluding deep sleep. Use this to
|
||||
* avoid timing a user activity when their phone is in their pocket!
|
||||
*
|
||||
* The majority of methods in this class are defined in terms of real time.
|
||||
*/
|
||||
@RobocopTarget
|
||||
public class Telemetry {
|
||||
private static final String LOGTAG = "Telemetry";
|
||||
|
||||
public static long uptime() {
|
||||
return SystemClock.uptimeMillis();
|
||||
}
|
||||
|
||||
public static long realtime() {
|
||||
return SystemClock.elapsedRealtime();
|
||||
}
|
||||
|
||||
// Define new histograms in:
|
||||
// toolkit/components/telemetry/Histograms.json
|
||||
public static void HistogramAdd(String name,
|
||||
int value) {
|
||||
GeckoEvent event =
|
||||
GeckoEvent.createTelemetryHistogramAddEvent(name, value);
|
||||
public static void HistogramAdd(String name, int value) {
|
||||
GeckoEvent event = GeckoEvent.createTelemetryHistogramAddEvent(name, value);
|
||||
GeckoAppShell.sendEventToGecko(event);
|
||||
}
|
||||
|
||||
public static class Timer {
|
||||
private long mStartTime;
|
||||
private String mName;
|
||||
private boolean mHasFinished;
|
||||
public abstract static class Timer {
|
||||
private final long mStartTime;
|
||||
private final String mName;
|
||||
|
||||
private volatile boolean mHasFinished = false;
|
||||
private volatile long mElapsed = -1;
|
||||
|
||||
protected abstract long now();
|
||||
|
||||
public Timer(String name) {
|
||||
mName = name;
|
||||
mStartTime = SystemClock.uptimeMillis();
|
||||
mHasFinished = false;
|
||||
mStartTime = now();
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
@ -44,17 +65,76 @@ public class Telemetry {
|
||||
// Only the first stop counts.
|
||||
if (mHasFinished) {
|
||||
return;
|
||||
} else {
|
||||
mHasFinished = true;
|
||||
}
|
||||
|
||||
final long elapsed = SystemClock.uptimeMillis() - mStartTime;
|
||||
mElapsed = elapsed;
|
||||
if (elapsed < Integer.MAX_VALUE) {
|
||||
HistogramAdd(mName, (int)(elapsed));
|
||||
} else {
|
||||
Log.e(LOGTAG, "Duration of " + elapsed + " ms is too long to add to histogram.");
|
||||
mHasFinished = true;
|
||||
|
||||
final long elapsed = now() - mStartTime;
|
||||
if (elapsed < 0) {
|
||||
Log.e(LOGTAG, "Current time less than start time -- clock shenanigans?");
|
||||
return;
|
||||
}
|
||||
|
||||
mElapsed = elapsed;
|
||||
if (elapsed > Integer.MAX_VALUE) {
|
||||
Log.e(LOGTAG, "Duration of " + elapsed + "ms is too great to add to histogram.");
|
||||
return;
|
||||
}
|
||||
|
||||
HistogramAdd(mName, (int)(elapsed));
|
||||
}
|
||||
}
|
||||
|
||||
public static class RealtimeTimer extends Timer {
|
||||
public RealtimeTimer(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long now() {
|
||||
return Telemetry.realtime();
|
||||
}
|
||||
}
|
||||
|
||||
public static class UptimeTimer extends Timer {
|
||||
public UptimeTimer(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long now() {
|
||||
return Telemetry.uptime();
|
||||
}
|
||||
}
|
||||
|
||||
public static void startUISession(String sessionName) {
|
||||
GeckoEvent event = GeckoEvent.createTelemetryUISessionStartEvent(sessionName, realtime());
|
||||
GeckoAppShell.sendEventToGecko(event);
|
||||
}
|
||||
|
||||
public static void stopUISession(String sessionName, String reason) {
|
||||
GeckoEvent event = GeckoEvent.createTelemetryUISessionStopEvent(sessionName, reason, realtime());
|
||||
GeckoAppShell.sendEventToGecko(event);
|
||||
}
|
||||
|
||||
public static void sendUIEvent(String action, String method, long timestamp, String extras) {
|
||||
GeckoEvent event = GeckoEvent.createTelemetryUIEvent(action, method, timestamp, extras);
|
||||
GeckoAppShell.sendEventToGecko(event);
|
||||
}
|
||||
|
||||
public static void sendUIEvent(String action, String method, long timestamp) {
|
||||
sendUIEvent(action, method, timestamp, null);
|
||||
}
|
||||
|
||||
public static void sendUIEvent(String action, String method, String extras) {
|
||||
sendUIEvent(action, method, realtime(), extras);
|
||||
}
|
||||
|
||||
public static void sendUIEvent(String action, String method) {
|
||||
sendUIEvent(action, method, realtime(), null);
|
||||
}
|
||||
|
||||
public static void sendUIEvent(String action) {
|
||||
sendUIEvent(action, null, realtime(), null);
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ skip-if = processor == "x86"
|
||||
[testBrowserProvider]
|
||||
[testBrowserSearchVisibility]
|
||||
[testClearPrivateData]
|
||||
[testDeviceSearchEngine]
|
||||
[testDistribution]
|
||||
[testDoorHanger]
|
||||
[testFindInPage]
|
||||
@ -32,14 +31,11 @@ skip-if = processor == "x86"
|
||||
skip-if = processor == "x86"
|
||||
[testInputUrlBar]
|
||||
[testJarReader]
|
||||
[testJNI]
|
||||
[testLinkContextMenu]
|
||||
[testLoad]
|
||||
[testMailToContextMenu]
|
||||
[testMasterPassword]
|
||||
# [testMozPay] # see bug 945675
|
||||
[testNewTab]
|
||||
[testOrderedBroadcast]
|
||||
[testOverscroll]
|
||||
[testPanCorrectness]
|
||||
# disabled on x86 only; bug 927476
|
||||
@ -58,7 +54,6 @@ skip-if = processor == "x86"
|
||||
[testSessionOOMSave]
|
||||
[testSessionOOMRestore]
|
||||
[testSettingsMenuItems]
|
||||
[testSharedPreferences]
|
||||
# [testShareLink] # see bug 915897
|
||||
[testSystemPages]
|
||||
# disabled on x86 only; bug 907383
|
||||
@ -66,6 +61,13 @@ skip-if = processor == "x86"
|
||||
# [testThumbnails] # see bug 813107
|
||||
# [testVkbOverlap] # see bug 907274
|
||||
|
||||
# Using JavascriptTest
|
||||
[testDeviceSearchEngine]
|
||||
[testJNI]
|
||||
# [testMozPay] # see bug 945675
|
||||
[testOrderedBroadcast]
|
||||
[testSharedPreferences]
|
||||
[testUITelemetry]
|
||||
|
||||
# Used for Talos, please don't use in mochitest
|
||||
#[testPan]
|
||||
|
38
mobile/android/base/tests/testUITelemetry.java
Normal file
38
mobile/android/base/tests/testUITelemetry.java
Normal file
@ -0,0 +1,38 @@
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import org.mozilla.gecko.Telemetry;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class testUITelemetry extends JavascriptTest {
|
||||
public testUITelemetry() {
|
||||
super("testUITelemetry.js");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testJavascript() throws Exception {
|
||||
blockForGeckoReady();
|
||||
Log.i("GeckoTest", "Adding telemetry events.");
|
||||
|
||||
try {
|
||||
Telemetry.sendUIEvent("enone", "method0");
|
||||
Telemetry.startUISession("foo");
|
||||
Telemetry.sendUIEvent("efoo", "method1");
|
||||
Telemetry.startUISession("foo");
|
||||
Telemetry.sendUIEvent("efoo", "method2");
|
||||
Telemetry.startUISession("bar");
|
||||
Telemetry.sendUIEvent("efoobar", "method3", "foobarextras");
|
||||
Telemetry.stopUISession("foo", "reasonfoo");
|
||||
Telemetry.sendUIEvent("ebar", "method4", "barextras");
|
||||
Telemetry.stopUISession("bar", "reasonbar");
|
||||
Telemetry.stopUISession("bar", "reasonbar2");
|
||||
Telemetry.sendUIEvent("enone", "method5");
|
||||
} catch (Exception e) {
|
||||
Log.e("GeckoTest", "Oops.", e);
|
||||
}
|
||||
|
||||
Log.i("GeckoTest", "Running remaining JS test code.");
|
||||
super.testJavascript();
|
||||
}
|
||||
}
|
||||
|
63
mobile/android/base/tests/testUITelemetry.js
Normal file
63
mobile/android/base/tests/testUITelemetry.js
Normal file
@ -0,0 +1,63 @@
|
||||
// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
|
||||
/* 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/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function do_check_array_eq(a1, a2) {
|
||||
do_check_eq(a1.length, a2.length);
|
||||
for (let i = 0; i < a1.length; ++i) {
|
||||
do_check_eq(a1[i], a2[i]);
|
||||
}
|
||||
}
|
||||
|
||||
add_test(function test_telemetry_events() {
|
||||
let bridge = Components.classes["@mozilla.org/android/bridge;1"]
|
||||
.getService(Components.interfaces.nsIAndroidBridge);
|
||||
let obsXPCOM = bridge.browserApp.getUITelemetryObserver();
|
||||
do_check_true(!!obsXPCOM);
|
||||
|
||||
let obs = obsXPCOM.wrappedJSObject;
|
||||
do_check_true(!!obs);
|
||||
|
||||
let measurements = obs.getUIMeasurements();
|
||||
|
||||
let expected = [
|
||||
["event", "enone", "method0", [], null],
|
||||
["event", "efoo", "method1", ["foo"], null],
|
||||
["event", "efoo", "method2", ["foo"], null],
|
||||
["event", "efoobar", "method3", ["foo", "bar"], "foobarextras"],
|
||||
["session", "foo", "reasonfoo"],
|
||||
["event", "ebar", "method4", ["bar"], "barextras"],
|
||||
["session", "bar", "reasonbar"],
|
||||
["event", "enone", "method5", [], null],
|
||||
];
|
||||
|
||||
do_check_eq(expected.length, measurements.length);
|
||||
|
||||
for (let i = 0; i < measurements.length; ++i) {
|
||||
let m = measurements[i];
|
||||
|
||||
let type = m[0];
|
||||
if (type == "event") {
|
||||
let [type, action, method, sessions, extras] = expected[i];
|
||||
do_check_eq(m.action, action);
|
||||
do_check_eq(m.method, method);
|
||||
do_check_array_eq(m.sessions, sessions);
|
||||
do_check_eq(m.extras, extras);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type == "session") {
|
||||
let [type, name, reason] = expected[i];
|
||||
do_check_eq(m.name, name);
|
||||
do_check_eq(m.reason, method);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
run_next_test();
|
@ -338,7 +338,6 @@ var BrowserApp = {
|
||||
DesktopUserAgent.init();
|
||||
Distribution.init();
|
||||
Tabs.init();
|
||||
UITelemetry.init();
|
||||
#ifdef ACCESSIBILITY
|
||||
AccessFu.attach(window);
|
||||
#endif
|
||||
@ -1530,6 +1529,10 @@ var BrowserApp = {
|
||||
return this.getTabForId(tabId);
|
||||
},
|
||||
|
||||
getUITelemetryObserver: function() {
|
||||
return UITelemetry;
|
||||
},
|
||||
|
||||
getPreferences: function getPreferences(requestId, prefNames, count) {
|
||||
this.handlePreferencesRequest(requestId, prefNames, false);
|
||||
},
|
||||
|
@ -7,80 +7,78 @@
|
||||
const Cu = Components.utils;
|
||||
|
||||
this.EXPORTED_SYMBOLS = [
|
||||
"UITelemetry"
|
||||
"UITelemetry",
|
||||
];
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
/**
|
||||
* UITelemetry is a helper JSM used to record UI specific telemetry events.
|
||||
*
|
||||
* It implements nsIUITelemetryObserver, defined in nsIAndroidBridge.idl.
|
||||
*/
|
||||
this.UITelemetry = {
|
||||
this.UITelemetry = Object.freeze({
|
||||
_activeSessions: {},
|
||||
_measurements: [],
|
||||
|
||||
measurements: [],
|
||||
|
||||
init: function init() {
|
||||
Services.obs.addObserver(this, "UITelemetry:Event", false);
|
||||
Services.obs.addObserver(this, "UITelemetry:Session", false);
|
||||
},
|
||||
|
||||
observe: function observe(aMessage, aTopic, aData) {
|
||||
switch(aTopic) {
|
||||
case "UITelemetry:Event":
|
||||
let args = JSON.parse(aData);
|
||||
this.addEvent(args.action, args.method, args.extras, args.timestamp);
|
||||
break;
|
||||
case "UITelemetry:Session":
|
||||
args = JSON.parse(aData);
|
||||
let sessionName = args.name;
|
||||
let timestamp = args.timestamp;
|
||||
if (args.state == "start") {
|
||||
this.startSession(sessionName, timestamp);
|
||||
} else if (args.state == "stop") {
|
||||
this.stopSession(sessionName, timestamp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/**
|
||||
* This exists exclusively for testing -- our events are not intended to
|
||||
* be retrieved via an XPCOM interface.
|
||||
*/
|
||||
get wrappedJSObject() {
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a single event described by an action, and the calling method. Optional
|
||||
* paramaters are extras and timestamp. The timestamp will be set here if it is
|
||||
* not passed in by the caller.
|
||||
* Holds the functions that provide UITelemetry's simple
|
||||
* measurements. Those functions are mapped to unique names,
|
||||
* and should be registered with addSimpleMeasureFunction.
|
||||
*/
|
||||
addEvent: function addEvent(aAction, aMethod, aExtras, aTimestamp) {
|
||||
let timestamp = aTimestamp || Date.now();
|
||||
_simpleMeasureFunctions: {},
|
||||
|
||||
/**
|
||||
* Adds a single event described by a timestamp, an action, and the calling
|
||||
* method.
|
||||
*
|
||||
* Optionally provide a string 'extras', which will be recorded as part of
|
||||
* the event.
|
||||
*
|
||||
* All extant sessions will be recorded by name for each event.
|
||||
*/
|
||||
addEvent: function(aAction, aMethod, aTimestamp, aExtras) {
|
||||
let sessions = Object.keys(this._activeSessions);
|
||||
let aEvent = {
|
||||
type: "event",
|
||||
action: aAction,
|
||||
method: aMethod,
|
||||
timestamp: timestamp
|
||||
sessions: sessions,
|
||||
timestamp: aTimestamp,
|
||||
};
|
||||
|
||||
if (aExtras) aEvent.extras = aExtras;
|
||||
this._logEvent(aEvent);
|
||||
},
|
||||
if (aExtras) {
|
||||
aEvent.extras = aExtras;
|
||||
}
|
||||
|
||||
activeSessions: {},
|
||||
this._recordEvent(aEvent);
|
||||
},
|
||||
|
||||
/**
|
||||
* Begins tracking a session by storing a timestamp for session start.
|
||||
*/
|
||||
startSession: function startSession(aName, aTimestamp) {
|
||||
let timestamp = aTimestamp || Date.now();
|
||||
if (this.activeSessions[aName]) {
|
||||
// Do not overwrite a previous event start if it already exsts.
|
||||
return;
|
||||
}
|
||||
this.activeSessions[aName] = timestamp;
|
||||
startSession: function(aName, aTimestamp) {
|
||||
if (this._activeSessions[aName]) {
|
||||
// Do not overwrite a previous event start if it already exists.
|
||||
return;
|
||||
}
|
||||
this._activeSessions[aName] = aTimestamp;
|
||||
},
|
||||
|
||||
/**
|
||||
* Tracks the end of a session with a timestamp.
|
||||
*/
|
||||
stopSession: function stopSession(aName, aTimestamp) {
|
||||
let timestamp = aTimestamp || Date.now();
|
||||
let sessionStart = this.activeSessions[aName];
|
||||
stopSession: function(aName, aReason, aTimestamp) {
|
||||
let sessionStart = this._activeSessions[aName];
|
||||
delete this._activeSessions[aName];
|
||||
|
||||
if (!sessionStart) {
|
||||
Services.console.logStringMessage("UITelemetry error: no session [" + aName + "] to stop!");
|
||||
@ -90,24 +88,18 @@ this.UITelemetry = {
|
||||
let aEvent = {
|
||||
type: "session",
|
||||
name: aName,
|
||||
reason: aReason,
|
||||
start: sessionStart,
|
||||
end: timestamp
|
||||
end: aTimestamp,
|
||||
};
|
||||
|
||||
this._logEvent(aEvent);
|
||||
this._recordEvent(aEvent);
|
||||
},
|
||||
|
||||
_logEvent: function sendEvent(aEvent) {
|
||||
this.measurements.push(aEvent);
|
||||
_recordEvent: function(aEvent) {
|
||||
this._measurements.push(aEvent);
|
||||
},
|
||||
|
||||
/**
|
||||
* Holds the functions that provide UITelemety's simple
|
||||
* measurements. Those functions are mapped to unique names,
|
||||
* and should be registered with addSimpleMeasureFunction.
|
||||
*/
|
||||
_simpleMeasureFuncs: {},
|
||||
|
||||
/**
|
||||
* Called by TelemetryPing to populate the simple measurement
|
||||
* blob. This function will iterate over all functions added
|
||||
@ -116,8 +108,8 @@ this.UITelemetry = {
|
||||
*/
|
||||
getSimpleMeasures: function() {
|
||||
let result = {};
|
||||
for (let name in this._simpleMeasureFuncs) {
|
||||
result[name] = this._simpleMeasureFuncs[name]();
|
||||
for (let name in this._simpleMeasureFunctions) {
|
||||
result[name] = this._simpleMeasureFunctions[name]();
|
||||
}
|
||||
return result;
|
||||
},
|
||||
@ -132,22 +124,22 @@ this.UITelemetry = {
|
||||
* registered for it.
|
||||
*/
|
||||
addSimpleMeasureFunction: function(aName, aFunction) {
|
||||
if (aName in this._simpleMeasureFuncs) {
|
||||
throw new Error("A simple measurement function is already registered for "
|
||||
+ aName);
|
||||
}
|
||||
if (!aFunction || typeof aFunction !== 'function') {
|
||||
throw new Error("A function must be passed as the second argument.");
|
||||
if (aName in this._simpleMeasureFunctions) {
|
||||
throw new Error("A simple measurement function is already registered for " + aName);
|
||||
}
|
||||
|
||||
this._simpleMeasureFuncs[aName] = aFunction;
|
||||
if (!aFunction || typeof aFunction !== 'function') {
|
||||
throw new Error("addSimpleMeasureFunction called with non-function argument.");
|
||||
}
|
||||
|
||||
this._simpleMeasureFunctions[aName] = aFunction;
|
||||
},
|
||||
|
||||
removeSimpleMeasureFunction: function(aName) {
|
||||
delete this._simpleMeasureFuncs[aName];
|
||||
delete this._simpleMeasureFunctions[aName];
|
||||
},
|
||||
|
||||
getUIMeasurements: function getUIMeasurements() {
|
||||
return this.measurements.slice();
|
||||
return this._measurements.slice();
|
||||
}
|
||||
};
|
||||
});
|
||||
|
@ -564,6 +564,27 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj)
|
||||
break;
|
||||
}
|
||||
|
||||
case TELEMETRY_UI_SESSION_START: {
|
||||
ReadCharactersField(jenv);
|
||||
mTime = jenv->GetLongField(jobj, jTimeField);
|
||||
break;
|
||||
}
|
||||
|
||||
case TELEMETRY_UI_SESSION_STOP: {
|
||||
ReadCharactersField(jenv);
|
||||
ReadCharactersExtraField(jenv);
|
||||
mTime = jenv->GetLongField(jobj, jTimeField);
|
||||
break;
|
||||
}
|
||||
|
||||
case TELEMETRY_UI_EVENT: {
|
||||
ReadCharactersField(jenv);
|
||||
ReadCharactersExtraField(jenv);
|
||||
ReadDataField(jenv);
|
||||
mTime = jenv->GetLongField(jobj, jTimeField);
|
||||
break;
|
||||
}
|
||||
|
||||
case PREFERENCES_OBSERVE:
|
||||
case PREFERENCES_GET: {
|
||||
ReadStringArray(mPrefNames, jenv, jPrefNamesField);
|
||||
|
@ -686,11 +686,14 @@ public:
|
||||
PREFERENCES_OBSERVE = 39,
|
||||
PREFERENCES_GET = 40,
|
||||
PREFERENCES_REMOVE_OBSERVERS = 41,
|
||||
TELEMETRY_UI_SESSION_START = 42,
|
||||
TELEMETRY_UI_SESSION_STOP = 43,
|
||||
TELEMETRY_UI_EVENT = 44,
|
||||
dummy_java_enum_list_end
|
||||
};
|
||||
|
||||
enum {
|
||||
// Memory pressue levels, keep in sync with those in MemoryMonitor.java
|
||||
// Memory pressure levels. Keep these in sync with those in MemoryMonitor.java.
|
||||
MEMORY_PRESSURE_NONE = 0,
|
||||
MEMORY_PRESSURE_CLEANUP = 1,
|
||||
MEMORY_PRESSURE_LOW = 2,
|
||||
|
@ -259,8 +259,7 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
|
||||
NativeEventCallback();
|
||||
break;
|
||||
|
||||
case AndroidGeckoEvent::SENSOR_EVENT:
|
||||
{
|
||||
case AndroidGeckoEvent::SENSOR_EVENT: {
|
||||
InfallibleTArray<float> values;
|
||||
mozilla::hal::SensorType type = (mozilla::hal::SensorType) curEvent->Flags();
|
||||
|
||||
@ -371,7 +370,6 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
|
||||
|
||||
case AndroidGeckoEvent::VIEWPORT:
|
||||
case AndroidGeckoEvent::BROADCAST: {
|
||||
|
||||
if (curEvent->Characters().Length() == 0)
|
||||
break;
|
||||
|
||||
@ -385,6 +383,57 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
|
||||
break;
|
||||
}
|
||||
|
||||
case AndroidGeckoEvent::TELEMETRY_UI_SESSION_STOP: {
|
||||
if (curEvent->Characters().Length() == 0)
|
||||
break;
|
||||
|
||||
nsCOMPtr<nsIUITelemetryObserver> obs;
|
||||
mBrowserApp->GetUITelemetryObserver(getter_AddRefs(obs));
|
||||
if (!obs)
|
||||
break;
|
||||
|
||||
obs->StopSession(
|
||||
nsString(curEvent->Characters()).get(),
|
||||
nsString(curEvent->CharactersExtra()).get(),
|
||||
curEvent->Time()
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case AndroidGeckoEvent::TELEMETRY_UI_SESSION_START: {
|
||||
if (curEvent->Characters().Length() == 0)
|
||||
break;
|
||||
|
||||
nsCOMPtr<nsIUITelemetryObserver> obs;
|
||||
mBrowserApp->GetUITelemetryObserver(getter_AddRefs(obs));
|
||||
if (!obs)
|
||||
break;
|
||||
|
||||
obs->StartSession(
|
||||
nsString(curEvent->Characters()).get(),
|
||||
curEvent->Time()
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case AndroidGeckoEvent::TELEMETRY_UI_EVENT: {
|
||||
if (curEvent->Characters().Length() == 0)
|
||||
break;
|
||||
|
||||
nsCOMPtr<nsIUITelemetryObserver> obs;
|
||||
mBrowserApp->GetUITelemetryObserver(getter_AddRefs(obs));
|
||||
if (!obs)
|
||||
break;
|
||||
|
||||
obs->AddEvent(
|
||||
nsString(curEvent->Data()).get(),
|
||||
nsString(curEvent->Characters()).get(),
|
||||
curEvent->Time(),
|
||||
nsString(curEvent->CharactersExtra()).get()
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case AndroidGeckoEvent::LOAD_URI: {
|
||||
nsCOMPtr<nsICommandLineRunner> cmdline
|
||||
(do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
|
||||
|
@ -11,7 +11,20 @@ interface nsIBrowserTab : nsISupports {
|
||||
readonly attribute float scale;
|
||||
};
|
||||
|
||||
[scriptable, uuid(7508b826-4129-40a0-91da-2a6bba33681f)]
|
||||
[scriptable, uuid(08426a73-e70b-4680-9282-630932e2b2bb)]
|
||||
interface nsIUITelemetryObserver : nsISupports {
|
||||
void startSession(in wstring name,
|
||||
in unsigned long timestamp);
|
||||
void stopSession(in wstring name,
|
||||
in wstring reason,
|
||||
in unsigned long timestamp);
|
||||
void addEvent(in wstring action,
|
||||
in wstring method,
|
||||
in unsigned long timestamp,
|
||||
in wstring extras);
|
||||
};
|
||||
|
||||
[scriptable, uuid(c31331d2-afad-460f-9c66-728b8c838cec)]
|
||||
interface nsIAndroidBrowserApp : nsISupports {
|
||||
nsIBrowserTab getBrowserTab(in int32_t tabId);
|
||||
void getPreferences(in int32_t requestId,
|
||||
@ -21,7 +34,9 @@ interface nsIAndroidBrowserApp : nsISupports {
|
||||
[array, size_is(count)] in wstring prefNames,
|
||||
in unsigned long count);
|
||||
void removePreferenceObservers(in int32_t requestId);
|
||||
nsIUITelemetryObserver getUITelemetryObserver();
|
||||
};
|
||||
|
||||
[scriptable, uuid(59cfcb35-69b7-47b2-8155-32b193272666)]
|
||||
interface nsIAndroidViewport : nsISupports {
|
||||
readonly attribute float x;
|
||||
|
Loading…
Reference in New Issue
Block a user