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 | |
5 | package org.chromium.android_webview; |
6 | |
7 | import android.graphics.Bitmap; |
8 | import android.os.AsyncTask; |
9 | import android.util.Log; |
10 | |
11 | import org.chromium.base.ThreadUtils; |
12 | |
13 | import java.io.IOException; |
14 | import java.io.InputStream; |
15 | import java.io.OutputStream; |
16 | import java.io.PipedInputStream; |
17 | import java.io.PipedOutputStream; |
18 | import 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 | */ |
27 | public 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 InterceptedRequestData which caller can get the image if the url is |
85 | * the default video poster URL, otherwise null is returned. |
86 | */ |
87 | public InterceptedRequestData shouldInterceptRequest(final String url) { |
88 | if (!mDefaultVideoPosterURL.equals(url)) return null; |
89 | |
90 | try { |
91 | return new InterceptedRequestData("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 | return "android-webview:default_video_poster/" + path; |
109 | } |
110 | } |