1// Copyright 2013 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.android_webview;
6
7import android.graphics.Bitmap;
8import android.os.AsyncTask;
9import android.util.Log;
10
11import org.chromium.base.ThreadUtils;
12
13import java.io.IOException;
14import java.io.InputStream;
15import java.io.OutputStream;
16import java.io.PipedInputStream;
17import java.io.PipedOutputStream;
18import java.util.Random;
19
20/**
21 * This class takes advantage of shouldInterceptRequest(), returns the bitmap from
22 * WebChromeClient.getDefaultVidoePoster() when the mDefaultVideoPosterURL is requested.
23 *
24 * The shouldInterceptRequest is used to get the default video poster, if the url is
25 * the mDefaultVideoPosterURL.
26 */
27public class DefaultVideoPosterRequestHandler {
28    private static InputStream getInputStream(final AwContentsClient contentClient)
29            throws IOException {
30        final PipedInputStream inputStream = new PipedInputStream();
31        final PipedOutputStream outputStream = new PipedOutputStream(inputStream);
32
33        // Send the request to UI thread to callback to the client, and if it provides a
34        // valid bitmap bounce on to the worker thread pool to compress it into the piped
35        // input/output stream.
36        ThreadUtils.runOnUiThread(new Runnable() {
37            @Override
38            public void run() {
39                final Bitmap defaultVideoPoster = contentClient.getDefaultVideoPoster();
40                if (defaultVideoPoster == null) {
41                    closeOutputStream(outputStream);
42                    return;
43                }
44                AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
45                    @Override
46                    public void run() {
47                        try {
48                            defaultVideoPoster.compress(Bitmap.CompressFormat.PNG, 100,
49                                    outputStream);
50                            outputStream.flush();
51                        } catch (IOException e) {
52                            Log.e(TAG, null, e);
53                        } finally {
54                            closeOutputStream(outputStream);
55                        }
56                    }
57                });
58            }
59        });
60        return inputStream;
61    }
62
63    private static void closeOutputStream(OutputStream outputStream) {
64        try {
65            outputStream.close();
66        } catch (IOException e) {
67            Log.e(TAG, null, e);
68        }
69    }
70
71    private static final String TAG = "DefaultVideoPosterRequestHandler";
72    private String mDefaultVideoPosterURL;
73    private AwContentsClient mContentClient;
74
75    public DefaultVideoPosterRequestHandler(AwContentsClient contentClient) {
76        mDefaultVideoPosterURL = generateDefaulVideoPosterURL();
77        mContentClient = contentClient;
78    }
79
80    /**
81     * Used to get the image if the url is mDefaultVideoPosterURL.
82     *
83     * @param url the url requested
84     * @return AwWebResourceResponse which caller can get the image if the url is
85     * the default video poster URL, otherwise null is returned.
86     */
87    public AwWebResourceResponse shouldInterceptRequest(final String url) {
88        if (!mDefaultVideoPosterURL.equals(url)) return null;
89
90        try {
91            return new AwWebResourceResponse("image/png", null, getInputStream(mContentClient));
92        } catch (IOException e) {
93            Log.e(TAG, null, e);
94            return null;
95        }
96    }
97
98    public String getDefaultVideoPosterURL() {
99        return mDefaultVideoPosterURL;
100    }
101
102    /**
103     * @return a unique URL which has little chance to be used by application.
104     */
105    private static String generateDefaulVideoPosterURL() {
106        Random randomGenerator = new Random();
107        String path = String.valueOf(randomGenerator.nextLong());
108        // The scheme of this URL should be kept in sync with kAndroidWebViewVideoPosterScheme
109        // on the native side (see android_webview/common/url_constants.h)
110        return "android-webview-video-poster:default_video_poster/" + path;
111    }
112}
113