OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 package org.chromium.chrome.browser.omaha; |
| 6 |
| 7 import android.content.Context; |
| 8 import android.os.Build; |
| 9 import android.util.Xml; |
| 10 |
| 11 import org.chromium.base.BuildInfo; |
| 12 import org.chromium.base.VisibleForTesting; |
| 13 import org.xmlpull.v1.XmlSerializer; |
| 14 |
| 15 import java.io.IOException; |
| 16 import java.io.StringWriter; |
| 17 import java.util.Locale; |
| 18 |
| 19 /** |
| 20 * Generates XML requests to send to the Omaha server. |
| 21 */ |
| 22 public abstract class RequestGenerator { |
| 23 // The Omaha specs say that new installs should use "-1". |
| 24 public static final int INSTALL_AGE_IMMEDIATELY_AFTER_INSTALLING = -1; |
| 25 |
| 26 private static final long MS_PER_DAY = 1000 * 60 * 60 * 24; |
| 27 |
| 28 private final Context mApplicationContext; |
| 29 |
| 30 @VisibleForTesting |
| 31 public RequestGenerator(Context context) { |
| 32 mApplicationContext = context.getApplicationContext(); |
| 33 } |
| 34 |
| 35 /** |
| 36 * Determine how long it's been since Chrome was first installed. Note that
this may not |
| 37 * accurate for various reasons, but it shouldn't affect stats too much. |
| 38 */ |
| 39 public static long installAge( |
| 40 long currentTimestamp, long installTimestamp, boolean sendInstallEve
nt) { |
| 41 if (sendInstallEvent) { |
| 42 return INSTALL_AGE_IMMEDIATELY_AFTER_INSTALLING; |
| 43 } else { |
| 44 return Math.max(0L, (currentTimestamp - installTimestamp) / MS_PER_D
AY); |
| 45 } |
| 46 } |
| 47 |
| 48 /** |
| 49 * Generates the XML for the current request. |
| 50 * Follows the format laid out at http://code.google.com/p/omaha/wiki/Server
Protocol |
| 51 * with some additional dummy values supplied. |
| 52 */ |
| 53 public String generateXML(String sessionID, String versionName, long install
Age, |
| 54 RequestData data) throws RequestFailureException { |
| 55 XmlSerializer serializer = Xml.newSerializer(); |
| 56 StringWriter writer = new StringWriter(); |
| 57 try { |
| 58 serializer.setOutput(writer); |
| 59 serializer.startDocument("UTF-8", true); |
| 60 |
| 61 // Set up <request protocol=3.0 ...> |
| 62 serializer.startTag(null, "request"); |
| 63 serializer.attribute(null, "protocol", "3.0"); |
| 64 serializer.attribute(null, "version", "Android-1.0.0.0"); |
| 65 serializer.attribute(null, "ismachine", "1"); |
| 66 serializer.attribute(null, "requestid", "{" + data.getRequestID() +
"}"); |
| 67 serializer.attribute(null, "sessionid", "{" + sessionID + "}"); |
| 68 serializer.attribute(null, "installsource", data.getInstallSource())
; |
| 69 appendExtraAttributes("request", serializer); |
| 70 |
| 71 // Set up <os platform="android"... /> |
| 72 serializer.startTag(null, "os"); |
| 73 serializer.attribute(null, "platform", "android"); |
| 74 serializer.attribute(null, "version", Build.VERSION.RELEASE); |
| 75 serializer.attribute(null, "arch", "arm"); |
| 76 serializer.endTag(null, "os"); |
| 77 |
| 78 // Set up <app version="" ...> |
| 79 serializer.startTag(null, "app"); |
| 80 serializer.attribute(null, "brand", getBrand()); |
| 81 serializer.attribute(null, "client", getClient()); |
| 82 serializer.attribute(null, "appid", getAppId()); |
| 83 serializer.attribute(null, "version", versionName); |
| 84 serializer.attribute(null, "nextversion", ""); |
| 85 serializer.attribute(null, "lang", getLanguage()); |
| 86 serializer.attribute(null, "installage", String.valueOf(installAge))
; |
| 87 serializer.attribute(null, "ap", getAdditionalParameters()); |
| 88 appendExtraAttributes("app", serializer); |
| 89 |
| 90 if (data.isSendInstallEvent()) { |
| 91 // Set up <event eventtype="2" eventresult="1" /> |
| 92 serializer.startTag(null, "event"); |
| 93 serializer.attribute(null, "eventtype", "2"); |
| 94 serializer.attribute(null, "eventresult", "1"); |
| 95 serializer.endTag(null, "event"); |
| 96 } else { |
| 97 // Set up <updatecheck /> |
| 98 serializer.startTag(null, "updatecheck"); |
| 99 serializer.endTag(null, "updatecheck"); |
| 100 |
| 101 // Set up <ping active="1" /> |
| 102 serializer.startTag(null, "ping"); |
| 103 serializer.attribute(null, "active", "1"); |
| 104 serializer.endTag(null, "ping"); |
| 105 } |
| 106 |
| 107 serializer.endTag(null, "app"); |
| 108 serializer.endTag(null, "request"); |
| 109 |
| 110 serializer.endDocument(); |
| 111 } catch (IOException e) { |
| 112 throw new RequestFailureException("Caught an IOException creating th
e XML: ", e); |
| 113 } catch (IllegalArgumentException e) { |
| 114 throw new RequestFailureException( |
| 115 "Caught an IllegalArgumentException creating the XML: ", e); |
| 116 } catch (IllegalStateException e) { |
| 117 throw new RequestFailureException( |
| 118 "Caught an IllegalStateException creating the XML: ", e); |
| 119 } |
| 120 |
| 121 return writer.toString(); |
| 122 } |
| 123 |
| 124 /** |
| 125 * Returns the application context. |
| 126 */ |
| 127 protected Context getContext() { |
| 128 return mApplicationContext; |
| 129 } |
| 130 |
| 131 /** |
| 132 * Returns the current Android language and region code (e.g. en-GB or de-DE
). |
| 133 * |
| 134 * Note: the region code depends only on the language the user selected in A
ndroid settings. |
| 135 * It doesn't depend on the user's physical location. |
| 136 */ |
| 137 public String getLanguage() { |
| 138 Locale locale = Locale.getDefault(); |
| 139 if (locale.getCountry().isEmpty()) { |
| 140 return locale.getLanguage(); |
| 141 } else { |
| 142 return locale.getLanguage() + "-" + locale.getCountry(); |
| 143 } |
| 144 } |
| 145 |
| 146 /** |
| 147 * Sends additional info that might be useful for statistics generation, |
| 148 * including information about channel and device type. |
| 149 * This string is partially sanitized for dashboard viewing and because peop
le randomly set |
| 150 * these strings when building their own custom Android ROMs. |
| 151 */ |
| 152 public String getAdditionalParameters() { |
| 153 String applicationLabel = |
| 154 StringSanitizer.sanitize(BuildInfo.getPackageLabel(mApplicationC
ontext)); |
| 155 String brand = StringSanitizer.sanitize(Build.BRAND); |
| 156 String model = StringSanitizer.sanitize(Build.MODEL); |
| 157 return applicationLabel + ";" + brand + ";" + model; |
| 158 } |
| 159 |
| 160 /** |
| 161 * Appends extra attributes to the XML for the given tag. |
| 162 * @param tag Tag to add extra attributes to. |
| 163 * @param serializer Serializer to append the attributes to. Expects the la
st open tag to be |
| 164 * the one being appended to. |
| 165 */ |
| 166 protected void appendExtraAttributes(String tag, XmlSerializer serializer) t
hrows IOException { |
| 167 } |
| 168 |
| 169 /** Returns the UUID of the Chrome version we're running. */ |
| 170 protected abstract String getAppId(); |
| 171 |
| 172 /** Returns the brand code. If one can't be retrieved, return "". */ |
| 173 protected abstract String getBrand(); |
| 174 |
| 175 /** Returns the current client ID. */ |
| 176 protected abstract String getClient(); |
| 177 |
| 178 /** URL for the Omaha server. */ |
| 179 public abstract String getServerUrl(); |
| 180 } |
OLD | NEW |