Basic changes to get embedded video working.

Add the ViewManager class to handle child views within a WebView. This class
attaches and removes the views in the UI thread. It also scales the layout
params based on the scale of the WebView.
diff --git a/core/java/android/webkit/HTML5VideoViewProxy.java b/core/java/android/webkit/HTML5VideoViewProxy.java
index 973cb010..5b2c0e2c 100644
--- a/core/java/android/webkit/HTML5VideoViewProxy.java
+++ b/core/java/android/webkit/HTML5VideoViewProxy.java
@@ -24,6 +24,7 @@
 import android.os.Message;
 import android.util.Log;
 import android.view.View;
+import android.webkit.ViewManager.ChildView;
 import android.widget.MediaController;
 import android.widget.VideoView;
 
@@ -46,8 +47,6 @@
 
     // The singleton instance.
     private static HTML5VideoViewProxy sInstance;
-    // The VideoView driven via this proxy.
-    private VideoView mVideoView;
     // The context object used to initialize the VideoView and the
     // MediaController.
     private Context mContext;
@@ -61,12 +60,6 @@
         super(Looper.getMainLooper());
         // Save the context object.
         mContext = context;
-        // Send a message to the UI thread to create the VideoView.
-        // This need to be done on the UI thread, or else the
-        // event Handlers used by the VideoView and MediaController
-        // will be attached to the wrong thread.
-        Message message = obtainMessage(INIT);
-        sendMessage(message);
     }
 
     @Override
@@ -74,25 +67,22 @@
         // This executes on the UI thread.
         switch (msg.what) {
             case INIT:
+                ChildView child = (ChildView) msg.obj;
                 // Create the video view and set a default controller.
-                mVideoView = new VideoView(mContext);
-                mVideoView.setMediaController(new MediaController(mContext));
+                VideoView v = new VideoView(mContext);
+                // This is needed because otherwise there will be a black square
+                // stuck on the screen.
+                v.setWillNotDraw(false);
+                v.setMediaController(new MediaController(mContext));
+                child.mView = v;
                 break;
             case PLAY:
-                // Check if the fullscreen video view is currently playing.
-                // If it is, ignore the message.
-                if (!mVideoView.isPlaying()) {
-                    HashMap<String, Object> map =
+                HashMap<String, Object> map =
                         (HashMap<String, Object>) msg.obj;
-                    String url = (String) map.get("url");
-                    WebView webview = (WebView) map.get("webview");
-                    WebChromeClient client = webview.getWebChromeClient();
-                    if (client != null) {
-                        mVideoView.setVideoURI(Uri.parse(url));
-                        mVideoView.start();
-                        client.onShowCustomView(mVideoView);
-                    }
-                }
+                String url = (String) map.get("url");
+                VideoView view = (VideoView) map.get("view");
+                view.setVideoURI(Uri.parse(url));
+                view.start();
                 break;
         }
     }
@@ -102,16 +92,35 @@
      * @param url is the URL of the video stream.
      * @param webview is the WebViewCore that is requesting the playback.
      */
