Bug 1372560 TSFTextStore should cache compartment for keyboard open/close r?m_kato draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 14 Jun 2017 15:37:41 +0900
changeset 593837 6c4d1946b768c4d384fd936bc46638cb29e9c4a8
parent 593816 8c4a46cf4a708253275645787a66f90575690297
child 633231 5ed7c525ca1a0c72422e6ae85c41233606a8db5f
push id63829
push usermasayuki@d-toybox.com
push dateWed, 14 Jun 2017 06:38:54 +0000
reviewersm_kato
bugs1372560
milestone56.0a1
Bug 1372560 TSFTextStore should cache compartment for keyboard open/close r?m_kato TSFTextStore::GetIMEOpenState() may be called a lot. Therefore, TSFTextStore should cache the compartment until shutting down. MozReview-Commit-ID: 2jz8zQMBHRS
widget/windows/TSFTextStore.cpp
widget/windows/TSFTextStore.h
--- a/widget/windows/TSFTextStore.cpp
+++ b/widget/windows/TSFTextStore.cpp
@@ -1629,16 +1629,17 @@ public:
 /* TSFTextStore                                                   */
 /******************************************************************/
 
 StaticRefPtr<ITfThreadMgr> TSFTextStore::sThreadMgr;
 StaticRefPtr<ITfMessagePump> TSFTextStore::sMessagePump;
 StaticRefPtr<ITfKeystrokeMgr> TSFTextStore::sKeystrokeMgr;
 StaticRefPtr<ITfDisplayAttributeMgr> TSFTextStore::sDisplayAttrMgr;
 StaticRefPtr<ITfCategoryMgr> TSFTextStore::sCategoryMgr;
+StaticRefPtr<ITfCompartment> TSFTextStore::sCompartmentForOpenClose;
 StaticRefPtr<ITfDocumentMgr> TSFTextStore::sDisabledDocumentMgr;
 StaticRefPtr<ITfContext> TSFTextStore::sDisabledContext;
 StaticRefPtr<ITfInputProcessorProfiles> TSFTextStore::sInputProcessorProfiles;
 StaticRefPtr<TSFTextStore> TSFTextStore::sEnabledTextStore;
 DWORD TSFTextStore::sClientId  = 0;
 
 #define TEXTSTORE_DEFAULT_VIEW (1)
 
@@ -5987,53 +5988,79 @@ GetCompartment(IUnknown* pUnk,
 // static
 void
 TSFTextStore::SetIMEOpenState(bool aState)
 {
   MOZ_LOG(sTextStoreLog, LogLevel::Debug,
     ("TSFTextStore::SetIMEOpenState(aState=%s)",
      GetBoolName(aState)));
 
-  RefPtr<ITfCompartment> comp;
-  if (!GetCompartment(sThreadMgr,
-                      GUID_COMPARTMENT_KEYBOARD_OPENCLOSE,
-                      getter_AddRefs(comp))) {
+  if (!sThreadMgr) {
+    return;
+  }
+
+  RefPtr<ITfCompartment> comp = GetCompartmentForOpenClose();
+  if (NS_WARN_IF(!comp)) {
     MOZ_LOG(sTextStoreLog, LogLevel::Debug,
       ("  TSFTextStore::SetIMEOpenState() FAILED due to"
        "no compartment available"));
     return;
   }
 
   VARIANT variant;
   variant.vt = VT_I4;
   variant.lVal = aState;
+  HRESULT hr = comp->SetValue(sClientId, &variant);
+  if (NS_WARN_IF(FAILED(hr))) {
+    MOZ_LOG(sTextStoreLog, LogLevel::Error,
+      ("  TSFTextStore::SetIMEOpenState() FAILED due to "
+       "ITfCompartment::SetValue() failure, hr=0x%08X", hr));
+    return;
+  }
   MOZ_LOG(sTextStoreLog, LogLevel::Debug,
     ("  TSFTextStore::SetIMEOpenState(), setting "
      "0x%04X to GUID_COMPARTMENT_KEYBOARD_OPENCLOSE...",
      variant.lVal));
-  comp->SetValue(sClientId, &variant);
 }
 
 // static
 bool
 TSFTextStore::GetIMEOpenState()
 {
-  RefPtr<ITfCompartment> comp;
-  if (!GetCompartment(sThreadMgr,
-                      GUID_COMPARTMENT_KEYBOARD_OPENCLOSE,
-                      getter_AddRefs(comp)))
+  if (!sThreadMgr) {
     return false;
+  }
+
+  RefPtr<ITfCompartment> comp = GetCompartmentForOpenClose();
+  if (NS_WARN_IF(!comp)) {
+    return false;
+  }
 
   VARIANT variant;
   ::VariantInit(&variant);
-  if (SUCCEEDED(comp->GetValue(&variant)) && variant.vt == VT_I4)
-    return variant.lVal != 0;
-
-  ::VariantClear(&variant); // clear up in case variant.vt != VT_I4
-  return false;
+  HRESULT hr = comp->GetValue(&variant);
+  if (NS_WARN_IF(FAILED(hr))) {
+    MOZ_LOG(sTextStoreLog, LogLevel::Error,
+      ("TSFTextStore::GetIMEOpenState() FAILED due to "
+       "ITfCompartment::GetValue() failure, hr=0x%08X", hr));
+    return false;
+  }
+  // Until IME is open in this process, the result may be empty.
+  if (variant.vt == VT_EMPTY) {
+    return false;
+  }
+  if (NS_WARN_IF(variant.vt != VT_I4)) {
+    MOZ_LOG(sTextStoreLog, LogLevel::Error,
+      ("TSFTextStore::GetIMEOpenState() FAILED due to "
+       "invalid result of ITfCompartment::GetValue()"));
+    ::VariantClear(&variant);
+    return false;
+  }
+
+  return variant.lVal != 0;
 }
 
 // static
 void
 TSFTextStore::SetInputContext(nsWindowBase* aWidget,
                              const InputContext& aContext,
                              const InputContextAction& aAction)
 {
@@ -6278,16 +6305,53 @@ TSFTextStore::GetCategoryMgr()
        "a category manager instance, hr=0x%08X", hr));
     return nullptr;
   }
   sCategoryMgr = categoryMgr;
   return categoryMgr.forget();
 }
 
 // static
