| Index: chrome/android/java_staging/src/org/chromium/chrome/browser/omaha/RequestGenerator.java
|
| diff --git a/chrome/android/java_staging/src/org/chromium/chrome/browser/omaha/RequestGenerator.java b/chrome/android/java_staging/src/org/chromium/chrome/browser/omaha/RequestGenerator.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d0c3c9556bb745b08914d622977e141cdf8b67db
|
| --- /dev/null
|
| +++ b/chrome/android/java_staging/src/org/chromium/chrome/browser/omaha/RequestGenerator.java
|
| @@ -0,0 +1,180 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +package org.chromium.chrome.browser.omaha;
|
| +
|
| +import android.content.Context;
|
| +import android.os.Build;
|
| +import android.util.Xml;
|
| +
|
| +import org.chromium.base.BuildInfo;
|
| +import org.chromium.base.VisibleForTesting;
|
| +import org.xmlpull.v1.XmlSerializer;
|
| +
|
| +import java.io.IOException;
|
| +import java.io.StringWriter;
|
| +import java.util.Locale;
|
| +
|
| +/**
|
| + * Generates XML requests to send to the Omaha server.
|
| + */
|
| +public abstract class RequestGenerator {
|
| + // The Omaha specs say that new installs should use "-1".
|
| + public static final int INSTALL_AGE_IMMEDIATELY_AFTER_INSTALLING = -1;
|
| +
|
| + private static final long MS_PER_DAY = 1000 * 60 * 60 * 24;
|
| +
|
| + private final Context mApplicationContext;
|
| +
|
| + @VisibleForTesting
|
| + public RequestGenerator(Context context) {
|
| + mApplicationContext = context.getApplicationContext();
|
| + }
|
| +
|
| + /**
|
| + * Determine how long it's been since Chrome was first installed. Note that this may not
|
| + * accurate for various reasons, but it shouldn't affect stats too much.
|
| + */
|
| + public static long installAge(
|
| + long currentTimestamp, long installTimestamp, boolean sendInstallEvent) {
|
| + if (sendInstallEvent) {
|
| + return INSTALL_AGE_IMMEDIATELY_AFTER_INSTALLING;
|
| + } else {
|
| + return Math.max(0L, (currentTimestamp - installTimestamp) / MS_PER_DAY);
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Generates the XML for the current request.
|
| + * Follows the format laid out at http://code.google.com/p/omaha/wiki/ServerProtocol
|
| + * with some additional dummy values supplied.
|
| + */
|
| + public String generateXML(String sessionID, String versionName, long installAge,
|
| + RequestData data) throws RequestFailureException {
|
| + XmlSerializer serializer = Xml.newSerializer();
|
| + StringWriter writer = new StringWriter();
|
| + try {
|
| + serializer.setOutput(writer);
|
| + serializer.startDocument("UTF-8", true);
|
| +
|
| + // Set up <request protocol=3.0 ...>
|
| + serializer.startTag(null, "request");
|
| + serializer.attribute(null, "protocol", "3.0");
|
| + serializer.attribute(null, "version", "Android-1.0.0.0");
|
| + serializer.attribute(null, "ismachine", "1");
|
| + serializer.attribute(null, "requestid", "{" + data.getRequestID() + "}");
|
| + serializer.attribute(null, "sessionid", "{" + sessionID + "}");
|
| + serializer.attribute(null, "installsource", data.getInstallSource());
|
| + appendExtraAttributes("request", serializer);
|
| +
|
| + // Set up <os platform="android"... />
|
| + serializer.startTag(null, "os");
|
| + serializer.attribute(null, "platform", "android");
|
| + serializer.attribute(null, "version", Build.VERSION.RELEASE);
|
| + serializer.attribute(null, "arch", "arm");
|
| + serializer.endTag(null, "os");
|
| +
|
| + // Set up <app version="" ...>
|
| + serializer.startTag(null, "app");
|
| + serializer.attribute(null, "brand", getBrand());
|
| + serializer.attribute(null, "client", getClient());
|
| + serializer.attribute(null, "appid", getAppId());
|
| + serializer.attribute(null, "version", versionName);
|
| + serializer.attribute(null, "nextversion", "");
|
| + serializer.attribute(null, "lang", getLanguage());
|
| + serializer.attribute(null, "installage", String.valueOf(installAge));
|
| + serializer.attribute(null, "ap", getAdditionalParameters());
|
| + appendExtraAttributes("app", serializer);
|
| +
|
| + if (data.isSendInstallEvent()) {
|
| + // Set up <event eventtype="2" eventresult="1" />
|
| + serializer.startTag(null, "event");
|
| + serializer.attribute(null, "eventtype", "2");
|
| + serializer.attribute(null, "eventresult", "1");
|
| + serializer.endTag(null, "event");
|
| + } else {
|
| + // Set up <updatecheck />
|
| + serializer.startTag(null, "updatecheck");
|
| + serializer.endTag(null, "updatecheck");
|
| +
|
| + // Set up <ping active="1" />
|
| + serializer.startTag(null, "ping");
|
| + serializer.attribute(null, "active", "1");
|
| + serializer.endTag(null, "ping");
|
| + }
|
| +
|
| + serializer.endTag(null, "app");
|
| + serializer.endTag(null, "request");
|
| +
|
| + serializer.endDocument();
|
| + } catch (IOException e) {
|
| + throw new RequestFailureException("Caught an IOException creating the XML: ", e);
|
| + } catch (IllegalArgumentException e) {
|
| + throw new RequestFailureException(
|
| + "Caught an IllegalArgumentException creating the XML: ", e);
|
| + } catch (IllegalStateException e) {
|
| + throw new RequestFailureException(
|
| + "Caught an IllegalStateException creating the XML: ", e);
|
| + }
|
| +
|
| + return writer.toString();
|
| + }
|
| +
|
| + /**
|
| + * Returns the application context.
|
| + */
|
| + protected Context getContext() {
|
| + return mApplicationContext;
|
| + }
|
| +
|
| + /**
|
| + * Returns the current Android language and region code (e.g. en-GB or de-DE).
|
| + *
|
| + * Note: the region code depends only on the language the user selected in Android settings.
|
| + * It doesn't depend on the user's physical location.
|
| + */
|
| + public String getLanguage() {
|
| + Locale locale = Locale.getDefault();
|
| + if (locale.getCountry().isEmpty()) {
|
| + return locale.getLanguage();
|
| + } else {
|
| + return locale.getLanguage() + "-" + locale.getCountry();
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Sends additional info that might be useful for statistics generation,
|
| + * including information about channel and device type.
|
| + * This string is partially sanitized for dashboard viewing and because people randomly set
|
| + * these strings when building their own custom Android ROMs.
|
| + */
|
| + public String getAdditionalParameters() {
|
| + String applicationLabel =
|
| + StringSanitizer.sanitize(BuildInfo.getPackageLabel(mApplicationContext));
|
| + String brand = StringSanitizer.sanitize(Build.BRAND);
|
| + String model = StringSanitizer.sanitize(Build.MODEL);
|
| + return applicationLabel + ";" + brand + ";" + model;
|
| + }
|
| +
|
| + /**
|
| + * Appends extra attributes to the XML for the given tag.
|
| + * @param tag Tag to add extra attributes to.
|
| + * @param serializer Serializer to append the attributes to. Expects the last open tag to be
|
| + * the one being appended to.
|
| + */
|
| + protected void appendExtraAttributes(String tag, XmlSerializer serializer) throws IOException {
|
| + }
|
| +
|
| + /** Returns the UUID of the Chrome version we're running. */
|
| + protected abstract String getAppId();
|
| +
|
| + /** Returns the brand code. If one can't be retrieved, return "". */
|
| + protected abstract String getBrand();
|
| +
|
| + /** Returns the current client ID. */
|
| + protected abstract String getClient();
|
| +
|
| + /** URL for the Omaha server. */
|
| + public abstract String getServerUrl();
|
| +}
|
|
|