HTML5VideoViewProxy.java revision 290c34ac3a36b407b74b42c37501c2d0cdac70ad
16fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu/*
26fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * Copyright (C) 2009 The Android Open Source Project
36fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu *
46fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * Licensed under the Apache License, Version 2.0 (the "License");
56fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * you may not use this file except in compliance with the License.
66fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * You may obtain a copy of the License at
76fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu *
86fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu *      http://www.apache.org/licenses/LICENSE-2.0
96fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu *
106fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * Unless required by applicable law or agreed to in writing, software
116fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * distributed under the License is distributed on an "AS IS" BASIS,
126fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * See the License for the specific language governing permissions and
146fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * limitations under the License.
156fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu */
166fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
176fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescupackage android.webkit;
186fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
196fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescuimport android.content.Context;
2064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport android.graphics.Bitmap;
2164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport android.graphics.BitmapFactory;
223c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescuimport android.media.MediaPlayer;
233c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescuimport android.media.MediaPlayer.OnPreparedListener;
2464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport android.media.MediaPlayer.OnCompletionListener;
2564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport android.media.MediaPlayer.OnErrorListener;
2664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport android.net.http.EventHandler;
2764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport android.net.http.Headers;
2864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport android.net.http.RequestHandle;
2964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport android.net.http.RequestQueue;
3064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport android.net.http.SslCertificate;
3164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport android.net.http.SslError;
326fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescuimport android.net.Uri;
336fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescuimport android.os.Bundle;
346fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescuimport android.os.Handler;
356fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescuimport android.os.Looper;
366fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescuimport android.os.Message;
376fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescuimport android.util.Log;
383c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescuimport android.view.MotionEvent;
396fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescuimport android.view.View;
403c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescuimport android.view.ViewGroup;
410a5ce01eda210f83619ada0603a80fd883512fe9Patrick Scottimport android.webkit.ViewManager.ChildView;
423c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescuimport android.widget.AbsoluteLayout;
4364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport android.widget.ImageView;
446fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescuimport android.widget.MediaController;
456fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescuimport android.widget.VideoView;
466fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
4764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport java.io.ByteArrayOutputStream;
4864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport java.io.IOException;
496fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescuimport java.util.HashMap;
50290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescuimport java.util.Map;
516fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
526fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu/**
533c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu * <p>Proxy for HTML5 video views.
546fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu */
55290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescuclass HTML5VideoViewProxy extends Handler
56290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                          implements MediaPlayer.OnPreparedListener,
57290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                          MediaPlayer.OnCompletionListener {
586fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    // Logging tag.
596fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    private static final String LOGTAG = "HTML5VideoViewProxy";
606fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
613c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu    // Message Ids for WebCore thread -> UI thread communication.
626fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    private static final int INIT              = 100;
636fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    private static final int PLAY              = 101;
6464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    private static final int SET_POSTER        = 102;
65290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    private static final int SEEK              = 103;
66290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    private static final int PAUSE             = 104;
676fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
6864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // Message Ids to be handled on the WebCore thread
69290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    private static final int PREPARED          = 200;
70290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    private static final int ENDED             = 201;
7164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
72290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    // The C++ MediaPlayerPrivateAndroid object.
73290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    int mNativePointer;
7464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // The handler for WebCore thread messages;
7564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    private Handler mWebCoreHandler;
763c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu    // The WebView instance that created this view.
773c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu    private WebView mWebView;
783c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu    // The ChildView instance used by the ViewManager.
793c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu    private ChildView mChildView;
8064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // The poster image to be shown when the video is not playing.
8164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    private ImageView mPosterView;
8264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // The poster downloader.
8364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    private PosterDownloader mPosterDownloader;
84290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    // The seek position.
85290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    private int mSeekPosition;
8664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // A helper class to control the playback. This executes on the UI thread!
8764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    private static final class VideoPlayer {
8864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The proxy that is currently playing (if any).
8964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private static HTML5VideoViewProxy mCurrentProxy;
9064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The VideoView instance. This is a singleton for now, at least until
9164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // http://b/issue?id=1973663 is fixed.
9264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private static VideoView mVideoView;
9364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
9464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private static final WebChromeClient.CustomViewCallback mCallback =
9564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            new WebChromeClient.CustomViewCallback() {
9664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                public void onCustomViewHidden() {
9764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    // At this point the videoview is pretty much destroyed.
9864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    // It listens to SurfaceHolder.Callback.SurfaceDestroyed event
9964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    // which happens when the video view is detached from its parent
10064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    // view. This happens in the WebChromeClient before this method
10164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    // is invoked.
10264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    mCurrentProxy.playbackEnded();
10364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    mCurrentProxy = null;
10464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    mVideoView = null;
10564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                }
10664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            };
10764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
108290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        public static void play(String url, int time, HTML5VideoViewProxy proxy,
109290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                WebChromeClient client) {
11064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            if (mCurrentProxy != null) {
11164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                // Some other video is already playing. Notify the caller that its playback ended.
11264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                proxy.playbackEnded();
11364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                return;
1143c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu            }
11564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mCurrentProxy = proxy;
11664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mVideoView = new VideoView(proxy.getContext());
11764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mVideoView.setWillNotDraw(false);
11864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mVideoView.setMediaController(new MediaController(proxy.getContext()));
11964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mVideoView.setVideoURI(Uri.parse(url));
120290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu            mVideoView.setOnCompletionListener(proxy);
121290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu            mVideoView.setOnPreparedListener(proxy);
122290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu            mVideoView.seekTo(time);
12364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mVideoView.start();
12464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            client.onShowCustomView(mVideoView, mCallback);
12564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
126290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu
127290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        public static void seek(int time, HTML5VideoViewProxy proxy) {
128290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu            if (mCurrentProxy == proxy && time >= 0 && mVideoView != null) {
129290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                mVideoView.seekTo(time);
130290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu            }
131290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        }
132290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu
133290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        public static void pause(HTML5VideoViewProxy proxy) {
134290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu            if (mCurrentProxy == proxy && mVideoView != null) {
135290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                mVideoView.pause();
136290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu            }
137290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        }
138290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    }
139290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu
140290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    // A bunch event listeners for our VideoView
141290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    // MediaPlayer.OnPreparedListener
142290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    public void onPrepared(MediaPlayer mp) {
143290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        Message msg = Message.obtain(mWebCoreHandler, PREPARED);
144290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        Map<String, Object> map = new HashMap<String, Object>();
145290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        map.put("dur", new Integer(mp.getDuration()));
146290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        map.put("width", new Integer(mp.getVideoWidth()));
147290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        map.put("height", new Integer(mp.getVideoHeight()));
148290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        msg.obj = map;
149290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        mWebCoreHandler.sendMessage(msg);
150290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    }
151290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu
152290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    // MediaPlayer.OnCompletionListener;
153290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    public void onCompletion(MediaPlayer mp) {
154290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        playbackEnded();
155290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    }
156290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu
157290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    public void playbackEnded() {
158290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        Message msg = Message.obtain(mWebCoreHandler, ENDED);
159290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        mWebCoreHandler.sendMessage(msg);
16064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    }
1613c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu
16264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // Handler for the messages from WebCore thread to the UI thread.
16364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    @Override
16464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    public void handleMessage(Message msg) {
16564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // This executes on the UI thread.
16664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        switch (msg.what) {
16764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            case INIT: {
16864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                mPosterView = new ImageView(mWebView.getContext());
16964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                mChildView.mView = mPosterView;
17064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                break;
1713c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu            }
17264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            case PLAY: {
17364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                String url = (String) msg.obj;
17464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                WebChromeClient client = mWebView.getWebChromeClient();
17564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                if (client != null) {
176290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                    VideoPlayer.play(url, mSeekPosition, this, client);
17764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                }
17864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                break;
17964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            }
18064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            case SET_POSTER: {
18164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                Bitmap poster = (Bitmap) msg.obj;
18264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                mPosterView.setImageBitmap(poster);
18364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                break;
18464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            }
185290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu            case SEEK: {
186290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                Integer time = (Integer) msg.obj;
187290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                mSeekPosition = time;
188290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                VideoPlayer.seek(mSeekPosition, this);
189290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                break;
190290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu            }
191290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu            case PAUSE: {
192290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                VideoPlayer.pause(this);
193290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                break;
194290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu            }
19564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
19664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    }
19764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
19864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // Everything below this comment executes on the WebCore thread, except for
19964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // the EventHandler methods, which are called on the network thread.
20064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
20164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // A helper class that knows how to download posters
20264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    private static final class PosterDownloader implements EventHandler {
20364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The request queue. This is static as we have one queue for all posters.
20464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private static RequestQueue mRequestQueue;
20564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private static int mQueueRefCount = 0;
20664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The poster URL
20764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private String mUrl;
20864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The proxy we're doing this for.
20964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private final HTML5VideoViewProxy mProxy;
21064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The poster bytes. We only touch this on the network thread.
21164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private ByteArrayOutputStream mPosterBytes;
21264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The request handle. We only touch this on the WebCore thread.
21364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private RequestHandle mRequestHandle;
21464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The response status code.
21564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private int mStatusCode;
21664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The response headers.
21764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private Headers mHeaders;
21864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The handler to handle messages on the WebCore thread.
21964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private Handler mHandler;
22064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
22164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public PosterDownloader(String url, HTML5VideoViewProxy proxy) {
22264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mUrl = url;
22364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mProxy = proxy;
22464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mHandler = new Handler();
22564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
22664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // Start the download. Called on WebCore thread.
22764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public void start() {
22864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            retainQueue();
22964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mRequestHandle = mRequestQueue.queueRequest(mUrl, "GET", null, this, null, 0);
23064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
23164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // Cancel the download if active and release the queue. Called on WebCore thread.
23264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public void cancelAndReleaseQueue() {
23364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            if (mRequestHandle != null) {
23464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                mRequestHandle.cancel();
23564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                mRequestHandle = null;
23664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            }
23764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            releaseQueue();
23864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
23964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // EventHandler methods. Executed on the network thread.
24064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public void status(int major_version,
24164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                int minor_version,
24264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                int code,
24364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                String reason_phrase) {
24464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mStatusCode = code;
24564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
2463c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu
24764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public void headers(Headers headers) {
24864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mHeaders = headers;
2493c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        }
2503c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu
25164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public void data(byte[] data, int len) {
25264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            if (mPosterBytes == null) {
25364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                mPosterBytes = new ByteArrayOutputStream();
2543c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu            }
25564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mPosterBytes.write(data, 0, len);
2563c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        }
2573c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu
25864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public void endData() {
25964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            if (mStatusCode == 200) {
26064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                if (mPosterBytes.size() > 0) {
26164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    Bitmap poster = BitmapFactory.decodeByteArray(
26264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                            mPosterBytes.toByteArray(), 0, mPosterBytes.size());
26364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    if (poster != null) {
26464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                        mProxy.doSetPoster(poster);
26564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    }
26664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                }
26764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                cleanup();
26864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            } else if (mStatusCode >= 300 && mStatusCode < 400) {
26964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                // We have a redirect.
27064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                mUrl = mHeaders.getLocation();
27164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                if (mUrl != null) {
27264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    mHandler.post(new Runnable() {
27364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                       public void run() {
27464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                           if (mRequestHandle != null) {
27564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                               mRequestHandle.setupRedirect(mUrl, mStatusCode,
27664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                                       new HashMap<String, String>());
27764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                           }
27864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                       }
27964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    });
28064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                }
28164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            }
2823c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        }
2833c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu
28464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public void certificate(SslCertificate certificate) {
28564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            // Don't care.
2863c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        }
2873c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu
28864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public void error(int id, String description) {
28964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            cleanup();
29064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
29164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
29264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public boolean handleSslErrorRequest(SslError error) {
29364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            // Don't care. If this happens, data() will never be called so
29464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            // mPosterBytes will never be created, so no need to call cleanup.
29564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            return false;
29664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
29764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // Tears down the poster bytes stream. Called on network thread.
29864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private void cleanup() {
29964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            if (mPosterBytes != null) {
30064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                try {
30164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    mPosterBytes.close();
30264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                } catch (IOException ignored) {
30364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    // Ignored.
30464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                } finally {
30564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    mPosterBytes = null;
30664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                }
3073c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu            }
30864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
30964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
31064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // Queue management methods. Called on WebCore thread.
31164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private void retainQueue() {
31264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            if (mRequestQueue == null) {
31364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                mRequestQueue = new RequestQueue(mProxy.getContext());
3143c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu            }
31564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mQueueRefCount++;
3163c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        }
3173c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu
31864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private void releaseQueue() {
31964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            if (mQueueRefCount == 0) {
32064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                return;
32164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            }
32264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            if (--mQueueRefCount == 0) {
32364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                mRequestQueue.shutdown();
32464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                mRequestQueue = null;
32564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            }
3263c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        }
3273c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu    }
3286fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
3296fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    /**
3306fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu     * Private constructor.
331290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu     * @param webView is the WebView that hosts the video.
332290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu     * @param nativePtr is the C++ pointer to the MediaPlayerPrivate object.
3336fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu     */
334290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    private HTML5VideoViewProxy(WebView webView, int nativePtr) {
3356fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu        // This handler is for the main (UI) thread.
3366fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu        super(Looper.getMainLooper());
3373c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        // Save the WebView object.
3383c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        mWebView = webView;
339290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        // Save the native ptr
340290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        mNativePointer = nativePtr;
34164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // create the message handler for this thread
34264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        createWebCoreHandler();
3436fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    }
3446fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
34564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    private void createWebCoreHandler() {
34664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        mWebCoreHandler = new Handler() {
34764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            @Override
34864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            public void handleMessage(Message msg) {
34964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                switch (msg.what) {
350290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                    case PREPARED: {
351290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                        Map<String, Object> map = (Map<String, Object>) msg.obj;
352290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                        Integer duration = (Integer) map.get("dur");
353290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                        Integer width = (Integer) map.get("width");
354290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                        Integer height = (Integer) map.get("height");
355290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                        nativeOnPrepared(duration.intValue(), width.intValue(),
356290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                                height.intValue(), mNativePointer);
357290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                        break;
358290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                    }
359290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                    case ENDED:
360290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                        nativeOnEnded(mNativePointer);
361290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                        break;
3623c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu                }
36364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            }
36464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        };
36564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    }
36664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
36764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    private void doSetPoster(Bitmap poster) {
36864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        if (poster == null) {
36964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            return;
3706fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu        }
37164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // Send the bitmap over to the UI thread.
37264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        Message message = obtainMessage(SET_POSTER);
37364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        message.obj = poster;
37464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        sendMessage(message);
3756fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    }
3766fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
37764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    public Context getContext() {
37864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        return mWebView.getContext();
37964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    }
38064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
38164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // The public methods below are all called from WebKit only.
3826fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    /**
3836fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu     * Play a video stream.
3846fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu     * @param url is the URL of the video stream.
3856fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu     */
3863c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu    public void play(String url) {
38764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        if (url == null) {
38864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            return;
38964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
3906fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu        Message message = obtainMessage(PLAY);
39164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        message.obj = url;
3926fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu        sendMessage(message);
3936fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    }
3946fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
39564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    /**
396290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu     * Seek into the video stream.
397290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu     * @param  time is the position in the video stream.
398290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu     */
399290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    public void seek(int time) {
400290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        Message message = obtainMessage(SEEK);
401290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        message.obj = new Integer(time);
402290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        sendMessage(message);
403290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    }
404290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu
405290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    /**
406290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu     * Pause the playback.
407290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu     */
408290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    public void pause() {
409290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        Message message = obtainMessage(PAUSE);
410290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        sendMessage(message);
411290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    }
412290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu
413290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    /**
41464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu     * Create the child view that will cary the poster.
41564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu     */
4163c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu    public void createView() {
4173c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        mChildView = mWebView.mViewManager.createView();
4183c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        sendMessage(obtainMessage(INIT));
4190a5ce01eda210f83619ada0603a80fd883512fe9Patrick Scott    }
4200a5ce01eda210f83619ada0603a80fd883512fe9Patrick Scott
42164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    /**
42264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu     * Attach the poster view.
42364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu     * @param x, y are the screen coordinates where the poster should be hung.
42464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu     * @param width, height denote the size of the poster.
42564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu     */
4263c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu    public void attachView(int x, int y, int width, int height) {
4273c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        if (mChildView == null) {
4283c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu            return;
4293c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        }
4303c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        mChildView.attachView(x, y, width, height);
4310a5ce01eda210f83619ada0603a80fd883512fe9Patrick Scott    }
4320a5ce01eda210f83619ada0603a80fd883512fe9Patrick Scott
43364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    /**
43464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu     * Remove the child view and, thus, the poster.
43564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu     */
4363c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu    public void removeView() {
4373c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        if (mChildView == null) {
4383c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu            return;
4393c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        }
4403c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        mChildView.removeView();
44164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // This is called by the C++ MediaPlayerPrivate dtor.
44264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // Cancel any active poster download.
44364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        if (mPosterDownloader != null) {
44464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mPosterDownloader.cancelAndReleaseQueue();
44564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
44664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    }
44764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
44864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    /**
44964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu     * Load the poster image.
45064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu     * @param url is the URL of the poster image.
45164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu     */
45264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    public void loadPoster(String url) {
45364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        if (url == null) {
45464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            return;
45564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
45664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // Cancel any active poster download.
45764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        if (mPosterDownloader != null) {
45864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mPosterDownloader.cancelAndReleaseQueue();
45964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
46064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // Load the poster asynchronously
46164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        mPosterDownloader = new PosterDownloader(url, this);
46264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        mPosterDownloader.start();
4630a5ce01eda210f83619ada0603a80fd883512fe9Patrick Scott    }
4640a5ce01eda210f83619ada0603a80fd883512fe9Patrick Scott
4656fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    /**
4663c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu     * The factory for HTML5VideoViewProxy instances.
4676fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu     * @param webViewCore is the WebViewCore that is requesting the proxy.
4686fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu     *
4693c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu     * @return a new HTML5VideoViewProxy object.
4706fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu     */
471290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    public static HTML5VideoViewProxy getInstance(WebViewCore webViewCore, int nativePtr) {
472290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        return new HTML5VideoViewProxy(webViewCore.getWebView(), nativePtr);
4736fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    }
474290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu
475290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    private native void nativeOnPrepared(int duration, int width, int height, int nativePointer);
476290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    private native void nativeOnEnded(int nativePointer);
4776fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu}
478