diff options
author | mef@chromium.org <mef@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-17 00:09:51 +0000 |
---|---|---|
committer | mef@chromium.org <mef@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-17 00:09:51 +0000 |
commit | 94de3e05dbde532c58791bac7f15266d896d3663 (patch) | |
tree | 4cfae92f2a2f3d1ff41bd36c424ce89c59db8383 /components | |
parent | c4b47790aa56e82303b224dcdb9be8b5dd79ed80 (diff) | |
download | chromium_src-94de3e05dbde532c58791bac7f15266d896d3663.zip chromium_src-94de3e05dbde532c58791bac7f15266d896d3663.tar.gz chromium_src-94de3e05dbde532c58791bac7f15266d896d3663.tar.bz2 |
Added Cronet HttpUrlRequestFactoryConfig.
BUG=354143
Review URL: https://codereview.chromium.org/260553002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@277587 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'components')
20 files changed, 542 insertions, 153 deletions
diff --git a/components/cronet.gypi b/components/cronet.gypi index 83a832c..9a8f3ec 100644 --- a/components/cronet.gypi +++ b/components/cronet.gypi @@ -44,6 +44,18 @@ 'includes': [ '../build/android/java_cpp_template.gypi' ], }, { + 'target_name': 'cronet_url_request_context_config_list', + 'type': 'none', + 'sources': [ + 'cronet/android/java/src/org/chromium/net/UrlRequestContextConfig.template', + ], + 'variables': { + 'package_name': 'org/chromium/cronet', + 'template_deps': ['cronet/url_request_context_config_list.h'], + }, + 'includes': [ '../build/android/java_cpp_template.gypi' ], + }, + { 'target_name': 'libcronet', 'type': 'shared_library', 'dependencies': [ @@ -53,11 +65,15 @@ '../third_party/icu/icu.gyp:icuuc', '../url/url.gyp:url_lib', 'cronet_jni_headers', + 'cronet_url_request_context_config_list', 'cronet_url_request_error_list', 'cronet_url_request_priority_list', '../net/net.gyp:net', ], 'sources': [ + 'cronet/url_request_context_config.cc', + 'cronet/url_request_context_config.h', + 'cronet/url_request_context_config_list.h', 'cronet/android/cronet_jni.cc', 'cronet/android/org_chromium_net_UrlRequest.cc', 'cronet/android/org_chromium_net_UrlRequest.h', @@ -65,6 +81,7 @@ 'cronet/android/org_chromium_net_UrlRequest_priority_list.h', 'cronet/android/org_chromium_net_UrlRequestContext.cc', 'cronet/android/org_chromium_net_UrlRequestContext.h', + 'cronet/android/org_chromium_net_UrlRequestContext_config_list.h', 'cronet/android/url_request_context_peer.cc', 'cronet/android/url_request_context_peer.h', 'cronet/android/url_request_peer.cc', diff --git a/components/cronet/android/java/src/org/chromium/net/ChromiumUrlRequest.java b/components/cronet/android/java/src/org/chromium/net/ChromiumUrlRequest.java index 6b20770..ee60408 100644 --- a/components/cronet/android/java/src/org/chromium/net/ChromiumUrlRequest.java +++ b/components/cronet/android/java/src/org/chromium/net/ChromiumUrlRequest.java @@ -32,7 +32,7 @@ class ChromiumUrlRequest extends UrlRequest implements HttpUrlRequest { private long mSize; - public ChromiumUrlRequest(ChromiumUrlRequestContext requestContext, + public ChromiumUrlRequest(UrlRequestContext requestContext, String url, int priority, Map<String, String> headers, HttpUrlRequestListener listener) { this(requestContext, url, priority, headers, @@ -40,7 +40,7 @@ class ChromiumUrlRequest extends UrlRequest implements HttpUrlRequest { mBufferFullResponse = true; } - public ChromiumUrlRequest(ChromiumUrlRequestContext requestContext, + public ChromiumUrlRequest(UrlRequestContext requestContext, String url, int priority, Map<String, String> headers, WritableByteChannel sink, HttpUrlRequestListener listener) { super(requestContext, url, convertRequestPriority(priority), headers, diff --git a/components/cronet/android/java/src/org/chromium/net/ChromiumUrlRequestContext.java b/components/cronet/android/java/src/org/chromium/net/ChromiumUrlRequestContext.java deleted file mode 100644 index e1416e1..0000000 --- a/components/cronet/android/java/src/org/chromium/net/ChromiumUrlRequestContext.java +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.net; - -import android.content.Context; -import android.util.Log; - -/** - * Provides context for the native HTTP operations. - */ -public class ChromiumUrlRequestContext extends UrlRequestContext { - private static final Object sLock = new Object(); - - private static final String TAG = "ChromiumNetwork"; - - private static ChromiumUrlRequestContext sInstance; - - private ChromiumUrlRequestContext(Context context, String userAgent, - int loggingLevel) { - super(context, userAgent, loggingLevel); - } - - public static ChromiumUrlRequestContext getInstance( - Context context) { - synchronized (sLock) { - if (sInstance == null) { - int loggingLevel; - if (Log.isLoggable(TAG, Log.VERBOSE)) { - loggingLevel = LOG_VERBOSE; - } else if (Log.isLoggable(TAG, Log.DEBUG)) { - loggingLevel = LOG_DEBUG; - } else { - loggingLevel = LOG_NONE; - } - sInstance = new ChromiumUrlRequestContext( - context.getApplicationContext(), - UserAgent.from(context), - loggingLevel); - } - } - return sInstance; - } -} diff --git a/components/cronet/android/java/src/org/chromium/net/ChromiumUrlRequestFactory.java b/components/cronet/android/java/src/org/chromium/net/ChromiumUrlRequestFactory.java index 0b0e9c2..57e4248 100644 --- a/components/cronet/android/java/src/org/chromium/net/ChromiumUrlRequestFactory.java +++ b/components/cronet/android/java/src/org/chromium/net/ChromiumUrlRequestFactory.java @@ -15,38 +15,41 @@ import java.util.Map; */ @UsedByReflection("HttpUrlRequestFactory.java") class ChromiumUrlRequestFactory extends HttpUrlRequestFactory { - private static ChromiumUrlRequestContext sRequestContext; + private UrlRequestContext mRequestContext; @UsedByReflection("HttpUrlRequestFactory.java") - public ChromiumUrlRequestFactory(Context context) { - if (sRequestContext == null && isEnabled()) { + public ChromiumUrlRequestFactory( + Context context, HttpUrlRequestFactoryConfig config) { + if (isEnabled()) { System.loadLibrary("cronet"); - sRequestContext = ChromiumUrlRequestContext.getInstance(context); + mRequestContext = new UrlRequestContext( + context.getApplicationContext(), UserAgent.from(context), + config.toString()); } } @Override - protected boolean isEnabled() { + public boolean isEnabled() { return Build.VERSION.SDK_INT >= 14; } @Override - protected String getName() { + public String getName() { return "Chromium/" + UrlRequestContext.getVersion(); } @Override - protected HttpUrlRequest createRequest(String url, int requestPriority, + public HttpUrlRequest createRequest(String url, int requestPriority, Map<String, String> headers, HttpUrlRequestListener listener) { - return new ChromiumUrlRequest(sRequestContext, url, requestPriority, + return new ChromiumUrlRequest(mRequestContext, url, requestPriority, headers, listener); } @Override - protected HttpUrlRequest createRequest(String url, int requestPriority, + public HttpUrlRequest createRequest(String url, int requestPriority, Map<String, String> headers, WritableByteChannel channel, HttpUrlRequestListener listener) { - return new ChromiumUrlRequest(sRequestContext, url, requestPriority, + return new ChromiumUrlRequest(mRequestContext, url, requestPriority, headers, channel, listener); } } diff --git a/components/cronet/android/java/src/org/chromium/net/HttpUrlConnectionUrlRequest.java b/components/cronet/android/java/src/org/chromium/net/HttpUrlConnectionUrlRequest.java index 77492aeb..f6db95e 100644 --- a/components/cronet/android/java/src/org/chromium/net/HttpUrlConnectionUrlRequest.java +++ b/components/cronet/android/java/src/org/chromium/net/HttpUrlConnectionUrlRequest.java @@ -169,6 +169,15 @@ class HttpUrlConnectionUrlRequest implements HttpUrlRequest { @Override public void start() { + getExecutor().execute(new Runnable() { + @Override + public void run() { + startOnExecutorThread(); + } + }); + } + + private void startOnExecutorThread() { boolean readingResponse = false; try { synchronized (mLock) { diff --git a/components/cronet/android/java/src/org/chromium/net/HttpUrlConnectionUrlRequestFactory.java b/components/cronet/android/java/src/org/chromium/net/HttpUrlConnectionUrlRequestFactory.java index 052131d..a0a243e 100644 --- a/components/cronet/android/java/src/org/chromium/net/HttpUrlConnectionUrlRequestFactory.java +++ b/components/cronet/android/java/src/org/chromium/net/HttpUrlConnectionUrlRequestFactory.java @@ -16,29 +16,30 @@ class HttpUrlConnectionUrlRequestFactory extends HttpUrlRequestFactory { private final Context mContext; - public HttpUrlConnectionUrlRequestFactory(Context context) { + public HttpUrlConnectionUrlRequestFactory( + Context context, HttpUrlRequestFactoryConfig config) { mContext = context.getApplicationContext(); } @Override - protected boolean isEnabled() { + public boolean isEnabled() { return true; } @Override - protected String getName() { + public String getName() { return "HttpUrlConnection"; } @Override - protected HttpUrlRequest createRequest(String url, int requestPriority, + public HttpUrlRequest createRequest(String url, int requestPriority, Map<String, String> headers, HttpUrlRequestListener listener) { return new HttpUrlConnectionUrlRequest(mContext, url, requestPriority, headers, listener); } @Override - protected HttpUrlRequest createRequest(String url, int requestPriority, + public HttpUrlRequest createRequest(String url, int requestPriority, Map<String, String> headers, WritableByteChannel channel, HttpUrlRequestListener listener) { return new HttpUrlConnectionUrlRequest(mContext, url, requestPriority, diff --git a/components/cronet/android/java/src/org/chromium/net/HttpUrlRequestFactory.java b/components/cronet/android/java/src/org/chromium/net/HttpUrlRequestFactory.java index 9ffd306..a500fd7 100644 --- a/components/cronet/android/java/src/org/chromium/net/HttpUrlRequestFactory.java +++ b/components/cronet/android/java/src/org/chromium/net/HttpUrlRequestFactory.java @@ -16,90 +16,73 @@ import java.util.Map; * available on the current platform. */ public abstract class HttpUrlRequestFactory { - private static final Object sLock = new Object(); - private static final String TAG = "HttpUrlRequestFactory"; private static final String CHROMIUM_URL_REQUEST_FACTORY = "org.chromium.net.ChromiumUrlRequestFactory"; - private static HttpUrlRequestFactory sFactory; - - private static HttpUrlRequestFactory getFactory( - Context context) { - synchronized (sLock) { - if (sFactory == null) { - try { - Class<? extends HttpUrlRequestFactory> factoryClass = - HttpUrlRequestFactory.class.getClassLoader(). - loadClass(CHROMIUM_URL_REQUEST_FACTORY). - asSubclass(HttpUrlRequestFactory.class); - Constructor<? extends HttpUrlRequestFactory> constructor = - factoryClass.getConstructor(Context.class); - HttpUrlRequestFactory chromiumFactory = - constructor.newInstance(context); - if (chromiumFactory.isEnabled()) { - sFactory = chromiumFactory; - } - } catch (ClassNotFoundException e) { - // Leave as null - } catch (Exception e) { - throw new IllegalStateException( - "Cannot instantiate: " + - CHROMIUM_URL_REQUEST_FACTORY, - e); - } - if (sFactory == null) { - // Default to HttpUrlConnection-based networking. - sFactory = new HttpUrlConnectionUrlRequestFactory(context); - } - Log.i(TAG, "Using network stack: " + sFactory.getName()); - } - return sFactory; + public static HttpUrlRequestFactory createFactory( + Context context, HttpUrlRequestFactoryConfig config) { + HttpUrlRequestFactory factory = null; + if (!config.legacyMode()) { + factory = createChromiumFactory(context, config); } - } - - /** - * Creates a new request intended for full-response buffering. - */ - public static HttpUrlRequest newRequest(Context context, String url, - int requestPriority, Map<String, String> headers, - HttpUrlRequestListener listener) { - return getFactory(context).createRequest(url, requestPriority, headers, - listener); - } - - /** - * Creates a new request intended for streaming the response. - */ - public static HttpUrlRequest newRequest(Context context, String url, - int requestPriority, Map<String, String> headers, - WritableByteChannel channel, HttpUrlRequestListener listener) { - return getFactory(context).createRequest(url, requestPriority, headers, - channel, listener); + if (factory == null) { + // Default to HttpUrlConnection-based networking. + factory = new HttpUrlConnectionUrlRequestFactory(context, config); + } + Log.i(TAG, "Using network stack: " + factory.getName()); + return factory; } /** * Returns true if the factory is enabled. */ - protected abstract boolean isEnabled(); + public abstract boolean isEnabled(); /** * Returns a human-readable name of the factory. */ - protected abstract String getName(); + public abstract String getName(); /** * Creates a new request intended for full-response buffering. */ - protected abstract HttpUrlRequest createRequest(String url, + public abstract HttpUrlRequest createRequest(String url, int requestPriority, Map<String, String> headers, HttpUrlRequestListener listener); /** * Creates a new request intended for streaming. */ - protected abstract HttpUrlRequest createRequest(String url, + public abstract HttpUrlRequest createRequest(String url, int requestPriority, Map<String, String> headers, WritableByteChannel channel, HttpUrlRequestListener listener); + + private static HttpUrlRequestFactory createChromiumFactory( + Context context, HttpUrlRequestFactoryConfig config) { + HttpUrlRequestFactory factory = null; + try { + Class<? extends HttpUrlRequestFactory> factoryClass = + HttpUrlRequestFactory.class.getClassLoader(). + loadClass(CHROMIUM_URL_REQUEST_FACTORY). + asSubclass(HttpUrlRequestFactory.class); + Constructor<? extends HttpUrlRequestFactory> constructor = + factoryClass.getConstructor( + Context.class, HttpUrlRequestFactoryConfig.class); + HttpUrlRequestFactory chromiumFactory = + constructor.newInstance(context, config); + if (chromiumFactory.isEnabled()) { + factory = chromiumFactory; + } + } catch (ClassNotFoundException e) { + // Leave as null + } catch (Exception e) { + throw new IllegalStateException( + "Cannot instantiate: " + + CHROMIUM_URL_REQUEST_FACTORY, + e); + } + return factory; + } } diff --git a/components/cronet/android/java/src/org/chromium/net/HttpUrlRequestFactoryConfig.java b/components/cronet/android/java/src/org/chromium/net/HttpUrlRequestFactoryConfig.java new file mode 100644 index 0000000..913bae8 --- /dev/null +++ b/components/cronet/android/java/src/org/chromium/net/HttpUrlRequestFactoryConfig.java @@ -0,0 +1,135 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.net; + +import org.json.JSONException; +import org.json.JSONObject; + +/** + * A config for HttpUrlRequestFactory, which allows runtime configuration of + * HttpUrlRequestFactory. + */ +public class HttpUrlRequestFactoryConfig { + /** + * Default config enables SPDY, QUIC, in memory http cache. + */ + public HttpUrlRequestFactoryConfig() { + enableLegacyMode(false); + enableQUIC(false); + enableSPDY(true); + enableHttpCache(HttpCache.IN_MEMORY, 100 * 1024); + } + + /** + * Create config from json serialized using @toString. + */ + public HttpUrlRequestFactoryConfig(String json) throws JSONException { + mConfig = new JSONObject(json); + } + + /** + * Boolean, use HttpUrlRequest-based implementation if true. All other + * keys are not applicable. + */ + public HttpUrlRequestFactoryConfig enableLegacyMode(boolean value) { + return putBoolean(UrlRequestContextConfig.ENABLE_LEGACY_MODE, value); + } + + public boolean legacyMode() { + return mConfig.optBoolean(UrlRequestContextConfig.ENABLE_LEGACY_MODE); + } + + /** + * Boolean, enable QUIC if true. + */ + public HttpUrlRequestFactoryConfig enableQUIC(boolean value) { + return putBoolean(UrlRequestContextConfig.ENABLE_QUIC, value); + } + + /** + * Boolean, enable SPDY if true. + */ + public HttpUrlRequestFactoryConfig enableSPDY(boolean value) { + return putBoolean(UrlRequestContextConfig.ENABLE_SPDY, value); + } + + /** + * Enumeration, Disable or Enable Disk or Memory Cache and specify its + * maximum size in bytes. + */ + public enum HttpCache { DISABLED, IN_MEMORY, DISK }; + public HttpUrlRequestFactoryConfig enableHttpCache(HttpCache value, + long maxSize) { + switch(value) { + case DISABLED: + return putString(UrlRequestContextConfig.HTTP_CACHE, + UrlRequestContextConfig.HTTP_CACHE_DISABLED); + case DISK: + putLong(UrlRequestContextConfig.HTTP_CACHE_MAX_SIZE, maxSize); + return putString(UrlRequestContextConfig.HTTP_CACHE, + UrlRequestContextConfig.HTTP_CACHE_DISK); + case IN_MEMORY: + putLong(UrlRequestContextConfig.HTTP_CACHE_MAX_SIZE, maxSize); + return putString(UrlRequestContextConfig.HTTP_CACHE, + UrlRequestContextConfig.HTTP_CACHE_MEMORY); + } + return this; + } + + /** + * String, path to directory for HTTP Cache and Cookie Storage. + */ + public HttpUrlRequestFactoryConfig setStoragePath(String value) { + return putString(UrlRequestContextConfig.STORAGE_PATH, value); + } + + /** + * Get JSON string representation of the config. + */ + public String toString() { + return mConfig.toString(); + } + + /** + * Sets a boolean value in the config. Returns a reference to the same + * config object, so you can chain put calls together. + */ + private HttpUrlRequestFactoryConfig putBoolean(String key, boolean value) { + try { + mConfig.put(key, value); + } catch (JSONException e) { + ; + } + return this; + } + + /** + * Sets a long value in the config. Returns a reference to the same + * config object, so you can chain put calls together. + */ + private HttpUrlRequestFactoryConfig putLong(String key, long value) { + try { + mConfig.put(key, value); + } catch (JSONException e) { + ; + } + return this; + } + + /** + * Sets a string value in the config. Returns a reference to the same + * config object, so you can chain put calls together. + */ + private HttpUrlRequestFactoryConfig putString(String key, String value) { + try { + mConfig.put(key, value); + } catch (JSONException e) { + ; + } + return this; + } + + private JSONObject mConfig = new JSONObject(); +} diff --git a/components/cronet/android/java/src/org/chromium/net/UrlRequestContext.java b/components/cronet/android/java/src/org/chromium/net/UrlRequestContext.java index f8abfb8..8396f2a 100644 --- a/components/cronet/android/java/src/org/chromium/net/UrlRequestContext.java +++ b/components/cronet/android/java/src/org/chromium/net/UrlRequestContext.java @@ -7,6 +7,7 @@ package org.chromium.net; import android.content.Context; import android.os.ConditionVariable; import android.os.Process; +import android.util.Log; import org.chromium.base.CalledByNative; import org.chromium.base.JNINamespace; @@ -16,9 +17,10 @@ import org.chromium.base.JNINamespace; */ @JNINamespace("cronet") public class UrlRequestContext { - protected static final int LOG_NONE = 0; - protected static final int LOG_DEBUG = 1; - protected static final int LOG_VERBOSE = 2; + private static final int LOG_NONE = 0; + private static final int LOG_DEBUG = 1; + private static final int LOG_VERBOSE = 2; + private static final String LOG_TAG = "ChromiumNetwork"; /** * Native peer object, owned by UrlRequestContext. @@ -30,13 +32,14 @@ public class UrlRequestContext { /** * Constructor. * - * @param loggingLevel see {@link #LOG_NONE}, {@link #LOG_DEBUG} and - * {@link #LOG_VERBOSE}. */ protected UrlRequestContext(Context context, String userAgent, - int loggingLevel) { + String config) { mUrlRequestContextPeer = nativeCreateRequestContextPeer(context, - userAgent, loggingLevel); + userAgent, getLoggingLevel(), config); + if (mUrlRequestContextPeer == 0) + throw new NullPointerException("Context Peer creation failed"); + // TODO(mef): Revisit the need of block here. mStarted.block(2000); } @@ -100,12 +103,28 @@ public class UrlRequestContext { return mUrlRequestContextPeer; } + /** + * @return loggingLevel see {@link #LOG_NONE}, {@link #LOG_DEBUG} and + * {@link #LOG_VERBOSE}. + */ + private int getLoggingLevel() { + int loggingLevel; + if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) { + loggingLevel = LOG_VERBOSE; + } else if (Log.isLoggable(LOG_TAG, Log.DEBUG)) { + loggingLevel = LOG_DEBUG; + } else { + loggingLevel = LOG_NONE; + } + return loggingLevel; + } + private static native String nativeGetVersion(); // Returns an instance URLRequestContextPeer to be stored in // mUrlRequestContextPeer. private native long nativeCreateRequestContextPeer(Context context, - String userAgent, int loggingLevel); + String userAgent, int loggingLevel, String config); private native void nativeReleaseRequestContextPeer( long urlRequestContextPeer); diff --git a/components/cronet/android/java/src/org/chromium/net/UrlRequestContextConfig.template b/components/cronet/android/java/src/org/chromium/net/UrlRequestContextConfig.template new file mode 100644 index 0000000..3d553ef --- /dev/null +++ b/components/cronet/android/java/src/org/chromium/net/UrlRequestContextConfig.template @@ -0,0 +1,14 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.net; + +// A simple auto-generated interface used to list config params as used by +// both org.chromium.net.HttpUrlRequestFactoryConfig and +// net/cronet/android/org_chromium_net_UrlRequestContext.h +public interface UrlRequestContextConfig { +#define DEFINE_CONTEXT_CONFIG(x) public static final String x = #x; +#include "components/cronet/android/org_chromium_net_UrlRequestContextConfig_list.h" +#undef DEFINE_CONTEXT_CONFIG +} diff --git a/components/cronet/android/org_chromium_net_UrlRequestContext.cc b/components/cronet/android/org_chromium_net_UrlRequestContext.cc index 38b6e81..375300a 100644 --- a/components/cronet/android/org_chromium_net_UrlRequestContext.cc +++ b/components/cronet/android/org_chromium_net_UrlRequestContext.cc @@ -4,12 +4,18 @@ #include "components/cronet/android/org_chromium_net_UrlRequestContext.h" +#include <string> + #include "base/android/jni_android.h" #include "base/android/jni_string.h" +#include "base/json/json_reader.h" +#include "base/memory/scoped_ptr.h" #include "base/metrics/statistics_recorder.h" +#include "base/values.h" #include "components/cronet/android/org_chromium_net_UrlRequest.h" #include "components/cronet/android/url_request_context_peer.h" #include "components/cronet/android/url_request_peer.h" +#include "components/cronet/url_request_context_config.h" #include "jni/UrlRequestContext_jni.h" // Version of this build of Chromium NET. @@ -63,10 +69,27 @@ static jlong CreateRequestContextPeer(JNIEnv* env, jobject object, jobject context, jstring user_agent, - jint log_level) { - const char* user_agent_utf8 = env->GetStringUTFChars(user_agent, NULL); - std::string user_agent_string(user_agent_utf8); - env->ReleaseStringUTFChars(user_agent, user_agent_utf8); + jint log_level, + jstring config) { + std::string user_agent_string = + base::android::ConvertJavaStringToUTF8(env, user_agent); + + std::string config_string = + base::android::ConvertJavaStringToUTF8(env, config); + + scoped_ptr<base::Value> config_value(base::JSONReader::Read(config_string)); + if (!config_value || !config_value->IsType(base::Value::TYPE_DICTIONARY)) { + DLOG(ERROR) << "Bad JSON: " << config_string; + return 0; + } + + scoped_ptr<URLRequestContextConfig> context_config( + new URLRequestContextConfig()); + base::JSONValueConverter<URLRequestContextConfig> converter; + if (!converter.Convert(*config_value, context_config.get())) { + DLOG(ERROR) << "Bad Config: " << config_value; + return 0; + } // Set application context. base::android::ScopedJavaLocalRef<jobject> scoped_context(env, context); @@ -81,7 +104,7 @@ static jlong CreateRequestContextPeer(JNIEnv* env, logging_level, kVersion); peer->AddRef(); // Hold onto this ref-counted object. - peer->Initialize(); + peer->Initialize(context_config.Pass()); return reinterpret_cast<jlong>(peer); } diff --git a/components/cronet/android/sample/javatests/src/org/chromium/cronet_sample_apk/CronetSampleUrlTest.java b/components/cronet/android/sample/javatests/src/org/chromium/cronet_sample_apk/CronetSampleUrlTest.java index 0c18708..8602376 100644 --- a/components/cronet/android/sample/javatests/src/org/chromium/cronet_sample_apk/CronetSampleUrlTest.java +++ b/components/cronet/android/sample/javatests/src/org/chromium/cronet_sample_apk/CronetSampleUrlTest.java @@ -7,6 +7,7 @@ package org.chromium.cronet_sample_apk; import android.test.suitebuilder.annotation.SmallTest; import org.chromium.base.test.util.Feature; +import org.chromium.net.HttpUrlRequestFactoryConfig; import java.io.File; @@ -86,4 +87,26 @@ public class CronetSampleUrlTest extends CronetSampleTestBase { assertTrue(file.delete()); assertTrue(!file.exists()); } + + @SmallTest + @Feature({"Cronet"}) + public void testLegacyLoadUrl() throws Exception { + HttpUrlRequestFactoryConfig config = new HttpUrlRequestFactoryConfig(); + config.enableLegacyMode(true); + + String[] commandLineArgs = { + CronetSampleActivity.CONFIG_KEY, config.toString() }; + CronetSampleActivity activity = + launchCronetSampleWithUrlAndCommandLineArgs(URL, + commandLineArgs); + + // Make sure the activity was created as expected. + assertNotNull(activity); + + waitForActiveShellToBeDoneLoading(); + + // Make sure that the URL is set as expected. + assertEquals(URL, activity.getUrl()); + assertEquals(200, activity.getHttpStatusCode()); + } } diff --git a/components/cronet/android/sample/javatests/src/org/chromium/cronet_sample_apk/HttpUrlRequestFactoryTest.java b/components/cronet/android/sample/javatests/src/org/chromium/cronet_sample_apk/HttpUrlRequestFactoryTest.java new file mode 100644 index 0000000..c97ad52 --- /dev/null +++ b/components/cronet/android/sample/javatests/src/org/chromium/cronet_sample_apk/HttpUrlRequestFactoryTest.java @@ -0,0 +1,40 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.cronet_sample_apk; + +import android.test.InstrumentationTestCase; +import android.test.suitebuilder.annotation.SmallTest; + +import org.chromium.base.test.util.Feature; +import org.chromium.net.HttpUrlRequestFactory; +import org.chromium.net.HttpUrlRequestFactoryConfig; + +/** + * Tests for {@link ChunkedWritableByteChannel} + */ +public class HttpUrlRequestFactoryTest extends InstrumentationTestCase { + @SmallTest + @Feature({"Cronet"}) + public void testCreateFactory() { + HttpUrlRequestFactoryConfig config = new HttpUrlRequestFactoryConfig(); + HttpUrlRequestFactory factory = HttpUrlRequestFactory.createFactory( + getInstrumentation().getContext(), config); + assertNotNull("Factory should be created", factory); + assertTrue("Factory should not be legacy", + "HttpUrlConnection" != factory.getName()); + } + + @SmallTest + @Feature({"Cronet"}) + public void testCreateLegacyFactory() { + HttpUrlRequestFactoryConfig config = new HttpUrlRequestFactoryConfig(); + config.enableLegacyMode(true); + + HttpUrlRequestFactory factory = HttpUrlRequestFactory.createFactory( + getInstrumentation().getContext(), config); + assertNotNull("Factory should be created", factory); + assertEquals("HttpUrlConnection", factory.getName()); + } +} diff --git a/components/cronet/android/sample/src/org/chromium/cronet_sample_apk/CronetSampleActivity.java b/components/cronet/android/sample/src/org/chromium/cronet_sample_apk/CronetSampleActivity.java index f667037..a0a6463 100644 --- a/components/cronet/android/sample/src/org/chromium/cronet_sample_apk/CronetSampleActivity.java +++ b/components/cronet/android/sample/src/org/chromium/cronet_sample_apk/CronetSampleActivity.java @@ -16,6 +16,7 @@ import android.widget.Toast; import org.chromium.net.HttpUrlRequest; import org.chromium.net.HttpUrlRequestFactory; +import org.chromium.net.HttpUrlRequestFactoryConfig; import org.chromium.net.HttpUrlRequestListener; import org.chromium.net.LibraryLoader; import org.chromium.net.UrlRequest; @@ -40,9 +41,12 @@ public class CronetSampleActivity extends Activity { public static final String COMMAND_LINE_ARGS_KEY = "commandLineArgs"; public static final String POST_DATA_KEY = "postData"; + public static final String CONFIG_KEY = "config"; UrlRequestContext mRequestContext; + HttpUrlRequestFactory mRequestFactory; + String mUrl; boolean mLoading = false; @@ -52,7 +56,7 @@ public class CronetSampleActivity extends Activity { class SampleRequestContext extends UrlRequestContext { public SampleRequestContext() { super(getApplicationContext(), "Cronet Sample", - UrlRequestContext.LOG_VERBOSE); + new HttpUrlRequestFactoryConfig().toString()); } } @@ -132,6 +136,27 @@ public class CronetSampleActivity extends Activity { } mRequestContext = new SampleRequestContext(); + HttpUrlRequestFactoryConfig config = new HttpUrlRequestFactoryConfig(); + config.enableHttpCache(HttpUrlRequestFactoryConfig.HttpCache.IN_MEMORY, + 100 * 1024) + .enableSPDY(true) + .enableQUIC(true); + + // Override config if it is passed from the launcher. + String configString = getCommandLineArg(CONFIG_KEY); + if (configString != null) { + try { + Log.i(TAG, "Using Config: " + configString); + config = new HttpUrlRequestFactoryConfig(configString); + } catch (org.json.JSONException e) { + Log.e(TAG, "Invalid Config.", e); + finish(); + return; + } + } + + mRequestFactory = HttpUrlRequestFactory.createFactory( + getApplicationContext(), config); String appUrl = getUrlFromIntent(getIntent()); if (appUrl == null) { @@ -162,7 +187,7 @@ public class CronetSampleActivity extends Activity { return intent != null ? intent.getDataString() : null; } - private void applyCommandLineToRequest(UrlRequest request) { + private String getCommandLineArg(String key) { Intent intent = getIntent(); Bundle extras = intent.getExtras(); Log.i(TAG, "Cronet extras: " + extras); @@ -172,16 +197,23 @@ public class CronetSampleActivity extends Activity { for (int i = 0; i < commandLine.length; ++i) { Log.i(TAG, "Cronet commandLine[" + i + "]=" + commandLine[i]); - if (commandLine[i].equals(POST_DATA_KEY)) { - InputStream dataStream = new ByteArrayInputStream( - commandLine[++i].getBytes()); - ReadableByteChannel dataChannel = Channels.newChannel( - dataStream); - request.setUploadChannel("text/plain", dataChannel); + if (commandLine[i].equals(key)) { + return commandLine[++i]; } } } } + return null; + } + + private void applyCommandLineToRequest(UrlRequest request) { + String postData = getCommandLineArg(POST_DATA_KEY); + if (postData != null) { + InputStream dataStream = new ByteArrayInputStream( + postData.getBytes()); + ReadableByteChannel dataChannel = Channels.newChannel(dataStream); + request.setUploadChannel("text/plain", dataChannel); + } } private void startWithURL(String url) { @@ -192,9 +224,8 @@ public class CronetSampleActivity extends Activity { HashMap<String, String> headers = new HashMap<String, String>(); HttpUrlRequestListener listener = new SampleHttpUrlRequestListener(); - HttpUrlRequest request = HttpUrlRequestFactory.newRequest( - getApplicationContext(), url, - UrlRequestPriority.MEDIUM, headers, listener); + HttpUrlRequest request = mRequestFactory.createRequest( + url, UrlRequestPriority.MEDIUM, headers, listener); request.start(); } diff --git a/components/cronet/android/sample/src/org/chromium/cronet_sample_apk/CronetSampleApplication.java b/components/cronet/android/sample/src/org/chromium/cronet_sample_apk/CronetSampleApplication.java index fb37e76..3b71587 100644 --- a/components/cronet/android/sample/src/org/chromium/cronet_sample_apk/CronetSampleApplication.java +++ b/components/cronet/android/sample/src/org/chromium/cronet_sample_apk/CronetSampleApplication.java @@ -4,15 +4,15 @@ package org.chromium.cronet_sample_apk; +import android.app.Application; import android.util.Log; -import org.chromium.base.BaseChromiumApplication; import org.chromium.base.PathUtils; /** * Application for managing the Cronet Sample. */ -public class CronetSampleApplication extends BaseChromiumApplication { +public class CronetSampleApplication extends Application { private static final String TAG = "CronetSampleApplication"; private static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "cronet_sample"; diff --git a/components/cronet/android/url_request_context_peer.cc b/components/cronet/android/url_request_context_peer.cc index 20b404e..df2cb4e 100644 --- a/components/cronet/android/url_request_context_peer.cc +++ b/components/cronet/android/url_request_context_peer.cc @@ -4,7 +4,10 @@ #include "components/cronet/android/url_request_context_peer.h" +#include "base/bind.h" #include "base/file_util.h" +#include "base/single_thread_task_runner.h" +#include "components/cronet/url_request_context_config.h" #include "net/base/net_errors.h" #include "net/base/net_log_logger.h" #include "net/cert/cert_verifier.h" @@ -120,7 +123,8 @@ URLRequestContextPeer::URLRequestContextPeer( version_ = version; } -void URLRequestContextPeer::Initialize() { +void URLRequestContextPeer::Initialize( + scoped_ptr<URLRequestContextConfig> config) { network_thread_ = new base::Thread("network"); base::Thread::Options options; options.message_loop_type = base::MessageLoop::TYPE_IO; @@ -128,16 +132,19 @@ void URLRequestContextPeer::Initialize() { GetNetworkTaskRunner()->PostTask( FROM_HERE, - base::Bind(&URLRequestContextPeer::InitializeURLRequestContext, this)); + base::Bind(&URLRequestContextPeer::InitializeURLRequestContext, + this, + Passed(&config))); } -void URLRequestContextPeer::InitializeURLRequestContext() { +void URLRequestContextPeer::InitializeURLRequestContext( + scoped_ptr<URLRequestContextConfig> config) { // TODO(mmenke): Add method to have the builder enable SPDY. net::URLRequestContextBuilder context_builder; context_builder.set_network_delegate(new BasicNetworkDelegate()); context_builder.set_proxy_config_service( new net::ProxyConfigServiceFixed(net::ProxyConfig())); - context_builder.DisableHttpCache(); + config->ConfigureURLRequestContextBuilder(&context_builder); context_.reset(context_builder.Build()); @@ -156,6 +163,7 @@ URLRequestContextPeer::~URLRequestContextPeer() { net_log_observer_.reset(); } StopNetLog(); + // TODO(mef): Ensure that |network_thread_| is destroyed properly. } const std::string& URLRequestContextPeer::GetUserAgent(const GURL& url) const { diff --git a/components/cronet/android/url_request_context_peer.h b/components/cronet/android/url_request_context_peer.h index 256a649..00893c9 100644 --- a/components/cronet/android/url_request_context_peer.h +++ b/components/cronet/android/url_request_context_peer.h @@ -23,6 +23,8 @@ class NetLogLogger; namespace cronet { +struct URLRequestContextConfig; + // Implementation of the Chromium NetLog observer interface. class NetLogObserver : public net::NetLog::ThreadSafeObserver { public: @@ -56,7 +58,7 @@ class URLRequestContextPeer : public net::URLRequestContextGetter { std::string user_agent, int log_level, const char* version); - void Initialize(); + void Initialize(scoped_ptr<URLRequestContextConfig> config); const std::string& GetUserAgent(const GURL& url) const; @@ -86,7 +88,7 @@ class URLRequestContextPeer : public net::URLRequestContextGetter { virtual ~URLRequestContextPeer(); // Initializes |context_| on the IO thread. - void InitializeURLRequestContext(); + void InitializeURLRequestContext(scoped_ptr<URLRequestContextConfig> config); DISALLOW_COPY_AND_ASSIGN(URLRequestContextPeer); }; diff --git a/components/cronet/url_request_context_config.cc b/components/cronet/url_request_context_config.cc new file mode 100644 index 0000000..11f2def --- /dev/null +++ b/components/cronet/url_request_context_config.cc @@ -0,0 +1,59 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/cronet/url_request_context_config.h" + +#include "net/url_request/url_request_context_builder.h" + +namespace cronet { + +#define DEFINE_CONTEXT_CONFIG(x) const char REQUEST_CONTEXT_CONFIG_##x[] = #x; +#include "components/cronet/url_request_context_config_list.h" +#undef DEFINE_CONTEXT_CONFIG + +URLRequestContextConfig::URLRequestContextConfig() { +} + +URLRequestContextConfig::~URLRequestContextConfig() { +} + +void URLRequestContextConfig::ConfigureURLRequestContextBuilder( + net::URLRequestContextBuilder* context_builder) { + std::string config_cache; + if (http_cache != REQUEST_CONTEXT_CONFIG_HTTP_CACHE_DISABLED) { + net::URLRequestContextBuilder::HttpCacheParams cache_params; + if (http_cache == REQUEST_CONTEXT_CONFIG_HTTP_CACHE_DISK && + !storage_path.empty()) { + cache_params.type = net::URLRequestContextBuilder::HttpCacheParams::DISK; + cache_params.path = base::FilePath(storage_path); + } else { + cache_params.type = + net::URLRequestContextBuilder::HttpCacheParams::IN_MEMORY; + } + cache_params.max_size = http_cache_max_size; + context_builder->EnableHttpCache(cache_params); + } else { + context_builder->DisableHttpCache(); + } + + context_builder->SetSpdyAndQuicEnabled(enable_spdy, enable_quic); + // TODO(mef): Use |config| to set cookies. +} + +// static +void URLRequestContextConfig::RegisterJSONConverter( + base::JSONValueConverter<URLRequestContextConfig>* converter) { + converter->RegisterBoolField(REQUEST_CONTEXT_CONFIG_ENABLE_QUIC, + &URLRequestContextConfig::enable_quic); + converter->RegisterBoolField(REQUEST_CONTEXT_CONFIG_ENABLE_SPDY, + &URLRequestContextConfig::enable_spdy); + converter->RegisterStringField(REQUEST_CONTEXT_CONFIG_HTTP_CACHE, + &URLRequestContextConfig::http_cache); + converter->RegisterIntField(REQUEST_CONTEXT_CONFIG_HTTP_CACHE_MAX_SIZE, + &URLRequestContextConfig::http_cache_max_size); + converter->RegisterStringField(REQUEST_CONTEXT_CONFIG_STORAGE_PATH, + &URLRequestContextConfig::storage_path); +} + +} // namespace cronet diff --git a/components/cronet/url_request_context_config.h b/components/cronet/url_request_context_config.h new file mode 100644 index 0000000..b295d02 --- /dev/null +++ b/components/cronet/url_request_context_config.h @@ -0,0 +1,47 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_CRONET_URL_REQUEST_CONTEXT_CONFIG_H_ +#define COMPONENTS_CRONET_URL_REQUEST_CONTEXT_CONFIG_H_ + +#include <string> + +#include "base/json/json_value_converter.h" + +namespace net { +class URLRequestContextBuilder; +} // namespace net + +namespace cronet { + +// Common configuration parameters used by Cronet to configure +// URLRequestContext. Can be parsed from JSON string passed through JNI. +struct URLRequestContextConfig { + URLRequestContextConfig(); + ~URLRequestContextConfig(); + + // Configure |context_builder| based on |this|. + void ConfigureURLRequestContextBuilder( + net::URLRequestContextBuilder* context_builder); + + // Register |converter| for use in converter.Convert(). + static void RegisterJSONConverter( + base::JSONValueConverter<URLRequestContextConfig>* converter); + + // Enable QUIC. + bool enable_quic; + // Enable SPDY. + bool enable_spdy; + // Type of http cache: "HTTP_CACHE_DISABLED", "HTTP_CACHE_DISK" or + // "HTTP_CACHE_IN_MEMORY". + std::string http_cache; + // Max size of http cache in bytes. + int http_cache_max_size; + // Storage path for http cache and cookie storage. + std::string storage_path; +}; + +} // namespace cronet + +#endif // COMPONENTS_CRONET_URL_REQUEST_CONTEXT_CONFIG_H_ diff --git a/components/cronet/url_request_context_config_list.h b/components/cronet/url_request_context_config_list.h new file mode 100644 index 0000000..fa77ca4 --- /dev/null +++ b/components/cronet/url_request_context_config_list.h @@ -0,0 +1,20 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file intentionally does not have header guards, it's included +// inside a macro to generate enum values. +#ifndef DEFINE_CONTEXT_CONFIG +#error "DEFINE_CONTEXT_CONFIG should be defined before including this file" +#endif +// See HttpUrlRequestFactoryConfig.java for description of these parameters. +DEFINE_CONTEXT_CONFIG(STORAGE_PATH) +DEFINE_CONTEXT_CONFIG(ENABLE_LEGACY_MODE) +DEFINE_CONTEXT_CONFIG(ENABLE_QUIC) +DEFINE_CONTEXT_CONFIG(ENABLE_SPDY) +DEFINE_CONTEXT_CONFIG(HTTP_CACHE) +DEFINE_CONTEXT_CONFIG(HTTP_CACHE_MAX_SIZE) + +DEFINE_CONTEXT_CONFIG(HTTP_CACHE_DISABLED) +DEFINE_CONTEXT_CONFIG(HTTP_CACHE_DISK) +DEFINE_CONTEXT_CONFIG(HTTP_CACHE_MEMORY) |