Bug 1285870 - (Part 1) Implement PresentationView as the custom presentation. r?snorp draft
authorKuoE0 <kuoe0.tw@gmail.com>
Fri, 09 Sep 2016 17:02:10 +0800
changeset 420085 da0f8ded9708766cf1235fcf95cbac54a560aea9
parent 420084 48a477d3305e1f3e18dc96cb4fef52103a3ba888
child 420086 98963470d7b9330b3cecb3389787e04ffe76c087
push id31085
push userbmo:kuoe0@mozilla.com
push dateMon, 03 Oct 2016 08:27:53 +0000
reviewerssnorp
bugs1285870
milestone52.0a1
Bug 1285870 - (Part 1) Implement PresentationView as the custom presentation. r?snorp MozReview-Commit-ID: 6G6i3MqGutW
mobile/android/base/java/org/mozilla/gecko/PresentationView.java
mobile/android/base/moz.build
mobile/android/chrome/content/PresentationView.js
mobile/android/chrome/content/PresentationView.xul
mobile/android/chrome/jar.mn
mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoView.java
widget/android/GeneratedJNIWrappers.h
widget/android/nsWindow.cpp
widget/android/nsWindow.h
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/java/org/mozilla/gecko/PresentationView.java
@@ -0,0 +1,56 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * vim: ts=4 sw=4 expandtab:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko;
+
+import org.mozilla.gecko.annotation.WrapForJNI;
+import org.mozilla.gecko.GeckoThread;
+import org.mozilla.gecko.GeckoView;
+import org.mozilla.gecko.ScreenManagerHelper;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+
+public class PresentationView extends GeckoView {
+    private static final String LOGTAG = "PresentationView";
+    private static final String presentationViewURI = "chrome://browser/content/PresentationView.xul";
+
+    private String mDeviceId;
+
+    public String getDeviceId() {
+        return mDeviceId;
+    }
+
+    public void setDeviceId(String aDeviceId) {
+        mDeviceId = aDeviceId;
+    }
+
+    public PresentationView(Context context) {
+        super(context);
+    }
+
+    public PresentationView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void openWindow() {
+        final DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
+
+        final String chromeURI = presentationViewURI + "#" + mDeviceId;
+
+        if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
+            Window.open(window, this, getCompositor(),
+                        chromeURI, metrics.widthPixels, metrics.heightPixels, screenId);
+        } else {
+            GeckoThread.queueNativeCallUntil(GeckoThread.State.PROFILE_READY, Window.class,
+                    "open", window, GeckoView.class, this, Object.class, getCompositor(),
+                    String.class, chromeURI, metrics.widthPixels, metrics.heightPixels,
+                    screenId);
+        }
+    }
+}
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -609,16 +609,17 @@ gbjar.sources += ['java/org/mozilla/geck
     'preferences/MultiPrefMultiChoicePreference.java',
     'preferences/PanelsPreference.java',
     'preferences/PanelsPreferenceCategory.java',
     'preferences/PrivateDataPreference.java',
     'preferences/SearchEnginePreference.java',
     'preferences/SearchPreferenceCategory.java',
     'preferences/SetHomepagePreference.java',
     'preferences/SyncPreference.java',
+    'PresentationView.java',
     'PrintHelper.java',
     'PrivateTab.java',
     'promotion/AddToHomeScreenPromotion.java',
     'promotion/HomeScreenPrompt.java',
     'promotion/ReaderViewBookmarkPromotion.java',
     'promotion/SimpleHelperUI.java',
     'prompts/ColorPickerInput.java',
     'prompts/IconGridInput.java',
new file mode 100644
--- /dev/null
+++ b/mobile/android/chrome/content/PresentationView.js
@@ -0,0 +1,23 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
+
+// globals Services
+Cu.import("resource://gre/modules/Services.jsm");
+
+let DEBUG = false;
+function log(str) {
+  dump("-*- PresentationView.js -*-: " + str + "\n");
+}
+
+let PresentationView = {
+  _id: null,
+
+  startup: function startup() {
+    // use hash as the ID of this top level window
+    this._id = window.location.hash.substr(1);
+  },
+};
new file mode 100644
--- /dev/null
+++ b/mobile/android/chrome/content/PresentationView.xul
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<window id="presentation-window"
+        onload="PresentationView.startup();"
+        windowtype="navigator:browser"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+  <browser id="content" type="content-targetable" src="about:blank" flex="1"/>
+
+  <script type="application/javascript" src="chrome://browser/content/PresentationView.js"/>
+</window>
--- a/mobile/android/chrome/jar.mn
+++ b/mobile/android/chrome/jar.mn
@@ -24,16 +24,18 @@ chrome.jar:
   content/aboutRights.xhtml            (content/aboutRights.xhtml)
   content/blockedSite.xhtml            (content/blockedSite.xhtml)
   content/languages.properties         (content/languages.properties)
   content/browser.xul                  (content/browser.xul)
   content/browser.css                  (content/browser.css)
   content/browser.js                   (content/browser.js)
   content/geckoview.xul                (content/geckoview.xul)
   content/geckoview.js                 (content/geckoview.js)
+  content/PresentationView.xul         (content/PresentationView.xul)
+  content/PresentationView.js          (content/PresentationView.js)
   content/bindings/checkbox.xml        (content/bindings/checkbox.xml)
   content/bindings/settings.xml        (content/bindings/settings.xml)
   content/netError.xhtml               (content/netError.xhtml)
   content/SelectHelper.js              (content/SelectHelper.js)
   content/SelectionHandler.js          (content/SelectionHandler.js)
   content/ActionBarHandler.js          (content/ActionBarHandler.js)
   content/EmbedRT.js                   (content/EmbedRT.js)
   content/InputWidgetHelper.js         (content/InputWidgetHelper.js)
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoView.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoView.java
@@ -1,9 +1,10 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * vim: ts=4 sw=4 expandtab:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko;
 
 import java.util.Set;
 
@@ -42,17 +43,22 @@ public class GeckoView extends LayerView
     private static final String DEFAULT_SHARED_PREFERENCES_FILE = "GeckoView";
     private static final String LOGTAG = "GeckoView";
 
     private ChromeDelegate mChromeDelegate;
     private ContentDelegate mContentDelegate;
 
     private InputConnectionListener mInputConnectionListener;
 
-    private boolean onAttachedToWindowCalled;
+    protected boolean onAttachedToWindowCalled;
+    protected int screenId = 0;
+
+    public void setScreenId(int screenId) {
+        this.screenId = screenId;
+    }
 
     @Override
     public void handleMessage(final String event, final JSONObject message) {
         ThreadUtils.postToUiThread(new Runnable() {
             @Override
             public void run() {
                 try {
                     if (event.equals("Gecko:Ready")) {
@@ -104,22 +110,22 @@ public class GeckoView extends LayerView
                 });
             }
         } catch (Exception e) {
             Log.w(LOGTAG, "handleMessage threw for " + event, e);
         }
     }
 
     @WrapForJNI(dispatchTo = "proxy")
-    private static final class Window extends JNIObject {
+    protected static final class Window extends JNIObject {
         @WrapForJNI(skip = true)
         /* package */ Window() {}
 
         static native void open(Window instance, GeckoView view, Object compositor,
-                                String chromeURI, int width, int height);
+                                String chromeURI, int width, int height, int screenId);
 
         @Override protected native void disposeNative();
         native void close();
         native void reattach(GeckoView view, Object compositor);
         native void loadUri(String uri, int flags);
     }
 
     // Object to hold onto our nsWindow connection when GeckoView gets destroyed.
@@ -161,17 +167,17 @@ public class GeckoView extends LayerView
 
                 @Override
                 public StateBinder[] newArray(int size) {
                     return new StateBinder[size];
                 }
             };
     }
 
