Add API to allow plugins to lock their orientation in full-screen mode.

This CL has companion changes in the browser and webkit.

bug: 3398386
Change-Id: I09eee11e3a22ba3ce0af67e2a068dc7331dc49c2
diff --git a/core/java/android/webkit/PluginFullScreenHolder.java b/core/java/android/webkit/PluginFullScreenHolder.java
index ae326d5..42ba7c9 100644
--- a/core/java/android/webkit/PluginFullScreenHolder.java
+++ b/core/java/android/webkit/PluginFullScreenHolder.java
@@ -24,34 +24,44 @@
  */
 package android.webkit;
 
-import android.app.Dialog;
+import android.content.Context;
+import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.SurfaceView;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.FrameLayout;
 
-class PluginFullScreenHolder extends Dialog {
+class PluginFullScreenHolder {
 
     private final WebView mWebView;
     private final int mNpp;
+    private final int mOrientation;
+
+    // The container for the plugin view
+    private static CustomFrameLayout mLayout;
+
     private View mContentView;
 
-    PluginFullScreenHolder(WebView webView, int npp) {
-        super(webView.getContext(), android.R.style.Theme_NoTitleBar_Fullscreen);
+    PluginFullScreenHolder(WebView webView, int orientation, int npp) {
         mWebView = webView;
         mNpp = npp;
+        mOrientation = orientation;
     }
 
-    @Override
     public void setContentView(View contentView) {
-        // as we are sharing the View between full screen and
-        // embedded mode, we have to remove the
-        // AbsoluteLayout.LayoutParams set by embedded mode to
-        // ViewGroup.LayoutParams before adding it to the dialog
-        contentView.setLayoutParams(new ViewGroup.LayoutParams(
-                ViewGroup.LayoutParams.MATCH_PARENT,
-                ViewGroup.LayoutParams.MATCH_PARENT));
+
+        // Create a FrameLayout that will contain the plugin's view
+        mLayout = new CustomFrameLayout(mWebView.getContext());
+        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
+                            ViewGroup.LayoutParams.MATCH_PARENT,
+                            ViewGroup.LayoutParams.MATCH_PARENT,
+                            Gravity.CENTER);
+
+        mLayout.addView(contentView, layoutParams);
+        mLayout.setVisibility(View.VISIBLE);
+
         // fixed size is only used either during pinch zoom or surface is too
         // big. Make sure it is not fixed size before setting it to the full
         // screen content view. The SurfaceView will be set to the correct mode
@@ -62,59 +72,79 @@
                 sView.getHolder().setSizeFromLayout();
             }
         }
-        super.setContentView(contentView);
+
         mContentView = contentView;
     }
 
