Bug 1494713 - Add `nsWindow::From`. r=jchen
authorLina Cambridge <lina@yakshaving.ninja>
Fri, 16 Nov 2018 17:31:58 +0000
changeset 446798 6644b6e14bde969270ccb646bb501a11221e3041
parent 446797 155387956608096a66495a3da674e238efb49912
child 446799 a1fe5c7791a7fec71e6c3a6b7c362e5ec00ba49f
push id35052
push userapavel@mozilla.com
push dateSat, 17 Nov 2018 11:25:40 +0000
treeherdermozilla-central@efc1da42132b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjchen
bugs1494713
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1494713 - Add `nsWindow::From`. r=jchen Differential Revision: https://phabricator.services.mozilla.com/D11289
accessible/android/SessionAccessibility.cpp
widget/android/AndroidBridge.cpp
widget/android/GeckoProcessManager.h
widget/android/nsAppShell.cpp
widget/android/nsWindow.cpp
widget/android/nsWindow.h
--- a/accessible/android/SessionAccessibility.cpp
+++ b/accessible/android/SessionAccessibility.cpp
@@ -140,21 +140,19 @@ SessionAccessibility::GetInstanceFor(Acc
   nsViewManager* vm = shell->GetViewManager();
   if (!vm) {
     return nullptr;
   }
 
   nsCOMPtr<nsIWidget> rootWidget;
   vm->GetRootWidget(getter_AddRefs(rootWidget));
   // `rootWidget` can be one of several types. Here we make sure it is an
-  // android nsWindow that implemented NS_NATIVE_WIDGET to return itself.
-  if (rootWidget &&
-      rootWidget->WindowType() == nsWindowType::eWindowType_toplevel &&
-      rootWidget->GetNativeData(NS_NATIVE_WIDGET) == rootWidget) {
-    return static_cast<nsWindow*>(rootWidget.get())->GetSessionAccessibility();
+  // android nsWindow.
+  if (RefPtr<nsWindow> window = nsWindow::From(rootWidget)) {
+    return window->GetSessionAccessibility();
   }
 
   return nullptr;
 }
 
 void
 SessionAccessibility::SendAccessibilityFocusedEvent(AccessibleWrap* aAccessible)
 {
--- a/widget/android/AndroidBridge.cpp
+++ b/widget/android/AndroidBridge.cpp
@@ -813,43 +813,28 @@ NS_IMETHODIMP nsAndroidBridge::SetBrowse
     return NS_OK;
 }
 
 extern "C"
 __attribute__ ((visibility("default")))
 jobject JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_allocateDirectBuffer(JNIEnv *env, jclass, jlong size);
 
-static RefPtr<nsWindow>
-GetWidget(mozIDOMWindowProxy* aWindow)
-{
-    MOZ_ASSERT(aWindow);
-
-    nsCOMPtr<nsPIDOMWindowOuter> domWindow = nsPIDOMWindowOuter::From(aWindow);
-    nsCOMPtr<nsIWidget> widget =
-            widget::WidgetUtils::DOMWindowToWidget(domWindow);
-    MOZ_ASSERT(widget);
-
-    return RefPtr<nsWindow>(static_cast<nsWindow*>(widget.get()));
-}
-
 void
 AndroidBridge::ContentDocumentChanged(mozIDOMWindowProxy* aWindow)
 {
-    auto widget = GetWidget(aWindow);
-    if (widget) {
+    if (RefPtr<nsWindow> widget = nsWindow::From(nsPIDOMWindowOuter::From(aWindow))) {
         widget->SetContentDocumentDisplayed(false);
     }
 }
 
 bool
 AndroidBridge::IsContentDocumentDisplayed(mozIDOMWindowProxy* aWindow)
 {
-    auto widget = GetWidget(aWindow);
-    if (widget) {
+    if (RefPtr<nsWindow> widget = nsWindow::From(nsPIDOMWindowOuter::From(aWindow))) {
         return widget->IsContentDocumentDisplayed();
     }
     return false;
 }
 
 jni::Object::LocalRef AndroidBridge::ChannelCreate(jni::Object::Param stream) {
     JNIEnv* const env = jni::GetEnvForThread();
     auto rv = jni::Object::LocalRef::Adopt(env, env->CallStaticObjectMethod(
--- a/widget/android/GeckoProcessManager.h
+++ b/widget/android/GeckoProcessManager.h
@@ -42,19 +42,19 @@ class GeckoProcessManager final
     }
 
 public:
     static void
     GetEditableParent(jni::Object::Param aEditableChild,
                       int64_t aContentId, int64_t aTabId)
     {
         nsCOMPtr<nsIWidget> widget = GetWidget(aContentId, aTabId);
-        if (widget && widget->GetNativeData(NS_NATIVE_WIDGET) == widget) {
+        if (RefPtr<nsWindow> window = nsWindow::From(widget)) {
             java::GeckoProcessManager::SetEditableChildParent(
                     aEditableChild,
-                    static_cast<nsWindow*>(widget.get())->GetEditableParent());
+                    window->GetEditableParent());
         }
     }
 };
 
 } // namespace mozilla
 
 #endif // GeckoProcessManager_h
--- a/widget/android/nsAppShell.cpp
+++ b/widget/android/nsAppShell.cpp
@@ -613,36 +613,24 @@ nsAppShell::Observe(nsISupports* aSubjec
         }
         removeObserver = true;
 
     } else if (!strcmp(aTopic, "chrome-document-loaded")) {
         // Set the global ready state and enable the window event dispatcher
         // for this particular GeckoView.
         nsCOMPtr<nsIDocument> doc = do_QueryInterface(aSubject);
         MOZ_ASSERT(doc);
-        nsCOMPtr<nsIWidget> widget =
-            widget::WidgetUtils::DOMWindowToWidget(doc->GetWindow());
-
-        // `widget` may be one of several different types in the parent
-        // process, including the Android nsWindow, PuppetWidget, etc. To
-        // ensure that we only accept the Android nsWindow, we check that the
-        // widget is a top-level window and that its NS_NATIVE_WIDGET value is
-        // non-null, which is not the case for non-native widgets like
-        // PuppetWidget.
-        if (widget &&
-            widget->WindowType() == nsWindowType::eWindowType_toplevel &&
-            widget->GetNativeData(NS_NATIVE_WIDGET) == widget) {
+        if (const RefPtr<nsWindow> window = nsWindow::From(doc->GetWindow())) {
             if (jni::IsAvailable()) {
                 // When our first window has loaded, assume any JS
                 // initialization has run and set Gecko to ready.
                 java::GeckoThread::CheckAndSetState(
                         java::GeckoThread::State::PROFILE_READY(),
                         java::GeckoThread::State::RUNNING());
             }
-            const auto window = static_cast<nsWindow*>(widget.get());
             window->OnGeckoViewReady();
         }
     } else if (!strcmp(aTopic, "quit-application")) {
         if (jni::IsAvailable()) {
             const bool restarting =
                     aData && NS_LITERAL_STRING("restart").Equals(aData);
             java::GeckoThread::SetState(
                     restarting ?
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -1258,20 +1258,18 @@ nsWindow::GeckoViewSupport::Open(const j
     }
     nsCOMPtr<mozIDOMWindowProxy> domWindow;
     ww->OpenWindow(nullptr, url.get(), aId->ToCString().get(), chromeFlags.get(),
                    androidView, getter_AddRefs(domWindow));
     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());
+    const RefPtr<nsWindow> window = nsWindow::From(pdomWindow);
+    MOZ_ASSERT(window);
     window->SetScreenId(aScreenId);
 
     // Attach a new GeckoView support object to the new window.
     GeckoSession::Window::LocalRef sessionWindow(aCls.Env(), aWindow);
     window->mGeckoViewSupport =
             mozilla::MakeUnique<GeckoViewSupport>(window, sessionWindow);
     window->mGeckoViewSupport->mDOMWindow = pdomWindow;
     window->mAndroidView = androidView;
@@ -1399,16 +1397,42 @@ nsWindow::InitNatives()
     nsWindow::GeckoViewSupport::Base::Init();
     nsWindow::LayerViewSupport::Init();
     nsWindow::NPZCSupport::Init();
 
     GeckoEditableSupport::Init();
     a11y::SessionAccessibility::Init();
 }
 
+/* static */ already_AddRefed<nsWindow>
+nsWindow::From(nsPIDOMWindowOuter* aDOMWindow)
+{
+    nsCOMPtr<nsIWidget> widget = WidgetUtils::DOMWindowToWidget(aDOMWindow);
+    return From(widget);
+}
+
+/* static */ already_AddRefed<nsWindow>
+nsWindow::From(nsIWidget* aWidget)
+{
+    // `widget` may be one of several different types in the parent
+    // process, including the Android nsWindow, PuppetWidget, etc. To
+    // ensure that the cast to the Android nsWindow is valid, we check that the
+    // widget is a top-level window and that its NS_NATIVE_WIDGET value is
+    // non-null, which is not the case for non-native widgets like
+    // PuppetWidget.
+    if (aWidget &&
+        aWidget->WindowType() == nsWindowType::eWindowType_toplevel &&
+        aWidget->GetNativeData(NS_NATIVE_WIDGET) == aWidget) {
+
+        RefPtr<nsWindow> window = static_cast<nsWindow*>(aWidget);
+        return window.forget();
+    }
+    return nullptr;
+}
+
 nsWindow*
 nsWindow::TopWindow()
 {
     if (!gTopLevelWindows.IsEmpty())
         return gTopLevelWindows[0];
     return nullptr;
 }
 
--- a/widget/android/nsWindow.h
+++ b/widget/android/nsWindow.h
@@ -202,16 +202,19 @@ private:
     // nullptr for nsWindows that were not opened from GeckoView.
     // Because other objects get destroyed in the mGeckOViewSupport destructor,
     // keep it last in the list, so its destructor is called first.
     mozilla::UniquePtr<GeckoViewSupport> mGeckoViewSupport;
 
     mozilla::Atomic<bool, mozilla::ReleaseAcquire> mContentDocumentDisplayed;
 
 public:
+    static already_AddRefed<nsWindow> From(nsPIDOMWindowOuter* aDOMWindow);
+    static already_AddRefed<nsWindow> From(nsIWidget* aWidget);
+
     static nsWindow* TopWindow();
 
     static mozilla::Modifiers GetModifiers(int32_t aMetaState);
     static mozilla::TimeStamp GetEventTimeStamp(int64_t aEventTime);
 
     void OnSizeChanged(const mozilla::gfx::IntSize& aSize);
 
     void InitEvent(mozilla::WidgetGUIEvent& event,