--- a/mobile/android/base/java/org/mozilla/gecko/ANRReporter.java
+++ b/mobile/android/base/java/org/mozilla/gecko/ANRReporter.java
@@ -17,16 +17,17 @@ import java.io.OutputStream;
import java.io.Reader;
import java.util.Locale;
import java.util.UUID;
import java.util.regex.Pattern;
import org.json.JSONObject;
import org.mozilla.gecko.annotation.WrapForJNI;
import org.mozilla.gecko.AppConstants.Versions;
+import org.mozilla.gecko.util.StringUtils;
import org.mozilla.gecko.util.ThreadUtils;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.Looper;
@@ -150,17 +151,18 @@ public final class ANRReporter extends B
try {
// getprop [prop-name [default-value]]
Process propProc = (new ProcessBuilder())
.command("/system/bin/getprop", "dalvik.vm.stack-trace-file")
.redirectErrorStream(true)
.start();
try {
BufferedReader buf = new BufferedReader(
- new InputStreamReader(propProc.getInputStream()), TRACES_LINE_SIZE);
+ new InputStreamReader(
+ propProc.getInputStream(), StringUtils.UTF_8), TRACES_LINE_SIZE);
String propVal = buf.readLine();
if (DEBUG) {
Log.d(LOGTAG, "getprop returned " + String.valueOf(propVal));
}
// getprop can return empty string when the prop value is empty
// or prop is undefined, treat both cases the same way
if (propVal != null && propVal.length() != 0) {
tracesFile = new File(propVal);
@@ -213,17 +215,18 @@ public final class ANRReporter extends B
if (!AppConstants.MANGLED_ANDROID_PACKAGE_NAME.equals(pkgName)) {
mangledPattern = Pattern.compile(Pattern.quote(
AppConstants.MANGLED_ANDROID_PACKAGE_NAME) + END_OF_PACKAGE_NAME);
}
if (DEBUG) {
Log.d(LOGTAG, "trying to match package: " + pkgName);
}
BufferedReader traces = new BufferedReader(
- new FileReader(tracesFile), TRACES_BLOCK_SIZE);
+ new InputStreamReader(new FileInputStream(
+ tracesFile), StringUtils.UTF_8), TRACES_BLOCK_SIZE);
try {
for (int count = 0; count < LINES_TO_IDENTIFY_TRACES; count++) {
String line = traces.readLine();
if (DEBUG) {
Log.d(LOGTAG, "identifying line: " + String.valueOf(line));
}
if (line == null) {
if (DEBUG) {
--- a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
@@ -2041,20 +2041,20 @@ public class BrowserApp extends GeckoApp
.execute(new IconCallback() {
@Override
public void onIconResponse(IconResponse response) {
ByteArrayOutputStream out = null;
Base64OutputStream b64 = null;
try {
out = new ByteArrayOutputStream();
- out.write("data:image/png;base64,".getBytes());
+ out.write("data:image/png;base64,".getBytes(StringUtils.UTF_8));
b64 = new Base64OutputStream(out, Base64.NO_WRAP);
response.getBitmap().compress(Bitmap.CompressFormat.PNG, 100, b64);
- callback.sendSuccess(new String(out.toByteArray()));
+ callback.sendSuccess(new String(out.toByteArray(), StringUtils.UTF_8));
} catch (IOException e) {
Log.w(LOGTAG, "Failed to convert to base64 data URI");
callback.sendError("Failed to convert favicon to a base64 data URI");
} finally {
try {
if (out != null) {
out.close();
}
--- a/mobile/android/base/java/org/mozilla/gecko/SuggestClient.java
+++ b/mobile/android/base/java/org/mozilla/gecko/SuggestClient.java
@@ -2,29 +2,31 @@
* 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;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import org.json.JSONArray;
import org.mozilla.gecko.annotation.RobocopTarget;
import org.mozilla.gecko.util.HardwareUtils;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
import org.mozilla.gecko.util.NetworkUtils;
+import org.mozilla.gecko.util.StringUtils;
/**
* Use network-based search suggestions.
*/
public class SuggestClient {
private static final String LOGTAG = "GeckoSuggestClient";
// This should go through GeckoInterface to get the UA, but the search activity
@@ -129,14 +131,14 @@ public class SuggestClient {
mPrevQuery = query;
mPrevResults = suggestions;
return suggestions;
}
private String convertStreamToString(java.io.InputStream is) {
try {
- return new java.util.Scanner(is).useDelimiter("\\A").next();
+ return new java.util.Scanner(new InputStreamReader(is, StringUtils.UTF_8)).useDelimiter("\\A").next();
} catch (java.util.NoSuchElementException e) {
return "";
}
}
}
--- a/mobile/android/base/java/org/mozilla/gecko/db/LoginsProvider.java
+++ b/mobile/android/base/java/org/mozilla/gecko/db/LoginsProvider.java
@@ -16,16 +16,17 @@ import android.net.Uri;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.Base64;
import org.mozilla.gecko.db.BrowserContract.DeletedLogins;
import org.mozilla.gecko.db.BrowserContract.Logins;
import org.mozilla.gecko.db.BrowserContract.LoginsDisabledHosts;
import org.mozilla.gecko.sync.Utils;
+import org.mozilla.gecko.util.StringUtils;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.util.HashMap;
import javax.crypto.Cipher;
import javax.crypto.NullCipher;
@@ -502,17 +503,18 @@ public class LoginsProvider extends Shar
debug("encryption failed : " + e);
throw new IllegalStateException("Logins encryption failed", e);
}
}
private String decrypt(@NonNull String initialValue) {
try {
final Cipher cipher = getCipher(Cipher.DECRYPT_MODE);
- return new String(cipher.doFinal(Base64.decode(initialValue.getBytes("UTF-8"), Base64.URL_SAFE)));
+ return new String(cipher.doFinal(Base64.decode(
+ initialValue.getBytes("UTF-8"), Base64.URL_SAFE)), StringUtils.UTF_8);
} catch (Exception e) {
debug("Decryption failed : " + e);
throw new IllegalStateException("Logins decryption failed", e);
}
}
private Cipher getCipher(int mode) throws UnsupportedEncodingException, GeneralSecurityException {
return new NullCipher();
--- a/mobile/android/base/java/org/mozilla/gecko/home/BrowserSearch.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/BrowserSearch.java
@@ -545,17 +545,18 @@ public class BrowserSearch extends HomeF
}
LinkedHashSet<String> domains = null;
private LinkedHashSet<String> getDomains() {
if (domains == null) {
domains = new LinkedHashSet<String>(500);
BufferedReader buf = null;
try {
- buf = new BufferedReader(new InputStreamReader(getResources().openRawResource(R.raw.topdomains)));
+ buf = new BufferedReader(new InputStreamReader(
+ getResources().openRawResource(R.raw.topdomains), StringUtils.UTF_8));
String res = null;
do {
res = buf.readLine();
if (res != null) {
domains.add(res);
}
} while (res != null);
--- a/mobile/android/base/java/org/mozilla/gecko/media/GeckoMediaDrmBridgeV21.java
+++ b/mobile/android/base/java/org/mozilla/gecko/media/GeckoMediaDrmBridgeV21.java
@@ -24,16 +24,18 @@ import android.os.HandlerThread;
import android.media.DeniedByServerException;
import android.media.MediaCrypto;
import android.media.MediaCryptoException;
import android.media.MediaDrm;
import android.media.MediaDrmException;
import android.media.NotProvisionedException;
import android.util.Log;
+import org.mozilla.gecko.util.StringUtils;
+
public class GeckoMediaDrmBridgeV21 implements GeckoMediaDrm {
protected final String LOGTAG;
private static final String INVALID_SESSION_ID = "Invalid";
private static final String WIDEVINE_KEY_SYSTEM = "com.widevine.alpha";
private static final boolean DEBUG = false;
private static final UUID WIDEVINE_SCHEME_UUID =
new UUID(0xedef8ba979d64aceL, 0xa3c827dcd51d21edL);
// MediaDrm.KeyStatus information listener is supported on M+, adding a
@@ -168,17 +170,18 @@ public class GeckoMediaDrmBridgeV21 impl
promiseId,
sessionId.array(),
request.getData());
onSessionMessage(sessionId.array(),
LICENSE_REQUEST_INITIAL,
request.getData());
mSessionMIMETypes.put(sessionId, initDataType);
mSessionIds.add(sessionId);
- if (DEBUG) Log.d(LOGTAG, " StringID : " + new String(sessionId.array()) + " is put into mSessionIds ");
+ if (DEBUG) Log.d(LOGTAG, " StringID : " + new String(
+ sessionId.array(), StringUtils.UTF_8) + " is put into mSessionIds ");
} catch (android.media.NotProvisionedException e) {
if (DEBUG) Log.d(LOGTAG, "Device not provisioned:" + e.getMessage());
if (sessionId != null) {
// The promise of this createSession will be either resolved
// or rejected after provisioning.
mDrm.closeSession(sessionId.array());
}
savePendingCreateSessionData(createSessionToken, promiseId,
@@ -192,17 +195,17 @@ public class GeckoMediaDrmBridgeV21 impl
String sessionId,
byte[] response) {
if (DEBUG) Log.d(LOGTAG, "updateSession(), sessionId = " + sessionId);
if (mDrm == null) {
onRejectPromise(promiseId, "MediaDrm instance doesn't exist !!");
return;
}
- ByteBuffer session = ByteBuffer.wrap(sessionId.getBytes());
+ ByteBuffer session = ByteBuffer.wrap(sessionId.getBytes(StringUtils.UTF_8));
if (!sessionExists(session)) {
onRejectPromise(promiseId, "Invalid session during updateSession.");
return;
}
try {
final byte [] keySetId = mDrm.provideKeyResponse(session.array(), response);
if (DEBUG) {
@@ -227,17 +230,17 @@ public class GeckoMediaDrmBridgeV21 impl
@Override
public void closeSession(int promiseId, String sessionId) {
if (DEBUG) Log.d(LOGTAG, "closeSession()");
if (mDrm == null) {
onRejectPromise(promiseId, "MediaDrm instance doesn't exist !!");
return;
}
- ByteBuffer session = ByteBuffer.wrap(sessionId.getBytes());
+ ByteBuffer session = ByteBuffer.wrap(sessionId.getBytes(StringUtils.UTF_8));
mSessionIds.remove(session);
mDrm.closeSession(session.array());
onSessionClosed(promiseId, session.array());
}
@Override
public void release() {
if (DEBUG) Log.d(LOGTAG, "release()");
@@ -373,20 +376,20 @@ public class GeckoMediaDrmBridgeV21 impl
case MediaDrm.EVENT_PROVISION_REQUIRED:
if (DEBUG) Log.d(LOGTAG, "MediaDrm.EVENT_PROVISION_REQUIRED");
break;
case MediaDrm.EVENT_KEY_REQUIRED:
if (DEBUG) Log.d(LOGTAG, "MediaDrm.EVENT_KEY_REQUIRED");
// No need to handle here if we're not in privacy mode.
break;
case MediaDrm.EVENT_KEY_EXPIRED:
- if (DEBUG) Log.d(LOGTAG, "MediaDrm.EVENT_KEY_EXPIRED, sessionId=" + new String(session.array()));
+ if (DEBUG) Log.d(LOGTAG, "MediaDrm.EVENT_KEY_EXPIRED, sessionId=" + new String(session.array(), StringUtils.UTF_8));
break;
case MediaDrm.EVENT_VENDOR_DEFINED:
- if (DEBUG) Log.d(LOGTAG, "MediaDrm.EVENT_VENDOR_DEFINED, sessionId=" + new String(session.array()));
+ if (DEBUG) Log.d(LOGTAG, "MediaDrm.EVENT_VENDOR_DEFINED, sessionId=" + new String(session.array(), StringUtils.UTF_8));
break;
default:
if (DEBUG) Log.d(LOGTAG, "Invalid DRM event " + event);
return;
}
}
}
@@ -451,25 +454,25 @@ public class GeckoMediaDrmBridgeV21 impl
urlConnection.setRequestProperty("Content-Type", "application/json");
// Execute HTTP Post Request
urlConnection.connect();
int responseCode = urlConnection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
BufferedReader in =
- new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
+ new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), StringUtils.UTF_8));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
- mResponseBody = String.valueOf(response).getBytes();
+ mResponseBody = String.valueOf(response).getBytes(StringUtils.UTF_8);
if (DEBUG) Log.d(LOGTAG, "Provisioning, response received.");
if (mResponseBody != null) Log.d(LOGTAG, "response length=" + mResponseBody.length);
} else {
Log.d(LOGTAG, "Provisioning, server returned HTTP error code :" + responseCode);
}
} catch (IOException e) {
Log.e(LOGTAG, "Got exception during posting provisioning request ...", e);
}
@@ -585,17 +588,18 @@ public class GeckoMediaDrmBridgeV21 impl
if (DEBUG) Log.d(LOGTAG, "Cannot open session for MediaCrypto");
return false;
}
if (MediaCrypto.isCryptoSchemeSupported(mSchemeUUID)) {
final byte [] cryptoSessionId = mCryptoSessionId.array();
mCrypto = new MediaCrypto(mSchemeUUID, cryptoSessionId);
mSessionIds.add(mCryptoSessionId);
- if (DEBUG) Log.d(LOGTAG, "MediaCrypto successfully created! - SId " + INVALID_SESSION_ID + ", " + new String(cryptoSessionId));
+ if (DEBUG) Log.d(LOGTAG, "MediaCrypto successfully created! - SId " + INVALID_SESSION_ID +
+ ", " + new String(cryptoSessionId, StringUtils.UTF_8));
return true;
} else {
if (DEBUG) Log.d(LOGTAG, "Cannot create MediaCrypto for unsupported scheme.");
return false;
}
} catch (android.media.MediaCryptoException e) {
if (DEBUG) Log.d(LOGTAG, "Cannot create MediaCrypto:" + e.getMessage());
release();
--- a/mobile/android/base/java/org/mozilla/gecko/search/SearchEngineManager.java
+++ b/mobile/android/base/java/org/mozilla/gecko/search/SearchEngineManager.java
@@ -18,16 +18,17 @@ import org.mozilla.gecko.GeckoProfile;
import org.mozilla.gecko.GeckoSharedPrefs;
import org.mozilla.gecko.Locales;
import org.mozilla.gecko.R;
import org.mozilla.gecko.distribution.Distribution;
import org.mozilla.gecko.util.FileUtils;
import org.mozilla.gecko.util.GeckoJarReader;
import org.mozilla.gecko.util.HardwareUtils;
import org.mozilla.gecko.util.RawResource;
+import org.mozilla.gecko.util.StringUtils;
import org.mozilla.gecko.util.ThreadUtils;
import org.xmlpull.v1.XmlPullParserException;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@@ -388,17 +389,17 @@ public class SearchEngineManager impleme
final String message = "{}";
urlConnection.setDoOutput(true);
urlConnection.setConnectTimeout(10000);
urlConnection.setReadTimeout(10000);
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("User-Agent", USER_AGENT);
urlConnection.setRequestProperty("Content-Type", "application/json");
- urlConnection.setFixedLengthStreamingMode(message.getBytes().length);
+ urlConnection.setFixedLengthStreamingMode(message.getBytes(StringUtils.UTF_8).length);
final OutputStream out = urlConnection.getOutputStream();
out.write(message.getBytes());
out.close();
responseText = getHttpResponse(urlConnection);
} finally {
urlConnection.disconnect();
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/StringUtils.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/StringUtils.java
@@ -4,27 +4,34 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.util;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.text.TextUtils;
+import java.nio.charset.Charset;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
public class StringUtils {
private static final String LOGTAG = "GeckoStringUtils";
private static final String FILTER_URL_PREFIX = "filter://";
private static final String USER_ENTERED_URL_PREFIX = "user-entered:";
+
+ /**
+ * The UTF-8 charset.
+ */
+ public static final Charset UTF_8 = Charset.forName("UTF-8");
+
/*
* This method tries to guess if the given string could be a search query or URL,
* and returns a previous result if there is ambiguity
*
* Search examples:
* foo
* foo bar.com
* foo http://bar.com
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/background/common/log/Logger.java
+++ b/mobile/android/services/src/main/java/org/mozilla/gecko/background/common/log/Logger.java
@@ -1,26 +1,28 @@
/* 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.background.common.log;
+import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import org.mozilla.gecko.background.common.GlobalConstants;
import org.mozilla.gecko.background.common.log.writers.AndroidLevelCachingLogWriter;
import org.mozilla.gecko.background.common.log.writers.AndroidLogWriter;
import org.mozilla.gecko.background.common.log.writers.LogWriter;
import org.mozilla.gecko.background.common.log.writers.PrintLogWriter;
import org.mozilla.gecko.background.common.log.writers.SimpleTagLogWriter;
import org.mozilla.gecko.background.common.log.writers.ThreadLocalTagLogWriter;
+import org.mozilla.gecko.util.StringUtils;
import android.util.Log;
/**
* Logging helper class. Serializes all log operations (by synchronizing).
*/
public class Logger {
public static final String LOGGER_TAG = "Logger";
@@ -121,17 +123,18 @@ public class Logger {
/**
* Start writing log output to stdout.
* <p>
* Use <code>resetLogging</code> to stop logging to stdout.
*/
public static synchronized void startLoggingToConsole() {
setThreadLogTag("Test");
- startLoggingTo(new PrintLogWriter(new PrintWriter(System.out, true)));
+ startLoggingTo(new PrintLogWriter(new PrintWriter(
+ new OutputStreamWriter(System.out, StringUtils.UTF_8), true)));
}
// Synchronized version for other classes to use.
public static synchronized boolean shouldLogVerbose(String logTag) {
for (LogWriter logWriter : logWriters) {
if (logWriter.shouldLogVerbose(logTag)) {
return true;
}
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/browserid/JSONWebTokenUtils.java
+++ b/mobile/android/services/src/main/java/org/mozilla/gecko/browserid/JSONWebTokenUtils.java
@@ -144,18 +144,20 @@ public class JSONWebTokenUtils {
* certificate is well-formed.
*/
public static ExtendedJSONObject parseCertificate(String input) {
try {
String[] parts = input.split("\\.");
if (parts.length != 3) {
return null;
}
- String cHeader = new String(Base64.decodeBase64(parts[0]));
- String cPayload = new String(Base64.decodeBase64(parts[1]));
+ String cHeader = new String(Base64.decodeBase64(parts[0]),
+ org.mozilla.gecko.util.StringUtils.UTF_8);
+ String cPayload = new String(Base64.decodeBase64(parts[1]),
+ org.mozilla.gecko.util.StringUtils.UTF_8);
String cSignature = Utils.byte2Hex(Base64.decodeBase64(parts[2]));
ExtendedJSONObject o = new ExtendedJSONObject();
o.put("header", new ExtendedJSONObject(cHeader));
o.put("payload", new ExtendedJSONObject(cPayload));
o.put("signature", cSignature);
return o;
} catch (Exception e) {
return null;
@@ -198,18 +200,20 @@ public class JSONWebTokenUtils {
return null;
}
String certificate = parts[0];
String assertion = parts[1];
parts = assertion.split("\\.");
if (parts.length != 3) {
return null;
}
- String aHeader = new String(Base64.decodeBase64(parts[0]));
- String aPayload = new String(Base64.decodeBase64(parts[1]));
+ String aHeader = new String(Base64.decodeBase64(parts[0]),
+ org.mozilla.gecko.util.StringUtils.UTF_8);
+ String aPayload = new String(Base64.decodeBase64(parts[1]),
+ org.mozilla.gecko.util.StringUtils.UTF_8);
String aSignature = Utils.byte2Hex(Base64.decodeBase64(parts[2]));
// We do all the assertion parsing *before* dumping the certificate in
// case there's a malformed assertion.
ExtendedJSONObject o = new ExtendedJSONObject();
o.put("header", new ExtendedJSONObject(aHeader));
o.put("payload", new ExtendedJSONObject(aPayload));
o.put("signature", aSignature);
o.put("certificate", certificate);
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/CollectionKeys.java
+++ b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/CollectionKeys.java
@@ -10,16 +10,17 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Set;
import org.json.simple.JSONArray;
import org.mozilla.apache.commons.codec.binary.Base64;
import org.mozilla.gecko.sync.crypto.CryptoException;
import org.mozilla.gecko.sync.crypto.KeyBundle;
+import org.mozilla.gecko.util.StringUtils;
public class CollectionKeys {
private KeyBundle defaultKeyBundle = null;
private final HashMap<String, KeyBundle> collectionKeyBundles = new HashMap<String, KeyBundle>();
/**
* Randomly generate a basic CollectionKeys object.
* @throws CryptoException
@@ -64,18 +65,18 @@ public class CollectionKeys {
String hmacKeyStr = (String) array.get(1);
return KeyBundle.fromBase64EncodedKeys(encKeyStr, hmacKeyStr);
}
@SuppressWarnings("unchecked")
private static JSONArray keyBundleToArray(KeyBundle bundle) {
// Generate JSON.
JSONArray keysArray = new JSONArray();
- keysArray.add(new String(Base64.encodeBase64(bundle.getEncryptionKey())));
- keysArray.add(new String(Base64.encodeBase64(bundle.getHMACKey())));
+ keysArray.add(new String(Base64.encodeBase64(bundle.getEncryptionKey()), StringUtils.UTF_8));
+ keysArray.add(new String(Base64.encodeBase64(bundle.getHMACKey()), StringUtils.UTF_8));
return keysArray;
}
private ExtendedJSONObject asRecordContents() throws NoCollectionKeysSetException {
ExtendedJSONObject json = new ExtendedJSONObject();
json.put("id", "keys");
json.put("collection", "crypto");
json.put("default", keyBundleToArray(this.defaultKeyBundle()));
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/CryptoRecord.java
+++ b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/CryptoRecord.java
@@ -11,16 +11,17 @@ import org.json.simple.JSONObject;
import org.mozilla.apache.commons.codec.binary.Base64;
import org.mozilla.gecko.sync.crypto.CryptoException;
import org.mozilla.gecko.sync.crypto.CryptoInfo;
import org.mozilla.gecko.sync.crypto.KeyBundle;
import org.mozilla.gecko.sync.crypto.MissingCryptoInputException;
import org.mozilla.gecko.sync.crypto.NoKeyBundleException;
import org.mozilla.gecko.sync.repositories.domain.Record;
import org.mozilla.gecko.sync.repositories.domain.RecordParseException;
+import org.mozilla.gecko.util.StringUtils;
/**
* A Sync crypto record has:
*
* <ul>
* <li>a collection of fields which are not encrypted (id and collection);</il>
* <li>a set of metadata fields (index, modified, ttl);</il>
* <li>a payload, which is encrypted and decrypted on request.</il>
@@ -199,17 +200,17 @@ public class CryptoRecord extends Record
return this;
}
public CryptoRecord encrypt() throws CryptoException, UnsupportedEncodingException {
if (this.keyBundle == null) {
throw new NoKeyBundleException();
}
String cleartext = payload.toJSONString();
- byte[] cleartextBytes = cleartext.getBytes("UTF-8");
+ byte[] cleartextBytes = cleartext.getBytes(StringUtils.UTF_8);
CryptoInfo info = CryptoInfo.encrypt(cleartextBytes, keyBundle);
String message = new String(Base64.encodeBase64(info.getMessage()));
String iv = new String(Base64.encodeBase64(info.getIV()));
String hmac = Utils.byte2Hex(info.getHMAC());
ExtendedJSONObject ciphertext = new ExtendedJSONObject();
ciphertext.put(KEY_CIPHERTEXT, message);
ciphertext.put(KEY_HMAC, hmac);
ciphertext.put(KEY_IV, iv);
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/Utils.java
+++ b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/Utils.java
@@ -26,33 +26,34 @@ import java.util.TreeMap;
import java.util.concurrent.Executor;
import org.json.simple.JSONArray;
import org.mozilla.apache.commons.codec.binary.Base32;
import org.mozilla.apache.commons.codec.binary.Base64;
import org.mozilla.gecko.background.common.log.Logger;
import org.mozilla.gecko.background.nativecode.NativeCrypto;
import org.mozilla.gecko.sync.setup.Constants;
+import org.mozilla.gecko.util.StringUtils;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
public class Utils {
private static final String LOG_TAG = "Utils";
private static final SecureRandom sharedSecureRandom = new SecureRandom();
// See <http://developer.android.com/reference/android/content/Context.html#getSharedPreferences%28java.lang.String,%20int%29>
public static final int SHARED_PREFERENCES_MODE = 0;
public static String generateGuid() {
byte[] encodedBytes = Base64.encodeBase64(generateRandomBytes(9), false);
- return new String(encodedBytes).replace("+", "-").replace("/", "_");
+ return new String(encodedBytes, StringUtils.UTF_8).replace("+", "-").replace("/", "_");
}
/**
* Helper to generate secure random bytes.
*
* @param length
* Number of bytes to generate.
*/
@@ -488,17 +489,17 @@ public class Utils {
}
FileInputStream fis = null;
InputStreamReader isr = null;
BufferedReader br = null;
try {
fis = context.openFileInput(filename);
- isr = new InputStreamReader(fis);
+ isr = new InputStreamReader(fis, StringUtils.UTF_8);
br = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
return sb.toString();
} catch (Exception e) {
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/MozResponse.java
+++ b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/MozResponse.java
@@ -13,16 +13,17 @@ import java.util.Scanner;
import org.json.simple.JSONArray;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.mozilla.gecko.background.common.log.Logger;
import org.mozilla.gecko.sync.ExtendedJSONObject;
import org.mozilla.gecko.sync.NonArrayJSONException;
import org.mozilla.gecko.sync.NonObjectJSONException;
+import org.mozilla.gecko.util.StringUtils;
import ch.boye.httpclientandroidlib.Header;
import ch.boye.httpclientandroidlib.HttpEntity;
import ch.boye.httpclientandroidlib.HttpResponse;
import ch.boye.httpclientandroidlib.HttpStatus;
import ch.boye.httpclientandroidlib.impl.cookie.DateParseException;
import ch.boye.httpclientandroidlib.impl.cookie.DateUtils;
@@ -74,17 +75,17 @@ public class MozResponse {
return body;
}
final HttpEntity entity = this.response.getEntity();
if (entity == null) {
body = null;
return null;
}
- InputStreamReader is = new InputStreamReader(entity.getContent());
+ InputStreamReader is = new InputStreamReader(entity.getContent(), StringUtils.UTF_8);
// Oh, Java, you are so evil.
body = new Scanner(is).useDelimiter("\\A").next();
return body;
}
/**
* Return the body as a <b>non-null</b> <code>ExtendedJSONObject</code>.
*
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SyncStorageCollectionRequest.java
+++ b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SyncStorageCollectionRequest.java
@@ -6,16 +6,17 @@ package org.mozilla.gecko.sync.net;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import org.mozilla.gecko.background.common.log.Logger;
+import org.mozilla.gecko.util.StringUtils;
import ch.boye.httpclientandroidlib.Header;
import ch.boye.httpclientandroidlib.HttpEntity;
import ch.boye.httpclientandroidlib.HttpResponse;
import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase;
import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient;
/**
@@ -98,17 +99,17 @@ public class SyncStorageCollectionReques
// it processes. Bug 721887.
// Line-by-line processing, then invoke success.
SyncStorageCollectionRequestDelegate delegate = (SyncStorageCollectionRequestDelegate) this.request.delegate;
InputStream content = null;
BufferedReader br = null;
try {
content = entity.getContent();
- br = new BufferedReader(new InputStreamReader(content), FETCH_BUFFER_SIZE);
+ br = new BufferedReader(new InputStreamReader(content, StringUtils.UTF_8), FETCH_BUFFER_SIZE);
String line;
// This relies on connection timeouts at the HTTP layer.
while (!aborting &&
null != (line = br.readLine())) {
try {
delegate.handleRequestProgress(line);
} catch (Exception ex) {
--- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/datahandling/DataStorageManager.java
+++ b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/datahandling/DataStorageManager.java
@@ -1,17 +1,19 @@
/* 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.mozstumbler.service.stumblerthread.datahandling;
import android.content.Context;
import android.util.Log;
+
import org.mozilla.mozstumbler.service.AppGlobals;
+import org.mozilla.mozstumbler.service.utils.StringUtils;
import org.mozilla.mozstumbler.service.utils.Zipper;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Properties;
@@ -96,17 +98,17 @@ public class DataStorageManager {
public QueuedCounts getQueuedCounts() {
int reportCount = mFileList.mReportCount + mCurrentReports.reports.size();
int wifiCount = mFileList.mWifiCount + mCurrentReports.wifiCount;
int cellCount = mFileList.mCellCount + mCurrentReports.cellCount;
long bytes = 0;
if (mCurrentReports.reports.size() > 0) {
try {
- bytes = Zipper.zipData(finalizeReports(mCurrentReports.reports).getBytes()).length;
+ bytes = Zipper.zipData(finalizeReports(mCurrentReports.reports).getBytes(StringUtils.UTF_8)).length;
} catch (IOException ex) {
Log.e(LOG_TAG, "Zip error in getQueuedCounts()", ex);
}
if (mFileList.mReportCount > 0) {
bytes += mFileList.mFilesOnDiskBytes;
}
}
@@ -296,17 +298,17 @@ public class DataStorageManager {
if (dirEmpty && currentReportsCount < 1) {
return null;
}
mReportBatchIterator = new ReportBatchIterator(mFileList);
if (currentReportsCount > 0) {
final String filename = MEMORY_BUFFER_NAME;
- final byte[] data = Zipper.zipData(finalizeReports(mCurrentReports.reports).getBytes());
+ final byte[] data = Zipper.zipData(finalizeReports(mCurrentReports.reports).getBytes(StringUtils.UTF_8));
final int wifiCount = mCurrentReports.wifiCount;
final int cellCount = mCurrentReports.cellCount;
clearCurrentReports();
final ReportBatch result = new ReportBatch(filename, data, currentReportsCount, wifiCount, cellCount);
mCurrentReportsSendBuffer = result;
return result;
} else {
return getNextBatch();
@@ -407,17 +409,17 @@ public class DataStorageManager {
return result;
}
public synchronized void saveCurrentReportsToDisk() throws IOException {
saveCurrentReportsSendBufferToDisk();
if (mCurrentReports.reports.size() < 1) {
return;
}
- final byte[] bytes = Zipper.zipData(finalizeReports(mCurrentReports.reports).getBytes());
+ final byte[] bytes = Zipper.zipData(finalizeReports(mCurrentReports.reports).getBytes(StringUtils.UTF_8));
saveToDisk(bytes, mCurrentReports.reports.size(), mCurrentReports.wifiCount, mCurrentReports.cellCount);
clearCurrentReports();
}
public synchronized void insert(String report, int wifiCount, int cellCount) throws IOException {
notifyStorageIsEmpty(false);
if (mFlushMemoryBuffersToDiskTimer != null) {
new file mode 100644
--- /dev/null
+++ b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/utils/StringUtils.java
@@ -0,0 +1,15 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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.mozstumbler.service.utils;
+
+import java.nio.charset.Charset;
+
+public class StringUtils {
+ /**
+ * The UTF-8 charset.
+ */
+ public static final Charset UTF_8 = Charset.forName("UTF-8");
+}
--- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/utils/Zipper.java
+++ b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/utils/Zipper.java
@@ -28,17 +28,17 @@ public class Zipper {
return output;
}
public static String unzipData(byte[] data) throws IOException {
StringBuilder result = new StringBuilder();
final ByteArrayInputStream bs = new ByteArrayInputStream(data);
GZIPInputStream gstream = new GZIPInputStream(bs);
try {
- InputStreamReader reader = new InputStreamReader(gstream);
+ InputStreamReader reader = new InputStreamReader(gstream, StringUtils.UTF_8);
BufferedReader in = new BufferedReader(reader);
String read;
while ((read = in.readLine()) != null) {
result.append(read);
}
} finally {
gstream.close();
bs.close();
--- a/mobile/android/stumbler/stumbler_sources.mozbuild
+++ b/mobile/android/stumbler/stumbler_sources.mozbuild
@@ -26,11 +26,12 @@ stumbler_sources = [
'java/org/mozilla/mozstumbler/service/stumblerthread/scanners/ScanManager.java',
'java/org/mozilla/mozstumbler/service/stumblerthread/scanners/WifiScanner.java',
'java/org/mozilla/mozstumbler/service/stumblerthread/StumblerService.java',
'java/org/mozilla/mozstumbler/service/uploadthread/AsyncUploader.java',
'java/org/mozilla/mozstumbler/service/uploadthread/UploadAlarmReceiver.java',
'java/org/mozilla/mozstumbler/service/utils/AbstractCommunicator.java',
'java/org/mozilla/mozstumbler/service/utils/NetworkUtils.java',
'java/org/mozilla/mozstumbler/service/utils/PersistentIntentService.java',
+ 'java/org/mozilla/mozstumbler/service/utils/StringUtils.java',
'java/org/mozilla/mozstumbler/service/utils/TelemetryWrapper.java',
'java/org/mozilla/mozstumbler/service/utils/Zipper.java',
]