-    @Override
-    public void onBackPressed() {
-        mWebView.mPrivateHandler.obtainMessage(WebView.HIDE_FULLSCREEN)
-                .sendToTarget();
+    public void show() {
+        // Other plugins may attempt to draw so hide them while we're active.
+        if (mWebView.getViewManager() != null)
+            mWebView.getViewManager().hideAll();
+
+        WebChromeClient client = mWebView.getWebChromeClient();
+        client.onShowCustomView(mLayout, mOrientation, mCallback);
     }
 
-    @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
-        if (event.isSystem()) {
-            return super.onKeyDown(keyCode, event);
+    public void hide() {
+        WebChromeClient client = mWebView.getWebChromeClient();
+        client.onHideCustomView();
+    }
+
+    private class CustomFrameLayout extends FrameLayout {
+
+        CustomFrameLayout(Context context) {
+            super(context);
         }
-        mWebView.onKeyDown(keyCode, event);
-        // always return true as we are the handler
-        return true;
-    }
 
-    @Override
-    public boolean onKeyUp(int keyCode, KeyEvent event) {
-        if (event.isSystem()) {
-            return super.onKeyUp(keyCode, event);
+        @Override
+        public boolean onKeyDown(int keyCode, KeyEvent event) {
+            if (event.isSystem()) {
+                return super.onKeyDown(keyCode, event);
+            }
+            mWebView.onKeyDown(keyCode, event);
+            // always return true as we are the handler
+            return true;
         }
-        mWebView.onKeyUp(keyCode, event);
-        // always return true as we are the handler
-        return true;
-    }
 
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        // always return true as we don't want the event to propagate any further
-        return true;
-    }
-
-    @Override
-    public boolean onTrackballEvent(MotionEvent event) {
-        mWebView.onTrackballEvent(event);
-        // always return true as we are the handler
-        return true;
-    }
-
-    @Override
-    protected void onStop() {
-        super.onStop();
-        // manually remove the contentView's parent since the dialog does not
-        if (mContentView != null && mContentView.getParent() != null) {
-            ViewGroup vg = (ViewGroup) mContentView.getParent();
-            vg.removeView(mContentView);
+        @Override
+        public boolean onKeyUp(int keyCode, KeyEvent event) {
+            if (event.isSystem()) {
+                return super.onKeyUp(keyCode, event);
+            }
+            mWebView.onKeyUp(keyCode, event);
+            // always return true as we are the handler
+            return true;
         }
-        mWebView.getWebViewCore().sendMessage(
-                WebViewCore.EventHub.HIDE_FULLSCREEN, mNpp, 0);
-    }
 
+        @Override
+        public boolean onTouchEvent(MotionEvent event) {
+            // always return true as we don't want the event to propagate any further
+            return true;
+        }
+
+        @Override
+        public boolean onTrackballEvent(MotionEvent event) {
+            mWebView.onTrackballEvent(event);
+            // always return true as we are the handler
+            return true;
+        }
+    }
+    
+    private final WebChromeClient.CustomViewCallback mCallback =
+        new WebChromeClient.CustomViewCallback() {
+            public void onCustomViewHidden() {
+
+                mWebView.mPrivateHandler.obtainMessage(WebView.HIDE_FULLSCREEN)
+                    .sendToTarget();
+
+                mWebView.getWebViewCore().sendMessage(
+                        WebViewCore.EventHub.HIDE_FULLSCREEN, mNpp, 0);
+
+                mLayout.removeView(mContentView);
+                mLayout = null;
+
+                // Re enable plugin views.
+                mWebView.getViewManager().showAll();
+            }
+        };
 }
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index 755366c..ae40ded 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -16,6 +16,7 @@
 
 package android.webkit;
 
+import android.content.pm.ActivityInfo;
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Message;
@@ -77,6 +78,18 @@
 
     /**
      * Notify the host application that the current page would
+     * like to show a custom View in a particular orientation.
+     * @param view is the View object to be shown.
+     * @param requestedOrientation An orientation constant as used in
+     * {@link ActivityInfo#screenOrientation ActivityInfo.screenOrientation}.
+     * @param callback is the callback to be invoked if and when the view
+     * is dismissed.
+     */
+    public void onShowCustomView(View view, int requestedOrientation,
+            CustomViewCallback callback) {};
+    
+    /**
+     * Notify the host application that the current page would
      * like to hide its custom view.
      */
     public void onHideCustomView() {}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 3c2c8f6..739d77e 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -5543,7 +5543,7 @@
 
     private void dismissFullScreenMode() {
         if (inFullScreenMode()) {
-            mFullScreenHolder.dismiss();
+            mFullScreenHolder.hide();
             mFullScreenHolder = null;
         }
     }
@@ -8198,16 +8198,15 @@
 
                 case SHOW_FULLSCREEN: {
                     View view = (View) msg.obj;
-                    int npp = msg.arg1;
+                    int orientation = msg.arg1;
+                    int npp = msg.arg2;
 
                     if (inFullScreenMode()) {
                         Log.w(LOGTAG, "Should not have another full screen.");
                         dismissFullScreenMode();
                     }
-                    mFullScreenHolder = new PluginFullScreenHolder(WebView.this, npp);
+                    mFullScreenHolder = new PluginFullScreenHolder(WebView.this, orientation, npp);
                     mFullScreenHolder.setContentView(view);
-                    mFullScreenHolder.setCancelable(false);
-                    mFullScreenHolder.setCanceledOnTouchOutside(false);
                     mFullScreenHolder.show();
 
                     break;
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 13a9793..16e4571 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -2623,14 +2623,15 @@
 
     // called by JNI. PluginWidget function to launch a full-screen view using a
     // View object provided by the plugin class.
-    private void showFullScreenPlugin(ViewManager.ChildView childView, int npp) {
+    private void showFullScreenPlugin(ViewManager.ChildView childView, int orientation, int npp) {
         if (mWebView == null) {
             return;
         }
 
         Message message = mWebView.mPrivateHandler.obtainMessage(WebView.SHOW_FULLSCREEN);
         message.obj = childView.mView;
-        message.arg1 = npp;
+        message.arg1 = orientation;
+        message.arg2 = npp;
         message.sendToTarget();
     }