1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5package org.chromium.net;
6
7import android.content.Context;
8import android.util.Log;
9
10import java.lang.reflect.Constructor;
11import java.nio.channels.WritableByteChannel;
12import java.util.Map;
13
14/**
15 * A factory for {@link HttpUrlRequest}'s, which uses the best HTTP stack
16 * available on the current platform.
17 */
18public abstract class HttpUrlRequestFactory {
19    private static final String TAG = "HttpUrlRequestFactory";
20
21    private static final String CHROMIUM_URL_REQUEST_FACTORY =
22            "org.chromium.net.ChromiumUrlRequestFactory";
23
24    public static HttpUrlRequestFactory createFactory(
25            Context context, HttpUrlRequestFactoryConfig config) {
26        HttpUrlRequestFactory factory = null;
27        if (!config.legacyMode()) {
28            factory = createChromiumFactory(context, config);
29        }
30        if (factory == null) {
31            // Default to HttpUrlConnection-based networking.
32            factory = new HttpUrlConnectionUrlRequestFactory(context, config);
33        }
34        Log.i(TAG, "Using network stack: " + factory.getName());
35        return factory;
36    }
37
38    /**
39     * Returns true if the factory is enabled.
40     */
41    public abstract boolean isEnabled();
42
43    /**
44     * Returns a human-readable name of the factory.
45     */
46    public abstract String getName();
47
48    /**
49     * Creates a new request intended for full-response buffering.
50     */
51    public abstract HttpUrlRequest createRequest(String url,
52            int requestPriority, Map<String, String> headers,
53            HttpUrlRequestListener listener);
54
55    /**
56     * Creates a new request intended for streaming.
57     */
58    public abstract HttpUrlRequest createRequest(String url,
59            int requestPriority, Map<String, String> headers,
60            WritableByteChannel channel, HttpUrlRequestListener listener);
61
62    private static HttpUrlRequestFactory createChromiumFactory(
63            Context context, HttpUrlRequestFactoryConfig config) {
64        HttpUrlRequestFactory factory = null;
65        try {
66            Class<? extends HttpUrlRequestFactory> factoryClass =
67                    HttpUrlRequestFactory.class.getClassLoader().
68                            loadClass(CHROMIUM_URL_REQUEST_FACTORY).
69                            asSubclass(HttpUrlRequestFactory.class);
70            Constructor<? extends HttpUrlRequestFactory> constructor =
71                    factoryClass.getConstructor(
72                            Context.class, HttpUrlRequestFactoryConfig.class);
73            HttpUrlRequestFactory chromiumFactory =
74                    constructor.newInstance(context, config);
75            if (chromiumFactory.isEnabled()) {
76                factory = chromiumFactory;
77            }
78        } catch (ClassNotFoundException e) {
79            // Leave as null
80        } catch (Exception e) {
81            throw new IllegalStateException(
82                    "Cannot instantiate: " +
83                    CHROMIUM_URL_REQUEST_FACTORY,
84                    e);
85        }
86        return factory;
87    }
88}
89