Bug 1469875 - Make nsPluginInstanceOwner::RequestCommitOrCancel() call IMEStateManager::NotifyIME() rather than calling nsIWidget::NotifyIME() r?m_kato draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 29 Jun 2018 17:32:09 +0900
changeset 813016 91b95b9abc4a800e172e2426a9a3e0cc196a3ca6
parent 813015 c5c1fa381d47591eb8226d1f3cd27a07e25b6d7d
push id114734
push usermasayuki@d-toybox.com
push dateMon, 02 Jul 2018 06:01:37 +0000
reviewersm_kato
bugs1469875
milestone63.0a1
Bug 1469875 - Make nsPluginInstanceOwner::RequestCommitOrCancel() call IMEStateManager::NotifyIME() rather than calling nsIWidget::NotifyIME() r?m_kato Any content code except TextComposition shouldn't call nsIWidget::NotifyIM() since IMEStateManager and TextComposition manage state of the composition. Therefore, we need to make nsPluginInstanceOwner::RequestCommitOrCancel() call IMEStateManager::NotifyIME() instead. Additionally, this method should ignore the request if composition has already been gone. This patch makes check whether there is a TextComposition instance for the widget and the composition is handled in the plugin owner element. MozReview-Commit-ID: 5cx5X2hGfek
dom/plugins/base/nsPluginInstanceOwner.cpp
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -887,21 +887,47 @@ nsPluginInstanceOwner::RequestCommitOrCa
   nsCOMPtr<nsIWidget> widget = GetContainingWidgetIfOffset();
   if (!widget) {
     widget = GetRootWidgetForPluginFrame(mPluginFrame);
     if (NS_WARN_IF(!widget)) {
       return false;
     }
   }
 
-  if (aCommitted) {
-    widget->NotifyIME(widget::REQUEST_TO_COMMIT_COMPOSITION);
-  } else {
-    widget->NotifyIME(widget::REQUEST_TO_CANCEL_COMPOSITION);
+  // Retrieve TextComposition for the widget with IMEStateManager instead of
+  // using GetTextComposition() because we cannot know whether the method
+  // failed due to no widget or no composition.
+  RefPtr<TextComposition> composition =
+    IMEStateManager::GetTextCompositionFor(widget);
+  if (!composition) {
+    // If there is composition, we should just ignore this request since
+    // the composition may have been committed after the plugin process
+    // sent this request.
+    return true;
   }
+
+  nsCOMPtr<nsIContent> content = do_QueryReferent(mContent);
+  if (content != composition->GetEventTargetNode()) {
+    // If the composition is handled in different node, that means that
+    // the composition for the plugin has gone and new composition has
+    // already started.  So, request from the plugin should be ignored
+    // since user inputs different text now.
+    return true;
+  }
+
+  // If active composition is being handled in the plugin, let's request to
+  // commit/cancel the composition via both IMEStateManager and TextComposition
+  // for avoid breaking the status management of composition.  I.e., don't
+  // call nsIWidget::NotifyIME() directly from here.
+  IMEStateManager::NotifyIME(aCommitted ?
+                                widget::REQUEST_TO_COMMIT_COMPOSITION :
+                                widget::REQUEST_TO_CANCEL_COMPOSITION,
+                             widget, composition->GetTabParent());
+  // FYI: This instance may have been destroyed.  Be careful if you need to
+  //      access members of this class.
   return true;
 }
 
 bool
 nsPluginInstanceOwner::EnableIME(bool aEnable)
 {
   if (NS_WARN_IF(!mPluginFrame)) {
     return false;