-    public void play(String url, WebViewCore webviewCore) {
+    public void play(String url, ChildView child) {
         // We need to know the webview that is requesting the playback.
         Message message = obtainMessage(PLAY);
         HashMap<String, Object> map = new HashMap();
         map.put("url", url);
-        map.put("webview", webviewCore.getWebView());
+        map.put("view", child.mView);
         message.obj = map;
         sendMessage(message);
     }
 
+    public ChildView createView(WebViewCore core) {
+        WebView w = core.getWebView();
+        if (w == null) {
+            return null;
+        }
+        ChildView child = w.mViewManager.createView();
+        sendMessage(obtainMessage(INIT, child));
+        return child;
+    }
+
+    public void attachView(ChildView child, int x, int y, int width,
+            int height) {
+        child.attachView(x, y, width, height);
+    }
+
+    public void removeView(ChildView child) {
+        child.removeView();
+    }
+
     /**
      * The factory for HTML5VideoViewProxy instances. Right now,
      * it only produces a singleton.
diff --git a/core/java/android/webkit/ViewManager.java b/core/java/android/webkit/ViewManager.java
new file mode 100644
index 0000000..476e85c
--- /dev/null
+++ b/core/java/android/webkit/ViewManager.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.AbsoluteLayout;
+
+import java.util.ArrayList;
+
+class ViewManager {
+    private final WebView mWebView;
+    private final ArrayList<ChildView> mChildren = new ArrayList<ChildView>();
+    private boolean mHidden;
+
+    class ChildView {
+        int x;
+        int y;
+        int width;
+        int height;
+        View mView; // generic view to show
+
+        ChildView() {
+        }
+
+        void setBounds(int x, int y, int width, int height) {
+            this.x = x;
+            this.y = y;
+            this.width = width;
+            this.height = height;
+        }
+
+        void attachView(int x, int y, int width, int height) {
+            if (mView == null) {
+                return;
+            }
+            setBounds(x, y, width, height);
+            final AbsoluteLayout.LayoutParams lp =
+                    new AbsoluteLayout.LayoutParams(ctv(width), ctv(height),
+                            ctv(x), ctv(y));
+            mWebView.mPrivateHandler.post(new Runnable() {
+                public void run() {
+                    // This method may be called multiple times. If the view is
+                    // already attached, just set the new LayoutParams,
+                    // otherwise attach the view and add it to the list of
+                    // children.
+                    if (mView.getParent() != null) {
+                        mView.setLayoutParams(lp);
+                    } else {
+                        mWebView.addView(mView, lp);
+                        mChildren.add(ChildView.this);
+                    }
+                }
+            });
+        }
+
+        void removeView() {
+            if (mView == null) {
+                return;
+            }
+            mWebView.mPrivateHandler.post(new Runnable() {
+                public void run() {
+                    mWebView.removeView(mView);
+                    mChildren.remove(ChildView.this);
+                }
+            });
+        }
+    }
+
+    ViewManager(WebView w) {
+        mWebView = w;
+    }
+
+    ChildView createView() {
+        return new ChildView();
+    }
+
+    // contentToView shorthand.
+    private int ctv(int val) {
+        return mWebView.contentToView(val);
+    }
+
+    void scaleAll() {
+        for (ChildView v : mChildren) {
+            View view = v.mView;
+            AbsoluteLayout.LayoutParams lp =
+                    (AbsoluteLayout.LayoutParams) view.getLayoutParams();
+            lp.width = ctv(v.width);
+            lp.height = ctv(v.height);
+            lp.x = ctv(v.x);
+            lp.y = ctv(v.y);
+            view.setLayoutParams(lp);
+        }
+    }
+
+    void hideAll() {
+        if (mHidden) {
+            return;
+        }
+        for (ChildView v : mChildren) {
+            v.mView.setVisibility(View.GONE);
+        }
+        mHidden = true;
+    }
+
+    void showAll() {
+        if (!mHidden) {
+            return;
+        }
+        for (ChildView v : mChildren) {
+            v.mView.setVisibility(View.VISIBLE);
+        }
+        mHidden = false;
+    }
+}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 57b9ac3..61c0cb9 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -308,6 +308,9 @@
     // more key events.
     private int mTextGeneration;
 
+    // Used by WebViewCore to create child views.
+    /* package */ final ViewManager mViewManager;
+
     // The list of loaded plugins.
     private static PluginList sPluginList;
 
@@ -710,6 +713,8 @@
         mDatabase = WebViewDatabase.getInstance(context);
         mScroller = new Scroller(context);
 
+        mViewManager = new ViewManager(this);
+
         mZoomButtonsController = new ZoomButtonsController(this);
         mZoomButtonsController.setOnZoomListener(mZoomListener);
         // ZoomButtonsController positions the buttons at the bottom, but in
@@ -1688,7 +1693,7 @@
         return Math.round(x * mInvActualScale);
     }
 
-    private int contentToView(int x) {
+    /*package*/ int contentToView(int x) {
         return Math.round(x * mActualScale);
     }
 
@@ -1779,6 +1784,9 @@
                 mActualScale = scale;
                 mInvActualScale = 1 / scale;
 
+                // Scale all the child views
+                mViewManager.scaleAll();
+
                 // as we don't have animation for scaling, don't do animation
                 // for scrolling, as it causes weird intermediate state
                 //        pinScrollTo(Math.round(sx), Math.round(sy));
@@ -2716,6 +2724,8 @@
                         - (width >> 1), (int) (scrollFrame.centerY()
                         * mActualScale) - (height >> 1));
                 mTouchMode = TOUCH_DONE_MODE;
+                // Show all the child views once we are done.
+                mViewManager.showAll();
             } else {
                 mTouchMode = SCROLL_ZOOM_OUT;
             }
@@ -2879,6 +2889,8 @@
             mTouchMode = TOUCH_DONE_MODE;
             return;
         }
+        // Hide the child views while in this mode.
+        mViewManager.hideAll();
         startZoomScrollOut();
         mTouchMode = SCROLL_ZOOM_ANIMATION_OUT;
         invalidate();
@@ -3625,6 +3637,7 @@
     @Override
     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
         super.onScrollChanged(l, t, oldl, oldt);
+
         sendOurVisibleRect();
     }