+already_AddRefed<ITfCompartment>
+TSFTextStore::GetCompartmentForOpenClose()
+{
+  if (sCompartmentForOpenClose) {
+    RefPtr<ITfCompartment> compartment = sCompartmentForOpenClose;
+    return compartment.forget();
+  }
+
+  if (!sThreadMgr) {
+    return nullptr;
+  }
+
+  RefPtr<ITfCompartmentMgr> compartmentMgr;
+  HRESULT hr = sThreadMgr->QueryInterface(IID_ITfCompartmentMgr,
+                                          getter_AddRefs(compartmentMgr));
+  if (NS_WARN_IF(FAILED(hr)) || NS_WARN_IF(!compartmentMgr)) {
+    MOZ_LOG(sTextStoreLog, LogLevel::Error,
+      ("TSFTextStore::GetCompartmentForOpenClose() FAILED due to"
+       "sThreadMgr not having ITfCompartmentMgr, hr=0x%08X", hr));
+    return nullptr;
+  }
+
+  RefPtr<ITfCompartment> compartment;
+  hr = compartmentMgr->GetCompartment(GUID_COMPARTMENT_KEYBOARD_OPENCLOSE,
+                                      getter_AddRefs(compartment));
+  if (NS_WARN_IF(FAILED(hr)) || NS_WARN_IF(!compartment)) {
+    MOZ_LOG(sTextStoreLog, LogLevel::Error,
+      ("TSFTextStore::GetCompartmentForOpenClose() FAILED due to"
+       "ITfCompartmentMgr::GetCompartment() failuere, hr=0x%08X", hr));
+    return nullptr;
+  }
+
+  sCompartmentForOpenClose = compartment;
+  return compartment.forget();
+}
+
+// static
 already_AddRefed<ITfInputProcessorProfiles>
 TSFTextStore::GetInputProcessorProfiles()
 {
   RefPtr<ITfInputProcessorProfiles> inputProcessorProfiles;
   if (sInputProcessorProfiles) {
     inputProcessorProfiles = sInputProcessorProfiles;
     return inputProcessorProfiles.forget();
   }
@@ -6318,16 +6382,17 @@ TSFTextStore::Terminate()
 
   TSFStaticSink::Shutdown();
 
   sDisplayAttrMgr = nullptr;
   sCategoryMgr = nullptr;
   sEnabledTextStore = nullptr;
   sDisabledDocumentMgr = nullptr;
   sDisabledContext = nullptr;
+  sCompartmentForOpenClose = nullptr;
   sInputProcessorProfiles = nullptr;
   sClientId = 0;
   if (sThreadMgr) {
     sThreadMgr->Deactivate();
     sThreadMgr = nullptr;
     sMessagePump = nullptr;
     sKeystrokeMgr = nullptr;
   }
--- a/widget/windows/TSFTextStore.h
+++ b/widget/windows/TSFTextStore.h
@@ -1009,16 +1009,19 @@ private:
   // sKeystrokeMgr is QI'ed from sThreadMgr
   static StaticRefPtr<ITfKeystrokeMgr> sKeystrokeMgr;
   // TSF display attribute manager
   static StaticRefPtr<ITfDisplayAttributeMgr> sDisplayAttrMgr;
   static already_AddRefed<ITfDisplayAttributeMgr> GetDisplayAttributeMgr();
   // TSF category manager
   static StaticRefPtr<ITfCategoryMgr> sCategoryMgr;
   static already_AddRefed<ITfCategoryMgr> GetCategoryMgr();
+  // Compartment for (Get|Set)IMEOpenState()
+  static StaticRefPtr<ITfCompartment> sCompartmentForOpenClose;
+  static already_AddRefed<ITfCompartment> GetCompartmentForOpenClose();
 
   // Current text store which is managing a keyboard enabled editor (i.e.,
   // editable editor).  Currently only ONE TSFTextStore instance is ever used,
   // although Create is called when an editor is focused and Destroy called
   // when the focused editor is blurred.
   static StaticRefPtr<TSFTextStore> sEnabledTextStore;
 
   // For IME (keyboard) disabled state: