Remove Google-specific (or only-used-by-Google-code) classes.
Fix a small typo in Context javadoc.
This commit is contained in:
@ -1314,7 +1314,7 @@ public abstract class Context {
|
||||
|
||||
/**
|
||||
* Use with {@link #getSystemService} to retrieve a
|
||||
* {@blink android.appwidget.AppWidgetManager} for accessing AppWidgets.
|
||||
* {@link android.appwidget.AppWidgetManager} for accessing AppWidgets.
|
||||
*
|
||||
* @hide
|
||||
* @see #getSystemService
|
||||
@ -1323,7 +1323,7 @@ public abstract class Context {
|
||||
|
||||
/**
|
||||
* Use with {@link #getSystemService} to retrieve an
|
||||
* {@blink android.backup.IBackupManager IBackupManager} for communicating
|
||||
* {@link android.backup.IBackupManager IBackupManager} for communicating
|
||||
* with the backup mechanism.
|
||||
* @hide
|
||||
*
|
||||
@ -1333,7 +1333,7 @@ public abstract class Context {
|
||||
|
||||
/**
|
||||
* Use with {@link #getSystemService} to retrieve a
|
||||
* {@blink android.os.DropBox DropBox} instance for recording
|
||||
* {@link android.os.DropBox DropBox} instance for recording
|
||||
* diagnostic logs.
|
||||
* @see #getSystemService
|
||||
*/
|
||||
|
@ -1,289 +0,0 @@
|
||||
// Copyright 2009 The Android Open Source Project
|
||||
|
||||
package com.android.internal.net;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.SQLException;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.util.Log;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.harmony.xnet.provider.jsse.SSLClientSessionCache;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.net.ssl.SSLSession;
|
||||
|
||||
/**
|
||||
* Hook into harmony SSL cache to persist the SSL sessions.
|
||||
*
|
||||
* Current implementation is suitable for saving a small number of hosts -
|
||||
* like google services. It can be extended with expiration and more features
|
||||
* to support more hosts.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public class DbSSLSessionCache implements SSLClientSessionCache {
|
||||
private static final String TAG = "DbSSLSessionCache";
|
||||
|
||||
/**
|
||||
* Table where sessions are stored.
|
||||
*/
|
||||
public static final String SSL_CACHE_TABLE = "ssl_sessions";
|
||||
|
||||
private static final String SSL_CACHE_ID = "_id";
|
||||
|
||||
/**
|
||||
* Key is host:port - port is not optional.
|
||||
*/
|
||||
private static final String SSL_CACHE_HOSTPORT = "hostport";
|
||||
|
||||
/**
|
||||
* Base64-encoded DER value of the session.
|
||||
*/
|
||||
private static final String SSL_CACHE_SESSION = "session";
|
||||
|
||||
/**
|
||||
* Time when the record was added - should be close to the time
|
||||
* of the initial session negotiation.
|
||||
*/
|
||||
private static final String SSL_CACHE_TIME_SEC = "time_sec";
|
||||
|
||||
public static final String DATABASE_NAME = "ssl_sessions.db";
|
||||
|
||||
public static final int DATABASE_VERSION = 2;
|
||||
|
||||
/** public for testing
|
||||
*/
|
||||
public static final int SSL_CACHE_ID_COL = 0;
|
||||
public static final int SSL_CACHE_HOSTPORT_COL = 1;
|
||||
public static final int SSL_CACHE_SESSION_COL = 2;
|
||||
public static final int SSL_CACHE_TIME_SEC_COL = 3;
|
||||
|
||||
public static final int MAX_CACHE_SIZE = 256;
|
||||
|
||||
private final Map<String, byte[]> mExternalCache =
|
||||
new HashMap<String, byte[]>();
|
||||
|
||||
|
||||
private DatabaseHelper mDatabaseHelper;
|
||||
|
||||
private boolean mNeedsCacheLoad = true;
|
||||
|
||||
public static final String[] PROJECTION = new String[] {
|
||||
SSL_CACHE_ID,
|
||||
SSL_CACHE_HOSTPORT,
|
||||
SSL_CACHE_SESSION,
|
||||
SSL_CACHE_TIME_SEC
|
||||
};
|
||||
|
||||
private static final Map<String,DbSSLSessionCache> sInstances =
|
||||
new HashMap<String,DbSSLSessionCache>();
|
||||
|
||||
/**
|
||||
* Returns a singleton instance of the DbSSLSessionCache that should be used for this
|
||||
* context's package.
|
||||
*
|
||||
* @param context The context that should be used for getting/creating the singleton instance.
|
||||
* @return The singleton instance for the context's package.
|
||||
*/
|
||||
public static synchronized DbSSLSessionCache getInstanceForPackage(Context context) {
|
||||
String packageName = context.getPackageName();
|
||||
if (sInstances.containsKey(packageName)) {
|
||||
return sInstances.get(packageName);
|
||||
}
|
||||
DbSSLSessionCache cache = new DbSSLSessionCache(context);
|
||||
sInstances.put(packageName, cache);
|
||||
return cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a SslSessionCache instance, using the specified context to
|
||||
* initialize the database.
|
||||
*
|
||||
* This constructor will use the default database - created for the application
|
||||
* context.
|
||||
*
|
||||
* @param activityContext
|
||||
*/
|
||||
private DbSSLSessionCache(Context activityContext) {
|
||||
Context appContext = activityContext.getApplicationContext();
|
||||
mDatabaseHelper = new DatabaseHelper(appContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a SslSessionCache that uses a specific database.
|
||||
*
|
||||
*
|
||||
* @param database
|
||||
*/
|
||||
public DbSSLSessionCache(DatabaseHelper database) {
|
||||
this.mDatabaseHelper = database;
|
||||
}
|
||||
|
||||
public void putSessionData(SSLSession session, byte[] der) {
|
||||
if (mDatabaseHelper == null) {
|
||||
return;
|
||||
}
|
||||
synchronized (this.getClass()) {
|
||||
SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
|
||||
if (mExternalCache.size() == MAX_CACHE_SIZE) {
|
||||
// remove oldest.
|
||||
// TODO: check if the new one is in cached already ( i.e. update ).
|
||||
Cursor byTime = mDatabaseHelper.getReadableDatabase().query(SSL_CACHE_TABLE,
|
||||
PROJECTION, null, null, null, null, SSL_CACHE_TIME_SEC);
|
||||
if (byTime.moveToFirst()) {
|
||||
// TODO: can I do byTime.deleteRow() ?
|
||||
String hostPort = byTime.getString(SSL_CACHE_HOSTPORT_COL);
|
||||
db.delete(SSL_CACHE_TABLE,
|
||||
SSL_CACHE_HOSTPORT + "= ?" , new String[] { hostPort });
|
||||
mExternalCache.remove(hostPort);
|
||||
} else {
|
||||
Log.w(TAG, "No rows found");
|
||||
// something is wrong, clear it
|
||||
clear();
|
||||
}
|
||||
}
|
||||
// Serialize native session to standard DER encoding
|
||||
long t0 = System.currentTimeMillis();
|
||||
|
||||
String b64 = new String(Base64.encodeBase64(der));
|
||||
String key = session.getPeerHost() + ":" + session.getPeerPort();
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(SSL_CACHE_HOSTPORT, key);
|
||||
values.put(SSL_CACHE_SESSION, b64);
|
||||
values.put(SSL_CACHE_TIME_SEC, System.currentTimeMillis() / 1000);
|
||||
|
||||
mExternalCache.put(key, der);
|
||||
|
||||
try {
|
||||
db.insert(SSL_CACHE_TABLE, null /*nullColumnHack */ , values);
|
||||
} catch(SQLException ex) {
|
||||
// Ignore - nothing we can do to recover, and caller shouldn't
|
||||
// be affected.
|
||||
Log.w(TAG, "Ignoring SQL exception when caching session", ex);
|
||||
}
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
long t1 = System.currentTimeMillis();
|
||||
Log.d(TAG, "New SSL session " + session.getPeerHost() +
|
||||
" DER len: " + der.length + " " + (t1 - t0));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public byte[] getSessionData(String host, int port) {
|
||||
// Current (simple) implementation does a single lookup to DB, then saves
|
||||
// all entries to the cache.
|
||||
|
||||
// This works for google services - i.e. small number of certs.
|
||||
// If we extend this to all processes - we should hold a separate cache
|
||||
// or do lookups to DB each time.
|
||||
if (mDatabaseHelper == null) {
|
||||
return null;
|
||||
}
|
||||
synchronized(this.getClass()) {
|
||||
if (mNeedsCacheLoad) {
|
||||
// Don't try to load again, if something is wrong on the first
|
||||
// request it'll likely be wrong each time.
|
||||
mNeedsCacheLoad = false;
|
||||
long t0 = System.currentTimeMillis();
|
||||
|
||||
Cursor cur = null;
|
||||
try {
|
||||
cur = mDatabaseHelper.getReadableDatabase().query(SSL_CACHE_TABLE,
|
||||
PROJECTION, null, null, null, null, null);
|
||||
if (cur.moveToFirst()) {
|
||||
do {
|
||||
String hostPort = cur.getString(SSL_CACHE_HOSTPORT_COL);
|
||||
String value = cur.getString(SSL_CACHE_SESSION_COL);
|
||||
|
||||
if (hostPort == null || value == null) {
|
||||
continue;
|
||||
}
|
||||
// TODO: blob support ?
|
||||
byte[] der = Base64.decodeBase64(value.getBytes());
|
||||
mExternalCache.put(hostPort, der);
|
||||
} while (cur.moveToNext());
|
||||
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
Log.d(TAG, "Error loading SSL cached entries ", ex);
|
||||
} finally {
|
||||
if (cur != null) {
|
||||
cur.close();
|
||||
}
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
long t1 = System.currentTimeMillis();
|
||||
Log.d(TAG, "LOADED CACHED SSL " + (t1 - t0) + " ms");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String key = host + ":" + port;
|
||||
|
||||
return mExternalCache.get(key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the database and internal state.
|
||||
* Used for testing or to free space.
|
||||
*/
|
||||
public void clear() {
|
||||
synchronized(this) {
|
||||
try {
|
||||
mExternalCache.clear();
|
||||
mNeedsCacheLoad = true;
|
||||
mDatabaseHelper.getWritableDatabase().delete(SSL_CACHE_TABLE,
|
||||
null, null);
|
||||
} catch (SQLException ex) {
|
||||
Log.d(TAG, "Error removing SSL cached entries ", ex);
|
||||
// ignore - nothing we can do about it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getSessionData(byte[] id) {
|
||||
// We support client side only - the cache will do nothing for
|
||||
// server-side sessions.
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Visible for testing.
|
||||
*/
|
||||
public static class DatabaseHelper extends SQLiteOpenHelper {
|
||||
|
||||
public DatabaseHelper(Context context) {
|
||||
super(context, DATABASE_NAME, null /* factory */, DATABASE_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
db.execSQL("CREATE TABLE " + SSL_CACHE_TABLE + " (" +
|
||||
SSL_CACHE_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||
SSL_CACHE_HOSTPORT + " TEXT UNIQUE ON CONFLICT REPLACE," +
|
||||
SSL_CACHE_SESSION + " TEXT," +
|
||||
SSL_CACHE_TIME_SEC + " INTEGER" +
|
||||
");");
|
||||
|
||||
// No index - we load on startup, index would slow down inserts.
|
||||
// If we want to scale this to lots of rows - we could use
|
||||
// index, but then we'll hit DB a bit too often ( including
|
||||
// negative hits )
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
db.execSQL("DROP TABLE IF EXISTS " + SSL_CACHE_TABLE );
|
||||
onCreate(db);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.net;
|
||||
|
||||
import android.net.TrafficStats;
|
||||
import android.os.SystemClock;
|
||||
import android.os.SystemProperties;
|
||||
import android.util.EventLog;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.entity.HttpEntityWrapper;
|
||||
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
|
||||
public class NetworkStatsEntity extends HttpEntityWrapper {
|
||||
|
||||
private static final int HTTP_STATS_EVENT = 52001;
|
||||
|
||||
private class NetworkStatsInputStream extends FilterInputStream {
|
||||
|
||||
public NetworkStatsInputStream(InputStream wrapped) {
|
||||
super(wrapped);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
try {
|
||||
super.close();
|
||||
} finally {
|
||||
long processingTime = SystemClock.elapsedRealtime() - mProcessingStartTime;
|
||||
long tx = TrafficStats.getUidTxBytes(mUid);
|
||||
long rx = TrafficStats.getUidRxBytes(mUid);
|
||||
|
||||
EventLog.writeEvent(HTTP_STATS_EVENT, mUa, mResponseLatency, processingTime,
|
||||
tx - mStartTx, rx - mStartRx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final String mUa;
|
||||
private final int mUid;
|
||||
private final long mStartTx;
|
||||
private final long mStartRx;
|
||||
private final long mResponseLatency;
|
||||
private final long mProcessingStartTime;
|
||||
|
||||
public NetworkStatsEntity(HttpEntity orig, String ua,
|
||||
int uid, long startTx, long startRx, long responseLatency,
|
||||
long processingStartTime) {
|
||||
super(orig);
|
||||
this.mUa = ua;
|
||||
this.mUid = uid;
|
||||
this.mStartTx = startTx;
|
||||
this.mStartRx = startRx;
|
||||
this.mResponseLatency = responseLatency;
|
||||
this.mProcessingStartTime = processingStartTime;
|
||||
}
|
||||
|
||||
public static boolean shouldLogNetworkStats() {
|
||||
return "1".equals(SystemProperties.get("googlehttpclient.logstats"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getContent() throws IOException {
|
||||
InputStream orig = super.getContent();
|
||||
return new NetworkStatsInputStream(orig);
|
||||
}
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
package com.google.android.net;
|
||||
|
||||
import org.apache.harmony.xnet.provider.jsse.SSLClientSessionCache;
|
||||
import org.apache.harmony.xnet.provider.jsse.FileClientSessionCache;
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.android.internal.net.DbSSLSessionCache;
|
||||
|
||||
/**
|
||||
* Factory that returns the appropriate implementation of a {@link SSLClientSessionCache} based
|
||||
* on gservices.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
// TODO: return a proxied implementation that is updated as the gservices value changes.
|
||||
public final class SSLClientSessionCacheFactory {
|
||||
|
||||
private static final String TAG = "SSLClientSessionCacheFactory";
|
||||
|
||||
public static final String DB = "db";
|
||||
public static final String FILE = "file";
|
||||
|
||||
// utility class
|
||||
private SSLClientSessionCacheFactory() {}
|
||||
|
||||
/**
|
||||
* Returns a new {@link SSLClientSessionCache} based on the persistent cache that's specified,
|
||||
* if any, in gservices. If no cache is specified, returns null.
|
||||
* @param context The application context used for the per-process persistent cache.
|
||||
* @return A new {@link SSLClientSessionCache}, or null if no persistent cache is configured.
|
||||
*/
|
||||
public static SSLClientSessionCache getCache(Context context) {
|
||||
String type = Settings.Gservices.getString(context.getContentResolver(),
|
||||
Settings.Gservices.SSL_SESSION_CACHE);
|
||||
|
||||
if (type != null) {
|
||||
if (DB.equals(type)) {
|
||||
return DbSSLSessionCache.getInstanceForPackage(context);
|
||||
} else if (FILE.equals(type)) {
|
||||
File dir = context.getFilesDir();
|
||||
File cacheDir = new File(dir, "sslcache");
|
||||
if (!cacheDir.exists()) {
|
||||
cacheDir.mkdir();
|
||||
}
|
||||
try {
|
||||
return FileClientSessionCache.usingDirectory(cacheDir);
|
||||
} catch (IOException ioe) {
|
||||
Log.w(TAG, "Unable to create FileClientSessionCache in " + cacheDir.getName(), ioe);
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "Ignoring unrecognized type: '" + type + "'");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,236 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.net;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.database.Cursor;
|
||||
import android.provider.Checkin;
|
||||
import android.provider.Settings;
|
||||
import android.util.Config;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A set of rules rewriting and blocking URLs. Used to offer a point of
|
||||
* control for redirecting HTTP requests, often to the Android proxy server.
|
||||
*
|
||||
* <p>Each rule has the following format:
|
||||
*
|
||||
* <pre><em>url-prefix</em> [REWRITE <em>new-prefix</em>] [BLOCK]</pre>
|
||||
*
|
||||
* <p>Any URL which starts with <em>url-prefix</em> will trigger the rule.
|
||||
* If BLOCK is specified, requests to that URL will be blocked and fail.
|
||||
* If REWRITE is specified, the matching prefix will be removed and replaced
|
||||
* with <em>new-prefix</em>. (If both are specified, BLOCK wins.) Case is
|
||||
* insensitive for the REWRITE and BLOCK keywords, but sensitive for URLs.
|
||||
*
|
||||
* <p>In Gservices, the value of any key that starts with "url:" will be
|
||||
* interpreted as a rule. The full name of the key is unimportant (but can
|
||||
* be used to document the intent of the rule, and must be unique).
|
||||
* Example gservices keys:
|
||||
*
|
||||
* <pre>
|
||||
* url:use_proxy_for_calendar = "http://www.google.com/calendar/ REWRITE http://android.clients.google.com/proxy/calendar/"
|
||||
* url:stop_crash_reports = "http://android.clients.google.com/crash/ BLOCK"
|
||||
* url:use_ssl_for_contacts = "http://www.google.com/m8/ REWRITE https://www.google.com/m8/"
|
||||
* </pre>
|
||||
*/
|
||||
public class UrlRules {
|
||||
public static final String TAG = "UrlRules";
|
||||
public static final boolean LOCAL_LOGV = Config.LOGV || false;
|
||||
|
||||
/** Thrown when the rewrite rules can't be parsed. */
|
||||
public static class RuleFormatException extends Exception {
|
||||
public RuleFormatException(String msg) { super(msg); }
|
||||
}
|
||||
|
||||
/** A single rule specifying actions for URLs matching a certain prefix. */
|
||||
public static class Rule implements Comparable {
|
||||
/** Name assigned to the rule (for logging and debugging). */
|
||||
public final String mName;
|
||||
|
||||
/** Prefix required to match this rule. */
|
||||
public final String mPrefix;
|
||||
|
||||
/** Text to replace mPrefix with (null to leave alone). */
|
||||
public final String mRewrite;
|
||||
|
||||
/** True if matching URLs should be blocked. */
|
||||
public final boolean mBlock;
|
||||
|
||||
/** Default rule that does nothing. */
|
||||
public static final Rule DEFAULT = new Rule();
|
||||
|
||||
/** Parse a rewrite rule as given in a Gservices value. */
|
||||
public Rule(String name, String rule) throws RuleFormatException {
|
||||
mName = name;
|
||||
String[] words = PATTERN_SPACE_PLUS.split(rule);
|
||||
if (words.length == 0) throw new RuleFormatException("Empty rule");
|
||||
|
||||
mPrefix = words[0];
|
||||
String rewrite = null;
|
||||
boolean block = false;
|
||||
for (int pos = 1; pos < words.length; ) {
|
||||
String word = words[pos].toLowerCase();
|
||||
if (word.equals("rewrite") && pos + 1 < words.length) {
|
||||
rewrite = words[pos + 1];
|
||||
pos += 2;
|
||||
} else if (word.equals("block")) {
|
||||
block = true;
|
||||
pos += 1;
|
||||
} else {
|
||||
throw new RuleFormatException("Illegal rule: " + rule);
|
||||
}
|
||||
// TODO: Parse timeout specifications, etc.
|
||||
}
|
||||
|
||||
mRewrite = rewrite;
|
||||
mBlock = block;
|
||||
}
|
||||
|
||||
/** Create the default Rule. */
|
||||
private Rule() {
|
||||
mName = "DEFAULT";
|
||||
mPrefix = "";
|
||||
mRewrite = null;
|
||||
mBlock = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the rule to a particular URL (assumed to match the rule).
|
||||
* @param url to rewrite or modify.
|
||||
* @return modified URL, or null if the URL is blocked.
|
||||
*/
|
||||
public String apply(String url) {
|
||||
if (mBlock) {
|
||||
return null;
|
||||
} else if (mRewrite != null) {
|
||||
return mRewrite + url.substring(mPrefix.length());
|
||||
} else {
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
||||
/** More generic rules are greater than more specific rules. */
|
||||
public int compareTo(Object o) {
|
||||
return ((Rule) o).mPrefix.compareTo(mPrefix);
|
||||
}
|
||||
}
|
||||
|
||||
/** Cached rule set from Gservices. */
|
||||
private static UrlRules sCachedRules = new UrlRules(new Rule[] {});
|
||||
|
||||
private static final Pattern PATTERN_SPACE_PLUS = Pattern.compile(" +");
|
||||
private static final Pattern RULE_PATTERN = Pattern.compile("\\W");
|
||||
|
||||
/** Gservices digest when sCachedRules was cached. */
|
||||
private static String sCachedDigest = null;
|
||||
|
||||
/** Currently active set of Rules. */
|
||||
private final Rule[] mRules;
|
||||
|
||||
/** Regular expression with one capturing group for each Rule. */
|
||||
private final Pattern mPattern;
|
||||
|
||||
/**
|
||||
* Create a rewriter from an array of Rules. Normally used only for
|
||||
* testing. Instead, use {@link #getRules} to get rules from Gservices.
|
||||
* @param rules to use.
|
||||
*/
|
||||
public UrlRules(Rule[] rules) {
|
||||
// Sort the rules to put the most specific rules first.
|
||||
Arrays.sort(rules);
|
||||
|
||||
// Construct a regular expression, escaping all the prefix strings.
|
||||
StringBuilder pattern = new StringBuilder("(");
|
||||
for (int i = 0; i < rules.length; ++i) {
|
||||
if (i > 0) pattern.append(")|(");
|
||||
pattern.append(RULE_PATTERN.matcher(rules[i].mPrefix).replaceAll("\\\\$0"));
|
||||
}
|
||||
mPattern = Pattern.compile(pattern.append(")").toString());
|
||||
mRules = rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match a string against every Rule and find one that matches.
|
||||
* @param uri to match against the Rules in the rewriter.
|
||||
* @return the most specific matching Rule, or Rule.DEFAULT if none match.
|
||||
*/
|
||||
public Rule matchRule(String url) {
|
||||
Matcher matcher = mPattern.matcher(url);
|
||||
if (matcher.lookingAt()) {
|
||||
for (int i = 0; i < mRules.length; ++i) {
|
||||
if (matcher.group(i + 1) != null) {
|
||||
return mRules[i]; // Rules are sorted most specific first.
|
||||
}
|
||||
}
|
||||
}
|
||||
return Rule.DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the (possibly cached) UrlRules based on the rules in Gservices.
|
||||
* @param resolver to use for accessing the Gservices database.
|
||||
* @return an updated UrlRules instance
|
||||
*/
|
||||
public static synchronized UrlRules getRules(ContentResolver resolver) {
|
||||
String digest = Settings.Gservices.getString(resolver,
|
||||
Settings.Gservices.PROVISIONING_DIGEST);
|
||||
if (sCachedDigest != null && sCachedDigest.equals(digest)) {
|
||||
// The digest is the same, so the rules are the same.
|
||||
if (LOCAL_LOGV) Log.v(TAG, "Using cached rules for digest: " + digest);
|
||||
return sCachedRules;
|
||||
}
|
||||
|
||||
if (LOCAL_LOGV) Log.v(TAG, "Scanning for Gservices \"url:*\" rules");
|
||||
Cursor cursor = resolver.query(Settings.Gservices.CONTENT_URI,
|
||||
new String[] {
|
||||
Settings.Gservices.NAME,
|
||||
Settings.Gservices.VALUE
|
||||
},
|
||||
Settings.Gservices.NAME + " like \"url:%\"", null,
|
||||
Settings.Gservices.NAME);
|
||||
try {
|
||||
ArrayList<Rule> rules = new ArrayList<Rule>();
|
||||
while (cursor.moveToNext()) {
|
||||
try {
|
||||
String name = cursor.getString(0).substring(4); // "url:X"
|
||||
String value = cursor.getString(1);
|
||||
if (value == null || value.length() == 0) continue;
|
||||
if (LOCAL_LOGV) Log.v(TAG, " Rule " + name + ": " + value);
|
||||
rules.add(new Rule(name, value));
|
||||
} catch (RuleFormatException e) {
|
||||
// Oops, Gservices has an invalid rule! Skip it.
|
||||
Log.e(TAG, "Invalid rule from Gservices", e);
|
||||
Checkin.logEvent(resolver,
|
||||
Checkin.Events.Tag.GSERVICES_ERROR, e.toString());
|
||||
}
|
||||
}
|
||||
sCachedRules = new UrlRules(rules.toArray(new Rule[rules.size()]));
|
||||
sCachedDigest = digest;
|
||||
if (LOCAL_LOGV) Log.v(TAG, "New rules stored for digest: " + digest);
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
return sCachedRules;
|
||||
}
|
||||
}
|
@ -691,8 +691,6 @@ com.google.android.mms.ContentType
|
||||
com.google.android.mms.pdu.CharacterSets
|
||||
com.google.android.mms.pdu.PduPart
|
||||
com.google.android.mms.pdu.PduPersister
|
||||
com.google.android.net.UrlRules
|
||||
com.google.android.net.UrlRules$Rule
|
||||
com.ibm.icu4jni.charset.CharsetDecoderICU
|
||||
com.ibm.icu4jni.charset.CharsetEncoderICU
|
||||
com.ibm.icu4jni.charset.CharsetICU
|
||||
|
@ -1,13 +0,0 @@
|
||||
package com.android.unit_tests;
|
||||
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
public class ApacheHttpTests {
|
||||
public static TestSuite suite() {
|
||||
TestSuite suite = new TestSuite(ApacheHttpTests.class.getName());
|
||||
|
||||
suite.addTestSuite(TestHttpService.class);
|
||||
|
||||
return suite;
|
||||
}
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
package com.android.unit_tests;
|
||||
|
||||
import com.google.android.net.SSLClientSessionCacheFactory;
|
||||
import com.android.internal.net.DbSSLSessionCache;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.test.suitebuilder.annotation.MediumTest;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import org.apache.harmony.xnet.provider.jsse.SSLClientSessionCache;
|
||||
|
||||
/**
|
||||
* Unit test for {@link SSLClientSessionCacheFactory}.
|
||||
*/
|
||||
@MediumTest
|
||||
public final class SSLClientSessionCacheFactoryTest extends AndroidTestCase {
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
setSslSessionCacheValue(getContext(), "");
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
private static void setSslSessionCacheValue(Context context, String value) {
|
||||
ContentResolver resolver = context.getContentResolver();
|
||||
Settings.Gservices.putString(resolver, Settings.Gservices.SSL_SESSION_CACHE, value);
|
||||
}
|
||||
|
||||
private static SSLClientSessionCache getCache(Context context, String type) {
|
||||
setSslSessionCacheValue(context, type);
|
||||
return SSLClientSessionCacheFactory.getCache(context);
|
||||
}
|
||||
|
||||
public void testGetDbCache() throws Exception {
|
||||
Context context = getContext();
|
||||
SSLClientSessionCache cache = getCache(context, "db");
|
||||
assertNotNull(cache);
|
||||
assertTrue(cache instanceof DbSSLSessionCache);
|
||||
}
|
||||
|
||||
public void testGetFileCache() throws Exception {
|
||||
Context context = getContext();
|
||||
SSLClientSessionCache cache = getCache(context, "file");
|
||||
assertNotNull(cache);
|
||||
// yuck =)
|
||||
assertEquals("org.apache.harmony.xnet.provider.jsse.FileClientSessionCache$Impl",
|
||||
cache.getClass().getName());
|
||||
}
|
||||
|
||||
public void testGetNoCache() throws Exception {
|
||||
Context context = getContext();
|
||||
SSLClientSessionCache cache = getCache(context, "none");
|
||||
assertNull(cache);
|
||||
}
|
||||
}
|
@ -1,207 +0,0 @@
|
||||
/*
|
||||
* $HeadURL: http://svn.apache.org/repos/asf/jakarta/httpcomponents/httpcore/tags/4.0-alpha6/module-main/src/test/java/org/apache/http/mockup/TestHttpServer.java $
|
||||
* $Revision: 576077 $
|
||||
* $Date: 2007-09-16 04:50:22 -0700 (Sun, 16 Sep 2007) $
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.android.unit_tests;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
|
||||
import org.apache.http.ConnectionClosedException;
|
||||
import org.apache.http.ConnectionReuseStrategy;
|
||||
import org.apache.http.HttpException;
|
||||
import org.apache.http.HttpResponseFactory;
|
||||
import org.apache.http.HttpServerConnection;
|
||||
import org.apache.http.impl.DefaultConnectionReuseStrategy;
|
||||
import org.apache.http.impl.DefaultHttpResponseFactory;
|
||||
import org.apache.http.impl.DefaultHttpServerConnection;
|
||||
import org.apache.http.params.BasicHttpParams;
|
||||
import org.apache.http.params.CoreConnectionPNames;
|
||||
import org.apache.http.params.HttpParams;
|
||||
import org.apache.http.params.CoreProtocolPNames;
|
||||
import org.apache.http.protocol.BasicHttpProcessor;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
import org.apache.http.protocol.BasicHttpContext;
|
||||
import org.apache.http.protocol.HttpExpectationVerifier;
|
||||
import org.apache.http.protocol.HttpRequestHandler;
|
||||
import org.apache.http.protocol.HttpRequestHandlerRegistry;
|
||||
import org.apache.http.protocol.HttpService;
|
||||
import org.apache.http.protocol.ResponseConnControl;
|
||||
import org.apache.http.protocol.ResponseContent;
|
||||
import org.apache.http.protocol.ResponseDate;
|
||||
import org.apache.http.protocol.ResponseServer;
|
||||
|
||||
public class TestHttpServer {
|
||||
|
||||
private final HttpParams params;
|
||||
private final BasicHttpProcessor httpproc;
|
||||
private final ConnectionReuseStrategy connStrategy;
|
||||
private final HttpResponseFactory responseFactory;
|
||||
private final HttpRequestHandlerRegistry reqistry;
|
||||
private final ServerSocket serversocket;
|
||||
|
||||
private HttpExpectationVerifier expectationVerifier;
|
||||
|
||||
private Thread listener;
|
||||
private volatile boolean shutdown;
|
||||
|
||||
public TestHttpServer() throws IOException {
|
||||
super();
|
||||
this.params = new BasicHttpParams();
|
||||
this.params
|
||||
.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 20000)
|
||||
.setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024)
|
||||
.setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false)
|
||||
.setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true)
|
||||
.setParameter(CoreProtocolPNames.ORIGIN_SERVER, "TEST-SERVER/1.1");
|
||||
this.httpproc = new BasicHttpProcessor();
|
||||
this.httpproc.addInterceptor(new ResponseDate());
|
||||
this.httpproc.addInterceptor(new ResponseServer());
|
||||
this.httpproc.addInterceptor(new ResponseContent());
|
||||
this.httpproc.addInterceptor(new ResponseConnControl());
|
||||
this.connStrategy = new DefaultConnectionReuseStrategy();
|
||||
this.responseFactory = new DefaultHttpResponseFactory();
|
||||
this.reqistry = new HttpRequestHandlerRegistry();
|
||||
this.serversocket = new ServerSocket(0);
|
||||
}
|
||||
|
||||
public void registerHandler(
|
||||
final String pattern,
|
||||
final HttpRequestHandler handler) {
|
||||
this.reqistry.register(pattern, handler);
|
||||
}
|
||||
|
||||
public void setExpectationVerifier(final HttpExpectationVerifier expectationVerifier) {
|
||||
this.expectationVerifier = expectationVerifier;
|
||||
}
|
||||
|
||||
private HttpServerConnection acceptConnection() throws IOException {
|
||||
Socket socket = this.serversocket.accept();
|
||||
DefaultHttpServerConnection conn = new DefaultHttpServerConnection();
|
||||
conn.bind(socket, this.params);
|
||||
return conn;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return this.serversocket.getLocalPort();
|
||||
}
|
||||
|
||||
public InetAddress getInetAddress() {
|
||||
return this.serversocket.getInetAddress();
|
||||
}
|
||||
|
||||
public void start() {
|
||||
if (this.listener != null) {
|
||||
throw new IllegalStateException("Listener already running");
|
||||
}
|
||||
this.listener = new Thread(new Runnable() {
|
||||
|
||||
public void run() {
|
||||
while (!shutdown && !Thread.interrupted()) {
|
||||
try {
|
||||
// Set up HTTP connection
|
||||
HttpServerConnection conn = acceptConnection();
|
||||
// Set up the HTTP service
|
||||
HttpService httpService = new HttpService(
|
||||
httpproc,
|
||||
connStrategy,
|
||||
responseFactory);
|
||||
httpService.setParams(params);
|
||||
httpService.setExpectationVerifier(expectationVerifier);
|
||||
httpService.setHandlerResolver(reqistry);
|
||||
|
||||
// Start worker thread
|
||||
Thread t = new WorkerThread(httpService, conn);
|
||||
t.setDaemon(true);
|
||||
t.start();
|
||||
} catch (InterruptedIOException ex) {
|
||||
break;
|
||||
} catch (IOException e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
this.listener.start();
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
if (this.shutdown) {
|
||||
return;
|
||||
}
|
||||
this.shutdown = true;
|
||||
try {
|
||||
this.serversocket.close();
|
||||
} catch (IOException ignore) {}
|
||||
this.listener.interrupt();
|
||||
try {
|
||||
this.listener.join(1000);
|
||||
} catch (InterruptedException ignore) {}
|
||||
}
|
||||
|
||||
static class WorkerThread extends Thread {
|
||||
|
||||
private final HttpService httpservice;
|
||||
private final HttpServerConnection conn;
|
||||
|
||||
public WorkerThread(
|
||||
final HttpService httpservice,
|
||||
final HttpServerConnection conn) {
|
||||
super();
|
||||
this.httpservice = httpservice;
|
||||
this.conn = conn;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
HttpContext context = new BasicHttpContext(null);
|
||||
try {
|
||||
while (!Thread.interrupted() && this.conn.isOpen()) {
|
||||
this.httpservice.handleRequest(this.conn, context);
|
||||
}
|
||||
} catch (ConnectionClosedException ex) {
|
||||
} catch (IOException ex) {
|
||||
System.err.println("I/O error: " + ex.getMessage());
|
||||
} catch (HttpException ex) {
|
||||
System.err.println("Unrecoverable HTTP protocol violation: " + ex.getMessage());
|
||||
} finally {
|
||||
try {
|
||||
this.conn.shutdown();
|
||||
} catch (IOException ignore) {}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,608 +0,0 @@
|
||||
/*
|
||||
* $HeadURL: http://svn.apache.org/repos/asf/jakarta/httpcomponents/httpcore/tags/4.0-alpha6/module-main/src/test/java/org/apache/http/protocol/TestHttpServiceAndExecutor.java $
|
||||
* $Revision: 576073 $
|
||||
* $Date: 2007-09-16 03:53:13 -0700 (Sun, 16 Sep 2007) $
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.android.unit_tests;
|
||||
|
||||
import org.apache.http.protocol.HttpExpectationVerifier;
|
||||
import org.apache.http.protocol.HttpRequestHandler;
|
||||
import android.test.PerformanceTestCase;
|
||||
import android.test.suitebuilder.annotation.LargeTest;
|
||||
import android.test.suitebuilder.annotation.MediumTest;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpConnectionMetrics;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpEntityEnclosingRequest;
|
||||
import org.apache.http.HttpException;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.HttpVersion;
|
||||
import org.apache.http.entity.ByteArrayEntity;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.DefaultHttpClientConnection;
|
||||
import org.apache.http.message.BasicHttpEntityEnclosingRequest;
|
||||
import org.apache.http.message.BasicHttpRequest;
|
||||
import org.apache.http.params.CoreProtocolPNames;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
import org.apache.http.util.EncodingUtils;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class TestHttpService extends TestCase implements PerformanceTestCase {
|
||||
|
||||
public boolean isPerformanceOnly() {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
public int startPerformance(Intermediates intermediates) {
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
private TestHttpServer server;
|
||||
private TestHttpClient client;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
this.server = new TestHttpServer();
|
||||
this.client = new TestHttpClient();
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
if (server != null) {
|
||||
this.server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This test case executes a series of simple GET requests
|
||||
*/
|
||||
@LargeTest
|
||||
public void testSimpleBasicHttpRequests() throws Exception {
|
||||
|
||||
int reqNo = 20;
|
||||
|
||||
Random rnd = new Random();
|
||||
|
||||
// Prepare some random data
|
||||
final List testData = new ArrayList(reqNo);
|
||||
for (int i = 0; i < reqNo; i++) {
|
||||
int size = rnd.nextInt(5000);
|
||||
byte[] data = new byte[size];
|
||||
rnd.nextBytes(data);
|
||||
testData.add(data);
|
||||
}
|
||||
|
||||
// Initialize the server-side request handler
|
||||
this.server.registerHandler("*", new HttpRequestHandler() {
|
||||
|
||||
public void handle(
|
||||
final HttpRequest request,
|
||||
final HttpResponse response,
|
||||
final HttpContext context) throws HttpException, IOException {
|
||||
|
||||
String s = request.getRequestLine().getUri();
|
||||
if (s.startsWith("/?")) {
|
||||
s = s.substring(2);
|
||||
}
|
||||
int index = Integer.parseInt(s);
|
||||
byte[] data = (byte []) testData.get(index);
|
||||
ByteArrayEntity entity = new ByteArrayEntity(data);
|
||||
response.setEntity(entity);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
this.server.start();
|
||||
|
||||
DefaultHttpClientConnection conn = new DefaultHttpClientConnection();
|
||||
HttpHost host = new HttpHost("localhost", this.server.getPort());
|
||||
|
||||
try {
|
||||
for (int r = 0; r < reqNo; r++) {
|
||||
if (!conn.isOpen()) {
|
||||
Socket socket = new Socket(host.getHostName(), host.getPort());
|
||||
conn.bind(socket, this.client.getParams());
|
||||
}
|
||||
|
||||
BasicHttpRequest get = new BasicHttpRequest("GET", "/?" + r);
|
||||
HttpResponse response = this.client.execute(get, host, conn);
|
||||
byte[] received = EntityUtils.toByteArray(response.getEntity());
|
||||
byte[] expected = (byte[]) testData.get(r);
|
||||
|
||||
assertEquals(expected.length, received.length);
|
||||
for (int i = 0; i < expected.length; i++) {
|
||||
assertEquals(expected[i], received[i]);
|
||||
}
|
||||
if (!this.client.keepAlive(response)) {
|
||||
conn.close();
|
||||
}
|
||||
}
|
||||
|
||||
//Verify the connection metrics
|
||||
HttpConnectionMetrics cm = conn.getMetrics();
|
||||
assertEquals(reqNo, cm.getRequestCount());
|
||||
assertEquals(reqNo, cm.getResponseCount());
|
||||
|
||||
} finally {
|
||||
conn.close();
|
||||
this.server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This test case executes a series of simple POST requests with content length
|
||||
* delimited content.
|
||||
*/
|
||||
@LargeTest
|
||||
public void testSimpleHttpPostsWithContentLength() throws Exception {
|
||||
|
||||
int reqNo = 20;
|
||||
|
||||
Random rnd = new Random();
|
||||
|
||||
// Prepare some random data
|
||||
List testData = new ArrayList(reqNo);
|
||||
for (int i = 0; i < reqNo; i++) {
|
||||
int size = rnd.nextInt(5000);
|
||||
byte[] data = new byte[size];
|
||||
rnd.nextBytes(data);
|
||||
testData.add(data);
|
||||
}
|
||||
|
||||
// Initialize the server-side request handler
|
||||
this.server.registerHandler("*", new HttpRequestHandler() {
|
||||
|
||||
public void handle(
|
||||
final HttpRequest request,
|
||||
final HttpResponse response,
|
||||
final HttpContext context) throws HttpException, IOException {
|
||||
|
||||
if (request instanceof HttpEntityEnclosingRequest) {
|
||||
HttpEntity incoming = ((HttpEntityEnclosingRequest) request).getEntity();
|
||||
byte[] data = EntityUtils.toByteArray(incoming);
|
||||
|
||||
ByteArrayEntity outgoing = new ByteArrayEntity(data);
|
||||
outgoing.setChunked(false);
|
||||
response.setEntity(outgoing);
|
||||
} else {
|
||||
StringEntity outgoing = new StringEntity("No content");
|
||||
response.setEntity(outgoing);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
this.server.start();
|
||||
|
||||
DefaultHttpClientConnection conn = new DefaultHttpClientConnection();
|
||||
HttpHost host = new HttpHost("localhost", this.server.getPort());
|
||||
|
||||
try {
|
||||
for (int r = 0; r < reqNo; r++) {
|
||||
if (!conn.isOpen()) {
|
||||
Socket socket = new Socket(host.getHostName(), host.getPort());
|
||||
conn.bind(socket, this.client.getParams());
|
||||
}
|
||||
|
||||
BasicHttpEntityEnclosingRequest post = new BasicHttpEntityEnclosingRequest("POST", "/");
|
||||
byte[] data = (byte[]) testData.get(r);
|
||||
ByteArrayEntity outgoing = new ByteArrayEntity(data);
|
||||
post.setEntity(outgoing);
|
||||
|
||||
HttpResponse response = this.client.execute(post, host, conn);
|
||||
byte[] received = EntityUtils.toByteArray(response.getEntity());
|
||||
byte[] expected = (byte[]) testData.get(r);
|
||||
|
||||
assertEquals(expected.length, received.length);
|
||||
for (int i = 0; i < expected.length; i++) {
|
||||
assertEquals(expected[i], received[i]);
|
||||
}
|
||||
if (!this.client.keepAlive(response)) {
|
||||
conn.close();
|
||||
}
|
||||
}
|
||||
//Verify the connection metrics
|
||||
HttpConnectionMetrics cm = conn.getMetrics();
|
||||
assertEquals(reqNo, cm.getRequestCount());
|
||||
assertEquals(reqNo, cm.getResponseCount());
|
||||
|
||||
} finally {
|
||||
conn.close();
|
||||
this.server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This test case executes a series of simple POST requests with chunk
|
||||
* coded content content.
|
||||
*/
|
||||
@LargeTest
|
||||
public void testSimpleHttpPostsChunked() throws Exception {
|
||||
|
||||
int reqNo = 20;
|
||||
|
||||
Random rnd = new Random();
|
||||
|
||||
// Prepare some random data
|
||||
List testData = new ArrayList(reqNo);
|
||||
for (int i = 0; i < reqNo; i++) {
|
||||
int size = rnd.nextInt(20000);
|
||||
byte[] data = new byte[size];
|
||||
rnd.nextBytes(data);
|
||||
testData.add(data);
|
||||
}
|
||||
|
||||
// Initialize the server-side request handler
|
||||
this.server.registerHandler("*", new HttpRequestHandler() {
|
||||
|
||||
public void handle(
|
||||
final HttpRequest request,
|
||||
final HttpResponse response,
|
||||
final HttpContext context) throws HttpException, IOException {
|
||||
|
||||
if (request instanceof HttpEntityEnclosingRequest) {
|
||||
HttpEntity incoming = ((HttpEntityEnclosingRequest) request).getEntity();
|
||||
byte[] data = EntityUtils.toByteArray(incoming);
|
||||
|
||||
ByteArrayEntity outgoing = new ByteArrayEntity(data);
|
||||
outgoing.setChunked(true);
|
||||
response.setEntity(outgoing);
|
||||
} else {
|
||||
StringEntity outgoing = new StringEntity("No content");
|
||||
response.setEntity(outgoing);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
this.server.start();
|
||||
|
||||
DefaultHttpClientConnection conn = new DefaultHttpClientConnection();
|
||||
HttpHost host = new HttpHost("localhost", this.server.getPort());
|
||||
|
||||
try {
|
||||
for (int r = 0; r < reqNo; r++) {
|
||||
if (!conn.isOpen()) {
|
||||
Socket socket = new Socket(host.getHostName(), host.getPort());
|
||||
conn.bind(socket, this.client.getParams());
|
||||
}
|
||||
|
||||
BasicHttpEntityEnclosingRequest post = new BasicHttpEntityEnclosingRequest("POST", "/");
|
||||
byte[] data = (byte[]) testData.get(r);
|
||||
ByteArrayEntity outgoing = new ByteArrayEntity(data);
|
||||
outgoing.setChunked(true);
|
||||
post.setEntity(outgoing);
|
||||
|
||||
HttpResponse response = this.client.execute(post, host, conn);
|
||||
byte[] received = EntityUtils.toByteArray(response.getEntity());
|
||||
byte[] expected = (byte[]) testData.get(r);
|
||||
|
||||
assertEquals(expected.length, received.length);
|
||||
for (int i = 0; i < expected.length; i++) {
|
||||
assertEquals(expected[i], received[i]);
|
||||
}
|
||||
if (!this.client.keepAlive(response)) {
|
||||
conn.close();
|
||||
}
|
||||
}
|
||||
//Verify the connection metrics
|
||||
HttpConnectionMetrics cm = conn.getMetrics();
|
||||
assertEquals(reqNo, cm.getRequestCount());
|
||||
assertEquals(reqNo, cm.getResponseCount());
|
||||
} finally {
|
||||
conn.close();
|
||||
this.server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This test case executes a series of simple HTTP/1.0 POST requests.
|
||||
*/
|
||||
@LargeTest
|
||||
public void testSimpleHttpPostsHTTP10() throws Exception {
|
||||
|
||||
int reqNo = 20;
|
||||
|
||||
Random rnd = new Random();
|
||||
|
||||
// Prepare some random data
|
||||
List testData = new ArrayList(reqNo);
|
||||
for (int i = 0; i < reqNo; i++) {
|
||||
int size = rnd.nextInt(5000);
|
||||
byte[] data = new byte[size];
|
||||
rnd.nextBytes(data);
|
||||
testData.add(data);
|
||||
}
|
||||
|
||||
// Initialize the server-side request handler
|
||||
this.server.registerHandler("*", new HttpRequestHandler() {
|
||||
|
||||
public void handle(
|
||||
final HttpRequest request,
|
||||
final HttpResponse response,
|
||||
final HttpContext context) throws HttpException, IOException {
|
||||
|
||||
if (request instanceof HttpEntityEnclosingRequest) {
|
||||
HttpEntity incoming = ((HttpEntityEnclosingRequest) request).getEntity();
|
||||
byte[] data = EntityUtils.toByteArray(incoming);
|
||||
|
||||
ByteArrayEntity outgoing = new ByteArrayEntity(data);
|
||||
outgoing.setChunked(false);
|
||||
response.setEntity(outgoing);
|
||||
} else {
|
||||
StringEntity outgoing = new StringEntity("No content");
|
||||
response.setEntity(outgoing);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
this.server.start();
|
||||
|
||||
// Set protocol level to HTTP/1.0
|
||||
this.client.getParams().setParameter(
|
||||
CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_0);
|
||||
|
||||
DefaultHttpClientConnection conn = new DefaultHttpClientConnection();
|
||||
HttpHost host = new HttpHost("localhost", this.server.getPort());
|
||||
|
||||
try {
|
||||
for (int r = 0; r < reqNo; r++) {
|
||||
if (!conn.isOpen()) {
|
||||
Socket socket = new Socket(host.getHostName(), host.getPort());
|
||||
conn.bind(socket, this.client.getParams());
|
||||
}
|
||||
|
||||
BasicHttpEntityEnclosingRequest post = new BasicHttpEntityEnclosingRequest("POST", "/");
|
||||
byte[] data = (byte[]) testData.get(r);
|
||||
ByteArrayEntity outgoing = new ByteArrayEntity(data);
|
||||
post.setEntity(outgoing);
|
||||
|
||||
HttpResponse response = this.client.execute(post, host, conn);
|
||||
assertEquals(HttpVersion.HTTP_1_0, response.getStatusLine().getProtocolVersion());
|
||||
byte[] received = EntityUtils.toByteArray(response.getEntity());
|
||||
byte[] expected = (byte[]) testData.get(r);
|
||||
|
||||
assertEquals(expected.length, received.length);
|
||||
for (int i = 0; i < expected.length; i++) {
|
||||
assertEquals(expected[i], received[i]);
|
||||
}
|
||||
if (!this.client.keepAlive(response)) {
|
||||
conn.close();
|
||||
}
|
||||
}
|
||||
|
||||
//Verify the connection metrics
|
||||
HttpConnectionMetrics cm = conn.getMetrics();
|
||||
assertEquals(reqNo, cm.getRequestCount());
|
||||
assertEquals(reqNo, cm.getResponseCount());
|
||||
} finally {
|
||||
conn.close();
|
||||
this.server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This test case executes a series of simple POST requests using
|
||||
* the 'expect: continue' handshake.
|
||||
*/
|
||||
@LargeTest
|
||||
public void testHttpPostsWithExpectContinue() throws Exception {
|
||||
|
||||
int reqNo = 20;
|
||||
|
||||
Random rnd = new Random();
|
||||
|
||||
// Prepare some random data
|
||||
List testData = new ArrayList(reqNo);
|
||||
for (int i = 0; i < reqNo; i++) {
|
||||
int size = rnd.nextInt(5000);
|
||||
byte[] data = new byte[size];
|
||||
rnd.nextBytes(data);
|
||||
testData.add(data);
|
||||
}
|
||||
|
||||
// Initialize the server-side request handler
|
||||
this.server.registerHandler("*", new HttpRequestHandler() {
|
||||
|
||||
public void handle(
|
||||
final HttpRequest request,
|
||||
final HttpResponse response,
|
||||
final HttpContext context) throws HttpException, IOException {
|
||||
|
||||
if (request instanceof HttpEntityEnclosingRequest) {
|
||||
HttpEntity incoming = ((HttpEntityEnclosingRequest) request).getEntity();
|
||||
byte[] data = EntityUtils.toByteArray(incoming);
|
||||
|
||||
ByteArrayEntity outgoing = new ByteArrayEntity(data);
|
||||
outgoing.setChunked(true);
|
||||
response.setEntity(outgoing);
|
||||
} else {
|
||||
StringEntity outgoing = new StringEntity("No content");
|
||||
response.setEntity(outgoing);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
this.server.start();
|
||||
|
||||
// Activate 'expect: continue' handshake
|
||||
this.client.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, true);
|
||||
|
||||
DefaultHttpClientConnection conn = new DefaultHttpClientConnection();
|
||||
HttpHost host = new HttpHost("localhost", this.server.getPort());
|
||||
|
||||
try {
|
||||
for (int r = 0; r < reqNo; r++) {
|
||||
if (!conn.isOpen()) {
|
||||
Socket socket = new Socket(host.getHostName(), host.getPort());
|
||||
conn.bind(socket, this.client.getParams());
|
||||
}
|
||||
|
||||
BasicHttpEntityEnclosingRequest post = new BasicHttpEntityEnclosingRequest("POST", "/");
|
||||
byte[] data = (byte[]) testData.get(r);
|
||||
ByteArrayEntity outgoing = new ByteArrayEntity(data);
|
||||
outgoing.setChunked(true);
|
||||
post.setEntity(outgoing);
|
||||
|
||||
HttpResponse response = this.client.execute(post, host, conn);
|
||||
byte[] received = EntityUtils.toByteArray(response.getEntity());
|
||||
byte[] expected = (byte[]) testData.get(r);
|
||||
|
||||
assertEquals(expected.length, received.length);
|
||||
for (int i = 0; i < expected.length; i++) {
|
||||
assertEquals(expected[i], received[i]);
|
||||
}
|
||||
if (!this.client.keepAlive(response)) {
|
||||
conn.close();
|
||||
}
|
||||
}
|
||||
|
||||
//Verify the connection metrics
|
||||
HttpConnectionMetrics cm = conn.getMetrics();
|
||||
assertEquals(reqNo, cm.getRequestCount());
|
||||
assertEquals(reqNo, cm.getResponseCount());
|
||||
} finally {
|
||||
conn.close();
|
||||
this.server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This test case executes a series of simple POST requests that do not
|
||||
* meet the target server expectations.
|
||||
*/
|
||||
@LargeTest
|
||||
public void testHttpPostsWithExpectationVerification() throws Exception {
|
||||
|
||||
int reqNo = 3;
|
||||
|
||||
// Initialize the server-side request handler
|
||||
this.server.registerHandler("*", new HttpRequestHandler() {
|
||||
|
||||
public void handle(
|
||||
final HttpRequest request,
|
||||
final HttpResponse response,
|
||||
final HttpContext context) throws HttpException, IOException {
|
||||
|
||||
StringEntity outgoing = new StringEntity("No content");
|
||||
response.setEntity(outgoing);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
this.server.setExpectationVerifier(new HttpExpectationVerifier() {
|
||||
|
||||
public void verify(
|
||||
final HttpRequest request,
|
||||
final HttpResponse response,
|
||||
final HttpContext context) throws HttpException {
|
||||
Header someheader = request.getFirstHeader("Secret");
|
||||
if (someheader != null) {
|
||||
int secretNumber;
|
||||
try {
|
||||
secretNumber = Integer.parseInt(someheader.getValue());
|
||||
} catch (NumberFormatException ex) {
|
||||
response.setStatusCode(HttpStatus.SC_BAD_REQUEST);
|
||||
return;
|
||||
}
|
||||
if (secretNumber < 2) {
|
||||
response.setStatusCode(HttpStatus.SC_EXPECTATION_FAILED);
|
||||
ByteArrayEntity outgoing = new ByteArrayEntity(
|
||||
EncodingUtils.getAsciiBytes("Wrong secret number"));
|
||||
response.setEntity(outgoing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
this.server.start();
|
||||
|
||||
// Activate 'expect: continue' handshake
|
||||
this.client.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, true);
|
||||
|
||||
DefaultHttpClientConnection conn = new DefaultHttpClientConnection();
|
||||
HttpHost host = new HttpHost("localhost", this.server.getPort());
|
||||
|
||||
try {
|
||||
for (int r = 0; r < reqNo; r++) {
|
||||
if (!conn.isOpen()) {
|
||||
Socket socket = new Socket(host.getHostName(), host.getPort());
|
||||
conn.bind(socket, this.client.getParams());
|
||||
}
|
||||
|
||||
BasicHttpEntityEnclosingRequest post = new BasicHttpEntityEnclosingRequest("POST", "/");
|
||||
post.addHeader("Secret", Integer.toString(r));
|
||||
ByteArrayEntity outgoing = new ByteArrayEntity(
|
||||
EncodingUtils.getAsciiBytes("No content"));
|
||||
post.setEntity(outgoing);
|
||||
|
||||
HttpResponse response = this.client.execute(post, host, conn);
|
||||
|
||||
HttpEntity entity = response.getEntity();
|
||||
assertNotNull(entity);
|
||||
entity.consumeContent();
|
||||
|
||||
if (r < 2) {
|
||||
assertEquals(HttpStatus.SC_EXPECTATION_FAILED, response.getStatusLine().getStatusCode());
|
||||
} else {
|
||||
assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
|
||||
}
|
||||
|
||||
if (!this.client.keepAlive(response)) {
|
||||
conn.close();
|
||||
}
|
||||
}
|
||||
//Verify the connection metrics
|
||||
HttpConnectionMetrics cm = conn.getMetrics();
|
||||
assertEquals(reqNo, cm.getRequestCount());
|
||||
assertEquals(reqNo, cm.getResponseCount());
|
||||
} finally {
|
||||
conn.close();
|
||||
this.server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,120 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.unit_tests;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.provider.Settings;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.test.suitebuilder.annotation.MediumTest;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
|
||||
import com.google.android.net.UrlRules;
|
||||
import static com.google.android.net.UrlRules.Rule;
|
||||
|
||||
/** Test loading and matching URL rewrite rules for UrlRules. */
|
||||
public class UrlRulesTest extends AndroidTestCase {
|
||||
@SmallTest
|
||||
public void testEmptyRules() {
|
||||
UrlRules rules = new UrlRules(new Rule[] { });
|
||||
assertTrue(rules.matchRule("http://foo.bar/") == Rule.DEFAULT);
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testInvalidRule() throws Exception {
|
||||
try {
|
||||
new Rule("rule", "foo bar");
|
||||
} catch (Exception e) {
|
||||
// Re-throw any exception except the one we're looking for.
|
||||
if (!e.toString().contains("Illegal rule: foo bar")) throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testRewriteRule() throws UrlRules.RuleFormatException {
|
||||
Rule rule = new Rule("test_rule",
|
||||
"http://foo.bar/ rewrite http://bar.foo/");
|
||||
assertEquals("test_rule", rule.mName);
|
||||
assertEquals("http://foo.bar/", rule.mPrefix);
|
||||
assertEquals("http://bar.foo/", rule.mRewrite);
|
||||
assertFalse(rule.mBlock);
|
||||
assertEquals("http://bar.foo/bat", rule.apply("http://foo.bar/bat"));
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testBlockRule() throws UrlRules.RuleFormatException {
|
||||
Rule rule = new Rule("test_rule",
|
||||
"http://foo.bar/ block");
|
||||
assertEquals("test_rule", rule.mName);
|
||||
assertEquals("http://foo.bar/", rule.mPrefix);
|
||||
assertTrue(rule.mRewrite == null);
|
||||
assertTrue(rule.mBlock);
|
||||
assertTrue(rule.apply("http://foo.bar/bat") == null);
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testMatchRule() throws UrlRules.RuleFormatException {
|
||||
UrlRules rules = new UrlRules(new Rule[] {
|
||||
new Rule("12", "http://one.two/ rewrite http://buckle.my.shoe/"),
|
||||
new Rule("34", "http://three.four/ rewrite http://close.the.door/"),
|
||||
new Rule("56", "http://five.six/ rewrite http://pick.up.sticks/"),
|
||||
});
|
||||
|
||||
assertTrue(rules.matchRule("https://one.two/") == Rule.DEFAULT);
|
||||
assertTrue(rules.matchRule("http://one.two") == Rule.DEFAULT);
|
||||
assertEquals("12", rules.matchRule("http://one.two/foo").mName);
|
||||
|
||||
String u = "http://five.six/bar";
|
||||
assertEquals("http://pick.up.sticks/bar", rules.matchRule(u).apply(u));
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testAmbiguousMatch() throws UrlRules.RuleFormatException {
|
||||
// Rule is the longest match wins.
|
||||
UrlRules rules = new UrlRules(new Rule[] {
|
||||
new Rule("1", "http://xyz/one rewrite http://rewrite/"),
|
||||
new Rule("123", "http://xyz/onetwothree rewrite http://rewrite/"),
|
||||
new Rule("12", "http://xyz/onetwo rewrite http://rewrite/"),
|
||||
});
|
||||
|
||||
assertEquals("1", rules.matchRule("http://xyz/one").mName);
|
||||
assertEquals("1", rules.matchRule("http://xyz/one...").mName);
|
||||
assertEquals("12", rules.matchRule("http://xyz/onetwo...").mName);
|
||||
assertEquals("123", rules.matchRule("http://xyz/onetwothree...").mName);
|
||||
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testGservicesRules() {
|
||||
// TODO: use a MockContentProvider/MockContentResolver instead.
|
||||
ContentResolver r = getContext().getContentResolver();
|
||||
|
||||
// Update the digest, so the UrlRules cache is reloaded.
|
||||
Settings.Gservices.putString(r, "digest", "testGservicesRules");
|
||||
Settings.Gservices.putString(r, "url:blank_test", "");
|
||||
Settings.Gservices.putString(r, "url:test",
|
||||
"http://foo.bar/ rewrite http://bar.foo/");
|
||||
|
||||
UrlRules rules = UrlRules.getRules(r); // Don't crash, please. :)
|
||||
assertTrue(rules.matchRule("http://bar.foo/") == Rule.DEFAULT);
|
||||
|
||||
Rule rule = rules.matchRule("http://foo.bar/bat");
|
||||
assertEquals("test", rule.mName);
|
||||
assertEquals("http://foo.bar/", rule.mPrefix);
|
||||
assertEquals("http://bar.foo/", rule.mRewrite);
|
||||
assertFalse(rule.mBlock);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user