Bug 1466910 - 8. Use "content-document-global-created" to attach GeckoEditableSupport; r?esawin draft
authorJim Chen <nchen@mozilla.com>
Tue, 19 Jun 2018 16:31:35 -0400
changeset 808554 a4d7b253f78415c40ce09b6ef74ef29d22fb5d65
parent 808553 92fcee67cc58ea48f3fae9d309d3b36dbcc7ef46
push id113421
push userbmo:nchen@mozilla.com
push dateTue, 19 Jun 2018 22:59:14 +0000
reviewersesawin
bugs1466910
milestone62.0a1
Bug 1466910 - 8. Use "content-document-global-created" to attach GeckoEditableSupport; r?esawin Right now we use the "tab-child-created" notification to attach GeckoEditableSupport to a PuppetWidget in the child process. However, "tab-child-created" is not fired for all instances of PuppetWidget creation, and attaching GeckoEditableSupport at this stage can also cause race conditions. This patch makes us listen to "content-document-global-created" instead, but attach GeckoEditableSupport to the PuppetWidget the same way. MozReview-Commit-ID: 8IAtzuvlK4K
widget/android/nsAppShell.cpp
--- a/widget/android/nsAppShell.cpp
+++ b/widget/android/nsAppShell.cpp
@@ -529,23 +529,24 @@ nsresult
 nsAppShell::Init()
 {
     nsresult rv = nsBaseAppShell::Init();
     nsCOMPtr<nsIObserverService> obsServ =
         mozilla::services::GetObserverService();
     if (obsServ) {
         obsServ->AddObserver(this, "browser-delayed-startup-finished", false);
         obsServ->AddObserver(this, "profile-after-change", false);
-        obsServ->AddObserver(this, "tab-child-created", false);
         obsServ->AddObserver(this, "quit-application", false);
         obsServ->AddObserver(this, "quit-application-granted", false);
         obsServ->AddObserver(this, "xpcom-shutdown", false);
 
         if (XRE_IsParentProcess()) {
             obsServ->AddObserver(this, "chrome-document-loaded", false);
+        } else {
+            obsServ->AddObserver(this, "content-document-global-created", false);
         }
     }
 
     if (sPowerManagerService)
         sPowerManagerService->AddWakeLockListener(sWakeLockListener);
 
     Preferences::AddStrongObservers(this, kObservedPrefs);
     mAllowCoalescingTouches = Preferences::GetBool(PREFNAME_COALESCE_TOUCHES, true);
@@ -655,40 +656,53 @@ nsAppShell::Observe(nsISupports* aSubjec
         }
         removeObserver = true;
 
     } else if (!strcmp(aTopic, "nsPref:changed")) {
         if (jni::IsAvailable()) {
             mozilla::PrefsHelper::OnPrefChange(aData);
         }
 
-    } else if (!strcmp(aTopic, "tab-child-created")) {
+    } else if (!strcmp(aTopic, "content-document-global-created")) {
         // Associate the PuppetWidget of the newly-created TabChild with a
         // GeckoEditableChild instance.
         MOZ_ASSERT(!XRE_IsParentProcess());
 
+        nsCOMPtr<mozIDOMWindowProxy> domWindow = do_QueryInterface(aSubject);
+        MOZ_ASSERT(domWindow);
+        nsCOMPtr<nsIWidget> domWidget = widget::WidgetUtils::DOMWindowToWidget(
+                nsPIDOMWindowOuter::From(domWindow));
+        NS_ENSURE_TRUE(domWidget, NS_OK);
+
         dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
-        nsCOMPtr<nsITabChild> ptabChild = do_QueryInterface(aSubject);
-        NS_ENSURE_TRUE(contentChild && ptabChild, NS_OK);
+        dom::TabChild* tabChild = domWidget->GetOwningTabChild();
+        RefPtr<widget::PuppetWidget> widget(tabChild->WebWidget());
+        NS_ENSURE_TRUE(contentChild && tabChild && widget, NS_OK);
+
+        widget::TextEventDispatcherListener* listener =
+                widget->GetNativeTextEventDispatcherListener();
+        if (listener && listener !=
+                static_cast<widget::TextEventDispatcherListener*>(widget)) {
+            // We already set a listener before.
+            return NS_OK;
+        }
 
         // Get the content/tab ID in order to get the correct
         // IGeckoEditableParent object, which GeckoEditableChild uses to
         // communicate with the parent process.
-        const auto tabChild = static_cast<dom::TabChild*>(ptabChild.get());
         const uint64_t contentId = contentChild->GetID();
         const uint64_t tabId = tabChild->GetTabId();
         NS_ENSURE_TRUE(contentId && tabId, NS_OK);
 
         auto editableParent = java::GeckoServiceChildProcess::GetEditableParent(
                 contentId, tabId);
         NS_ENSURE_TRUE(editableParent, NS_OK);
 
-        RefPtr<widget::PuppetWidget> widget(tabChild->WebWidget());
         auto editableChild = java::GeckoEditableChild::New(editableParent);
-        NS_ENSURE_TRUE(widget && editableChild, NS_OK);
+        NS_ENSURE_TRUE(editableChild, NS_OK);
 
         RefPtr<widget::GeckoEditableSupport> editableSupport =
                 new widget::GeckoEditableSupport(editableChild);
 
         // Tell PuppetWidget to use our listener for IME operations.
         widget->SetNativeTextEventDispatcherListener(editableSupport);
     }