-    private Window window;
+    protected Window window;
     private boolean stateSaved;
 
     public GeckoView(Context context) {
         super(context);
         init(context);
     }
 
     public GeckoView(Context context, AttributeSet attrs) {
@@ -219,32 +225,33 @@ public class GeckoView extends LayerView
             reattachWindow();
         }
 
         // We have to always call super.onRestoreInstanceState because View keeps
         // track of these calls and throws an exception when we don't call it.
         super.onRestoreInstanceState(stateBinder.superState);
     }
 
-    private void openWindow() {
+    protected void openWindow() {
         final DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
 
         final String chromeURI = getGeckoInterface().getDefaultChromeURI();
 
         if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
             Window.open(window, this, getCompositor(),
-                        chromeURI, metrics.widthPixels, metrics.heightPixels);
+                        chromeURI, metrics.widthPixels, metrics.heightPixels, screenId);
         } else {
             GeckoThread.queueNativeCallUntil(GeckoThread.State.PROFILE_READY, Window.class,
                     "open", window, GeckoView.class, this, Object.class, getCompositor(),
-                    String.class, chromeURI, metrics.widthPixels, metrics.heightPixels);
+                    String.class, chromeURI, metrics.widthPixels, metrics.heightPixels,
+                    screenId);
         }
     }
 
-    private void reattachWindow() {
+    protected void reattachWindow() {
         if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
             window.reattach(this, getCompositor());
         } else {
             GeckoThread.queueNativeCallUntil(GeckoThread.State.PROFILE_READY,
                     window, "reattach", GeckoView.class, this, Object.class, getCompositor());
         }
     }
 
--- a/widget/android/GeneratedJNIWrappers.h
+++ b/widget/android/GeneratedJNIWrappers.h
@@ -3270,20 +3270,21 @@ public:
         typedef void ReturnType;
         typedef void SetterType;
         typedef mozilla::jni::Args<
                 Window::Param,
                 GeckoView::Param,
                 mozilla::jni::Object::Param,
                 mozilla::jni::String::Param,
                 int32_t,
+                int32_t,
                 int32_t> Args;
         static constexpr char name[] = "open";
         static constexpr char signature[] =
