mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-18 15:55:36 +00:00
Bug 1205835 - Add TelemetryPingGenerator for core pings. r=rnewman
--HG-- extra : commitid : Fcv0mHGrnsq extra : rebase_source : a7eaa66686a398d2e75000bc97346889ec107c18
This commit is contained in:
parent
63f3fa53d1
commit
1fee6bfb4c
@ -38,12 +38,18 @@ import android.app.Activity;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.support.annotation.WorkerThread;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
public final class GeckoProfile {
|
||||
private static final String LOGTAG = "GeckoProfile";
|
||||
|
||||
// The path in the profile to the file containing the client ID.
|
||||
private static final String CLIENT_ID_FILE_PATH = "datareporting/state.json";
|
||||
// In the client ID file, the attribute title in the JSON object containing the client ID value.
|
||||
private static final String CLIENT_ID_JSON_ATTR = "clientID";
|
||||
|
||||
// Only tests should need to do this.
|
||||
// We can default this to AppConstants.RELEASE_BUILD once we fix Bug 1069687.
|
||||
private static volatile boolean sAcceptDirectoryChanges = true;
|
||||
@ -588,6 +594,39 @@ public final class GeckoProfile {
|
||||
return new File(f, aFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the Gecko client ID from the filesystem.
|
||||
*
|
||||
* This method assumes the client ID is located in a file at a hard-coded path within the profile. The format of
|
||||
* this file is a JSONObject which at the bottom level contains a String -> String mapping containing the client ID.
|
||||
*
|
||||
* WARNING: the platform provides a JSM to retrieve the client ID [1] and this would be a
|
||||
* robust way to access it. However, we don't want to rely on Gecko running in order to get
|
||||
* the client ID so instead we access the file this module accesses directly. However, it's
|
||||
* possible the format of this file (and the access calls in the jsm) will change, leaving
|
||||
* this code to fail.
|
||||
*
|
||||
* TODO: Write tests to prevent regressions. Mention them here. Test both file location and file format.
|
||||
*
|
||||
* [1]: https://mxr.mozilla.org/mozilla-central/source/toolkit/modules/ClientID.jsm
|
||||
*/
|
||||
@WorkerThread
|
||||
public String getClientId() throws IOException {
|
||||
final String clientIdFileContents;
|
||||
try {
|
||||
clientIdFileContents = readFile(CLIENT_ID_FILE_PATH);
|
||||
} catch (final IOException e) {
|
||||
throw new IOException("Could not read client ID file to retrieve client ID", e);
|
||||
}
|
||||
|
||||
try {
|
||||
final org.json.JSONObject json = new org.json.JSONObject(clientIdFileContents);
|
||||
return json.getString(CLIENT_ID_JSON_ATTR);
|
||||
} catch (final JSONException e) {
|
||||
throw new IOException("Could not parse JSON to retrieve client ID", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the session file to the backup session file.
|
||||
*
|
||||
|
@ -0,0 +1,25 @@
|
||||
/* 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/. */
|
||||
|
||||
package org.mozilla.gecko.telemetry;
|
||||
|
||||
public class TelemetryConstants {
|
||||
|
||||
public static class CorePing {
|
||||
private CorePing() { /* To prevent instantiation */ }
|
||||
|
||||
public static final String NAME = "core";
|
||||
public static final int VERSION_VALUE = 1;
|
||||
public static final String OS_VALUE = "Android";
|
||||
|
||||
public static final String ARCHITECTURE = "arch";
|
||||
public static final String CLIENT_ID = "clientId";
|
||||
public static final String DEVICE = "device";
|
||||
public static final String LOCALE = "locale";
|
||||
public static final String OS_ATTR = "os";
|
||||
public static final String OS_VERSION = "osversion";
|
||||
public static final String SEQ = "seq";
|
||||
public static final String VERSION_ATTR = "v";
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
* 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/. */
|
||||
|
||||
package org.mozilla.gecko.telemetry;
|
||||
|
||||
import org.mozilla.gecko.sync.ExtendedJSONObject;
|
||||
|
||||
/**
|
||||
* Container for telemetry data and the data necessary to upload it.
|
||||
*/
|
||||
public class TelemetryPing {
|
||||
private final String url;
|
||||
private final ExtendedJSONObject payload;
|
||||
|
||||
public TelemetryPing(final String url, final ExtendedJSONObject payload) {
|
||||
this.url = url;
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
public String getURL() { return url; }
|
||||
public ExtendedJSONObject getPayload() { return payload; }
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
* 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/. */
|
||||
|
||||
package org.mozilla.gecko.telemetry;
|
||||
|
||||
import android.os.Build;
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.mozilla.gecko.AppConstants;
|
||||
import org.mozilla.gecko.Locales;
|
||||
import org.mozilla.gecko.sync.ExtendedJSONObject;
|
||||
import org.mozilla.gecko.telemetry.TelemetryConstants.CorePing;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
|
||||
/**
|
||||
* A class with static methods to generate the various Java-created Telemetry pings to upload to the telemetry server.
|
||||
*/
|
||||
public class TelemetryPingGenerator {
|
||||
|
||||
// In the server url, the initial path directly after the "scheme://host:port/"
|
||||
private static final String SERVER_INITIAL_PATH = "submit/telemetry";
|
||||
|
||||
/**
|
||||
* Returns a url of the format:
|
||||
* http://hostname/submit/telemetry/docId/docType/appName/appVersion/appUpdateChannel/appBuildID
|
||||
*
|
||||
* @param docId A unique document ID for the ping associated with the upload to this server
|
||||
* @param serverURLSchemeHostPort The server url with the scheme, host, and port (e.g. "http://mozilla.org:80")
|
||||
* @param docType The name of the ping (e.g. "main")
|
||||
* @return a url at which to POST the telemetry data to
|
||||
*/
|
||||
private static String getTelemetryServerURL(final String docId, final String serverURLSchemeHostPort,
|
||||
final String docType) {
|
||||
final String appName = AppConstants.MOZ_APP_BASENAME;
|
||||
final String appVersion = AppConstants.MOZ_APP_VERSION;
|
||||
final String appUpdateChannel = AppConstants.MOZ_UPDATE_CHANNEL;
|
||||
final String appBuildId = AppConstants.MOZ_APP_BUILDID;
|
||||
|
||||
// The compiler will optimize a single String concatenation into a StringBuilder statement.
|
||||
// If you change this `return`, be sure to keep it as a single statement to keep it optimized!
|
||||
return serverURLSchemeHostPort + '/' +
|
||||
SERVER_INITIAL_PATH + '/' +
|
||||
docId + '/' +
|
||||
docType + '/' +
|
||||
appName + '/' +
|
||||
appVersion + '/' +
|
||||
appUpdateChannel + '/' +
|
||||
appBuildId + '/';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param docId A unique document ID for the ping associated with the upload to this server
|
||||
* @param clientId The client ID of this profile (from Gecko)
|
||||
* @param serverURLSchemeHostPort The server url with the scheme, host, and port (e.g. "http://mozilla.org:80")
|
||||
* @throws IOException when client ID could not be created
|
||||
*/
|
||||
public static TelemetryPing createCorePing(final String docId, final String clientId,
|
||||
final String serverURLSchemeHostPort, final int seq) {
|
||||
final String serverURL = getTelemetryServerURL(docId, serverURLSchemeHostPort, CorePing.NAME);
|
||||
final ExtendedJSONObject payload = createCorePingPayload(clientId, seq);
|
||||
return new TelemetryPing(serverURL, payload);
|
||||
}
|
||||
|
||||
private static ExtendedJSONObject createCorePingPayload(final String clientId, final int seq) {
|
||||
final ExtendedJSONObject ping = new ExtendedJSONObject();
|
||||
ping.put(CorePing.VERSION_ATTR, CorePing.VERSION_VALUE);
|
||||
ping.put(CorePing.OS_ATTR, CorePing.OS_VALUE);
|
||||
|
||||
// We limit the device descriptor to 32 characters because it can get long. We give fewer characters to the
|
||||
// manufacturer because we're less likely to have manufacturers with similar names than we are for a
|
||||
// manufacturer to have two devices with the similar names (e.g. Galaxy S6 vs. Galaxy Note 6).
|
||||
final String deviceDescriptor =
|
||||
StringUtils.safeSubstring(Build.MANUFACTURER, 0, 12) + '-' + StringUtils.safeSubstring(Build.MODEL, 0, 19);
|
||||
|
||||
ping.put(CorePing.ARCHITECTURE, AppConstants.ANDROID_CPU_ARCH);
|
||||
ping.put(CorePing.CLIENT_ID, clientId);
|
||||
ping.put(CorePing.DEVICE, deviceDescriptor);
|
||||
ping.put(CorePing.LOCALE, Locales.getLanguageTag(Locale.getDefault()));
|
||||
ping.put(CorePing.OS_VERSION, Integer.toString(Build.VERSION.SDK_INT)); // A String for cross-platform reasons.
|
||||
ping.put(CorePing.SEQ, seq);
|
||||
return ping;
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@
|
||||
package org.mozilla.gecko.util;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.mozilla.gecko.AppConstants.Versions;
|
||||
@ -240,4 +241,10 @@ public class StringUtils {
|
||||
|
||||
return Collections.unmodifiableSet(names);
|
||||
}
|
||||
|
||||
public static String safeSubstring(@NonNull final String str, final int start, final int end) {
|
||||
return str.substring(
|
||||
Math.max(0, start),
|
||||
Math.min(end, str.length()));
|
||||
}
|
||||
}
|
||||
|
@ -540,6 +540,9 @@ gbjar.sources += ['java/org/mozilla/gecko/' + x for x in [
|
||||
'tabs/TabsPanel.java',
|
||||
'tabs/TabsPanelThumbnailView.java',
|
||||
'Telemetry.java',
|
||||
'telemetry/TelemetryConstants.java',
|
||||
'telemetry/TelemetryPing.java',
|
||||
'telemetry/TelemetryPingGenerator.java',
|
||||
'TelemetryContract.java',
|
||||
'TextSelection.java',
|
||||
'TextSelectionHandle.java',
|
||||
|
Loading…
Reference in New Issue
Block a user