Chromium Code Reviews| Index: components/cronet/android/api/src/org/chromium/net/CronetEngine.java |
| diff --git a/components/cronet/android/api/src/org/chromium/net/CronetEngine.java b/components/cronet/android/api/src/org/chromium/net/CronetEngine.java |
| index cd7f42558d03a9e3bcae83a468e22f5c47f6e1ef..efc47901e95b056c81851f0fef3b09ec51b5fa49 100644 |
| --- a/components/cronet/android/api/src/org/chromium/net/CronetEngine.java |
| +++ b/components/cronet/android/api/src/org/chromium/net/CronetEngine.java |
| @@ -6,12 +6,18 @@ package org.chromium.net; |
| import android.content.Context; |
| import android.net.http.HttpResponseCache; |
| +import android.support.annotation.VisibleForTesting; |
| import java.io.IOException; |
| import java.net.URL; |
| import java.net.URLConnection; |
| import java.net.URLStreamHandlerFactory; |
| +import java.util.ArrayList; |
| +import java.util.Collections; |
| +import java.util.Comparator; |
| import java.util.Date; |
| +import java.util.Iterator; |
| +import java.util.List; |
| import java.util.Set; |
| import java.util.concurrent.Executor; |
| @@ -63,7 +69,20 @@ public abstract class CronetEngine { |
| * the lifetime of {@code context} unnecessarily. |
| */ |
| public Builder(Context context) { |
| - mBuilderDelegate = ImplLoader.load(context); |
| + this(createBuilderDelegate(context)); |
| + } |
| + |
| + /** |
| + * Constructs {@link Builder} with a given delegate that provides the actual implementation |
| + * of the {@code Builder} methods. This constructor is used only by the internal |
| + * implementation. |
| + * |
| + * @param builderDelegate delegate that provides the actual implementation. |
| + * |
| + * {@hide} |
| + */ |
| + public Builder(ICronetEngineBuilder builderDelegate) { |
| + mBuilderDelegate = builderDelegate; |
| } |
| /** |
| @@ -282,6 +301,107 @@ public abstract class CronetEngine { |
| public CronetEngine build() { |
| return mBuilderDelegate.build(); |
| } |
| + |
| + /** |
| + * Creates an implementation of {@link ICronetEngineBuilder} that can be used |
| + * to delegate the builder calls to. The method uses {@link CronetProviders} |
| + * to obtain the list of available providers. |
| + * |
| + * @param context Android Context to use. |
| + * @return the created {@code ICronetEngineBuilder}. |
| + */ |
| + private static ICronetEngineBuilder createBuilderDelegate(Context context) { |
| + List<CronetProvider> providerList = |
| + getEnabledCronetProviders(context, CronetProviders.getInstance()); |
| + CronetEngine.Builder builder = providerList.get(0).createBuilder(); |
| + return builder.mBuilderDelegate; |
|
pauljensen
2017/01/23 14:44:28
how about combining these two lines together?
retu
kapishnikov
2017/01/23 18:16:52
Done.
|
| + } |
| + |
| + /** |
| + * Returns the list of available and enabled {@link CronetProvider}. The returned list |
| + * is sorted based on the provider versions and types. |
| + * |
| + * @param context Android Context to use. |
| + * @return the sorted list of enabled providers. The list contains at least one provider. |
| + * @throws RuntimeException is the list of providers is empty or all of the providers |
| + * are disabled. |
| + */ |
| + @VisibleForTesting |
| + static List<CronetProvider> getEnabledCronetProviders( |
| + Context context, CronetProviders providers) { |
| + // Check that there is at least one available provider. |
| + List<CronetProvider> providerList = new ArrayList<>(providers.getAllProviders(context)); |
| + if (providerList.size() == 0) { |
| + throw new RuntimeException("Unable to find any Cronet provider." |
| + + " Have you included all necessary jars?"); |
| + } |
| + |
| + // Exclude disabled providers from the list. |
| + for (Iterator<CronetProvider> i = providerList.iterator(); i.hasNext();) { |
| + CronetProvider provider = i.next(); |
| + if (!provider.isEnabled()) { |
| + i.remove(); |
| + } |
| + } |
| + |
| + // Check that there is at least one enabled provider. |
| + if (providerList.size() == 0) { |
| + throw new RuntimeException("All available Cronet providers are disabled." |
| + + " A provider should be enabled before it can be used."); |
| + } |
| + |
| + // Sort providers based on version and type. |
| + Collections.sort(providerList, new Comparator<CronetProvider>() { |
| + @Override |
| + public int compare(CronetProvider p1, CronetProvider p2) { |
| + // The platform provider should always be at the end of the list. |
| + if (CronetProviders.PROVIDER_NAME_PLATFORM.equals(p1.getName())) { |
| + return 1; |
| + } |
| + if (CronetProviders.PROVIDER_NAME_PLATFORM.equals(p2.getName())) { |
| + return -1; |
| + } |
| + // A provider with higher version should go first. |
| + return -compareVersions(p1.getVersion(), p2.getVersion()); |
| + } |
| + }); |
| + return providerList; |
| + } |
| + |
| + /** |
| + * Compares two strings that contain versions. The string should only contain |
| + * dot-separated segments that contain an arbitrary number of digits digits [0-9]. |
| + * |
| + * @param s1 the first string. |
| + * @param s2 the second string. |
| + * @return -1 if s1<s2, +1 if s1>s2 and 0 if s1=s2. If two versions are equal, the |
| + * version with the higher number of segments is considered to be higher. |
| + * |
| + * @throws IllegalArgumentException if any of the strings contains an illegal |
| + * version number. |
| + */ |
| + @VisibleForTesting |
| + static int compareVersions(String s1, String s2) { |
| + if (s1 == null || s2 == null) { |
| + throw new IllegalArgumentException("The input values cannot be null"); |
| + } |
| + String[] s1segments = s1.split("\\."); |
| + String[] s2segments = s2.split("\\."); |
| + for (int i = 0; i < s1segments.length && i < s2segments.length; i++) { |
| + try { |
| + int s1segment = Integer.parseInt(s1segments[i]); |
| + int s2segment = Integer.parseInt(s2segments[i]); |
| + if (s1segment != s2segment) { |
| + return Integer.signum(s1segment - s2segment); |
| + } |
| + } catch (NumberFormatException e) { |
| + throw new IllegalArgumentException("Unable to convert version segments into" |
| + + " integers: " + s1segments[i] + " & " + s2segments[i], |
| + e); |
| + } |
| + } |
| + return Integer.signum(s1segments.length - s2segments.length); |
| + } |
| } |
| /** |