-                "(Lorg/mozilla/gecko/GeckoView$Window;Lorg/mozilla/gecko/GeckoView;Ljava/lang/Object;Ljava/lang/String;II)V";
+                "(Lorg/mozilla/gecko/GeckoView$Window;Lorg/mozilla/gecko/GeckoView;Ljava/lang/Object;Ljava/lang/String;III)V";
         static const bool isStatic = true;
         static const mozilla::jni::ExceptionMode exceptionMode =
                 mozilla::jni::ExceptionMode::ABORT;
         static const mozilla::jni::CallingThread callingThread =
                 mozilla::jni::CallingThread::ANY;
         static const mozilla::jni::DispatchTarget dispatchTarget =
                 mozilla::jni::DispatchTarget::PROXY;
     };
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -1,9 +1,10 @@
 /* -*- Mode: c++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
+ * vim: set sw=4 ts=4 expandtab:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <android/log.h>
 #include <android/native_window.h>
 #include <android/native_window_jni.h>
 #include <math.h>
@@ -341,17 +342,18 @@ private:
     nsCOMPtr<nsPIDOMWindowOuter> mDOMWindow;
 
 public:
     // Create and attach a window.
     static void Open(const jni::Class::LocalRef& aCls,
                      GeckoView::Window::Param aWindow,
                      GeckoView::Param aView, jni::Object::Param aCompositor,
                      jni::String::Param aChromeURI,
-                     int32_t aWidth, int32_t aHeight);
+                     int32_t aWidth, int32_t aHeight,
+                     int32_t screenId);
 
     // Close and destroy the nsWindow.
     void Close();
 
     // Reattach this nsWindow to a new GeckoView.
     void Reattach(const GeckoView::Window::LocalRef& inst,
                   GeckoView::Param aView, jni::Object::Param aCompositor);
 
@@ -1318,17 +1320,18 @@ nsWindow::GeckoViewSupport::~GeckoViewSu
 }
 
 /* static */ void
 nsWindow::GeckoViewSupport::Open(const jni::Class::LocalRef& aCls,
                                  GeckoView::Window::Param aWindow,
                                  GeckoView::Param aView,
                                  jni::Object::Param aCompositor,
                                  jni::String::Param aChromeURI,
-                                 int32_t aWidth, int32_t aHeight)
+                                 int32_t aWidth, int32_t aHeight,
+                                 int32_t aScreenId)
 {
     MOZ_ASSERT(NS_IsMainThread());
 
     PROFILER_LABEL("nsWindow", "GeckoViewSupport::Open",
                    js::ProfileEntry::Category::OTHER);
 
     nsCOMPtr<nsIWindowWatcher> ww = do_GetService(NS_WINDOWWATCHER_CONTRACTID);
     MOZ_RELEASE_ASSERT(ww);
@@ -1365,16 +1368,17 @@ nsWindow::GeckoViewSupport::Open(const j
     MOZ_RELEASE_ASSERT(domWindow);
 
     nsCOMPtr<nsPIDOMWindowOuter> pdomWindow =
             nsPIDOMWindowOuter::From(domWindow);
     nsCOMPtr<nsIWidget> widget = WidgetUtils::DOMWindowToWidget(pdomWindow);
     MOZ_ASSERT(widget);
 
     const auto window = static_cast<nsWindow*>(widget.get());
+    window->SetScreenId(aScreenId);
 
     // Attach a new GeckoView support object to the new window.
     window->mGeckoViewSupport  = mozilla::MakeUnique<GeckoViewSupport>(
             window, GeckoView::Window::LocalRef(aCls.Env(), aWindow), aView);
 
     window->mGeckoViewSupport->mDOMWindow = pdomWindow;
 
     // Attach the Compositor to the new window.
@@ -1667,29 +1671,25 @@ nsWindow::GetDPI()
     if (AndroidBridge::Bridge())
         return AndroidBridge::Bridge()->GetDPI();
     return 160.0f;
 }
 
 double
 nsWindow::GetDefaultScaleInternal()
 {
-    static double density = 0.0;
-
-    if (density != 0.0) {
-        return density;
-    }
-
-    density = GeckoAppShell::GetDensity();
-
-    if (!density) {
-        density = 1.0;
-    }
-
-    return density;
+    nsCOMPtr<nsIScreenManager> screenMgr =
+        do_GetService("@mozilla.org/gfx/screenmanager;1");
+    MOZ_ASSERT(screenMgr, "Failed to get nsIScreenManager");
+
+    nsCOMPtr<nsIScreen> screen;
+    screenMgr->ScreenForId(mScreenId, getter_AddRefs(screen));
+    MOZ_ASSERT(screen);
+    RefPtr<nsScreenAndroid> screenAndroid = (nsScreenAndroid*) screen.get();
+    return screenAndroid->GetDensity();
 }
 
 NS_IMETHODIMP
 nsWindow::Show(bool aState)
 {
     ALOG("nsWindow[%p]::Show %d", (void*)this, aState);
 
     if (mWindowType == eWindowType_invisible) {
--- a/widget/android/nsWindow.h
+++ b/widget/android/nsWindow.h
@@ -1,9 +1,10 @@
 /* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * vim: set sw=4 ts=4 expandtab:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef NSWINDOW_H_
 #define NSWINDOW_H_
 
 #include "nsBaseWidget.h"