Bug 1180684 - Part 2. Hook GetKeyState on plugin process. r?aklotz draft
authorMakoto Kato <m_kato@ga2.so-net.ne.jp>
Mon, 22 Aug 2016 16:06:50 +0900
changeset 404828 deb94e05c6aa9f6fc6110919b6227aa2ba2fbf70
parent 404827 16bc22579d530b52d177987ee4a1044bfbf01e15
child 529286 7a130758920facf7a6e68750fce56b232075b600
push id27317
push userm_kato@ga2.so-net.ne.jp
push dateWed, 24 Aug 2016 07:41:37 +0000
reviewersaklotz
bugs1180684
milestone51.0a1
Bug 1180684 - Part 2. Hook GetKeyState on plugin process. r?aklotz MozReview-Commit-ID: 3cCWMYYaTkn
dom/plugins/ipc/PPluginModule.ipdl
dom/plugins/ipc/PluginModuleChild.cpp
dom/plugins/ipc/PluginModuleParent.cpp
dom/plugins/ipc/PluginModuleParent.h
dom/plugins/ipc/PluginQuirks.cpp
dom/plugins/ipc/PluginQuirks.h
--- a/dom/plugins/ipc/PPluginModule.ipdl
+++ b/dom/plugins/ipc/PPluginModule.ipdl
@@ -152,12 +152,14 @@ parent:
 
   async Profile(nsCString aProfile);
 
   // Answers to request about site data
   async ReturnClearSiteData(NPError aRv, uint64_t aCallbackId);
 
   async ReturnSitesWithData(nsCString[] aSites, uint64_t aCallbackId);
 
+  intr GetKeyState(int32_t aVirtKey)
+    returns (int16_t aState);
 };
 
 } // namespace plugins
 } // namespace mozilla
--- a/dom/plugins/ipc/PluginModuleChild.cpp
+++ b/dom/plugins/ipc/PluginModuleChild.cpp
@@ -85,16 +85,19 @@ static CreateFileAPtr sCreateFileAStub =
 
 // Used with fix for flash fullscreen window loosing focus.
 static bool gDelayFlashFocusReplyUntilEval = false;
 // Used to fix GetWindowInfo problems with internal flash settings dialogs
 static WindowsDllInterceptor sUser32Intercept;
 typedef BOOL (WINAPI *GetWindowInfoPtr)(HWND hwnd, PWINDOWINFO pwi);
 static GetWindowInfoPtr sGetWindowInfoPtrStub = nullptr;
 static HWND sBrowserHwnd = nullptr;
+// sandbox process doesn't get current key states.  So we need get it on chrome.
+typedef SHORT (WINAPI *GetKeyStatePtr)(int);
+static GetKeyStatePtr sGetKeyStatePtrStub = nullptr;
 #endif
 
 /* static */
 PluginModuleChild*
 PluginModuleChild::CreateForContentProcess(mozilla::ipc::Transport* aTransport,
                                            base::ProcessId aOtherPid)
 {
     PluginModuleChild* child = new PluginModuleChild(false);
@@ -2061,16 +2064,30 @@ PMCGetWindowInfoHook(HWND hWnd, PWINDOWI
   // it's internal settings window. Post removing sub widgets for tabs, touch
   // this up so they get the rect they expect.
   // XXX potentially tie this to a specific major version?
   BOOL result = sGetWindowInfoPtrStub(hWnd, pwi);
   if (sBrowserHwnd && sBrowserHwnd == hWnd)
       pwi->rcWindow = pwi->rcClient;
   return result;
 }
+
+// static
+SHORT WINAPI
+PMCGetKeyState(int aVirtKey)
+{
+    PluginModuleChild* chromeInstance = PluginModuleChild::GetChrome();
+    if (chromeInstance) {
+        int16_t ret = 0;
+        if (chromeInstance->CallGetKeyState(aVirtKey, &ret)) {
+          return ret;
+        }
+    }
+    return sGetKeyStatePtrStub(aVirtKey);
+}
 #endif
 
 PPluginInstanceChild*
 PluginModuleChild::AllocPPluginInstanceChild(const nsCString& aMimeType,
                                              const uint16_t& aMode,
                                              const InfallibleTArray<nsCString>& aNames,
                                              const InfallibleTArray<nsCString>& aValues)
 {
@@ -2081,22 +2098,28 @@ PluginModuleChild::AllocPPluginInstanceC
     // allocates an instance on its own. Make sure it gets the latest copy
     // of quirks once we have them. Also note, with process-per-tab, we may
     // have multiple PluginModuleChilds in the same plugin process, so only
     // initialize this once in gChromeInstance, which is a singleton.
     GetChrome()->InitQuirksModes(aMimeType);
     mQuirks = GetChrome()->mQuirks;
 
 #ifdef XP_WIN
+    sUser32Intercept.Init("user32.dll");
     if ((mQuirks & QUIRK_FLASH_HOOK_GETWINDOWINFO) &&
         !sGetWindowInfoPtrStub) {
-        sUser32Intercept.Init("user32.dll");
         sUser32Intercept.AddHook("GetWindowInfo", reinterpret_cast<intptr_t>(PMCGetWindowInfoHook),
                                  (void**) &sGetWindowInfoPtrStub);
     }
+
+    if ((mQuirks & QUIRK_FLASH_HOOK_GETKEYSTATE) &&
+        !sGetKeyStatePtrStub) {
+        sUser32Intercept.AddHook("GetKeyState", reinterpret_cast<intptr_t>(PMCGetKeyState),
+                                 (void**) &sGetKeyStatePtrStub);
+    }
 #endif
 
     return new PluginInstanceChild(&mFunctions, aMimeType, aMode, aNames,
                                    aValues);
 }
 
 void
 PluginModuleChild::InitQuirksModes(const nsCString& aMimeType)
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -3360,9 +3360,25 @@ PluginModuleChromeParent::RecvProfile(co
     }
 
     mProfile = aProfile;
     mGatherer->GatheredOOPProfile();
 #endif
     return true;
 }
 
-
+bool
+PluginModuleParent::AnswerGetKeyState(const int32_t& aVirtKey, int16_t* aRet)
+{
+    return false;
+}
+
+bool
+PluginModuleChromeParent::AnswerGetKeyState(const int32_t& aVirtKey,
+                                            int16_t* aRet)
+{
+#if defined(XP_WIN)
+    *aRet = ::GetKeyState(aVirtKey);
+    return true;
+#else
+    return PluginModuleParent::AnswerGetKeyState(aVirtKey, aRet);
+#endif
+}
--- a/dom/plugins/ipc/PluginModuleParent.h
+++ b/dom/plugins/ipc/PluginModuleParent.h
@@ -203,16 +203,18 @@ protected:
     static void TimeoutChanged(const char* aPref, void* aModule);
 
     virtual void UpdatePluginTimeout() {}
 
     virtual bool RecvNotifyContentModuleDestroyed() override { return true; }
 
     virtual bool RecvProfile(const nsCString& aProfile) override { return true; }
 
+    virtual bool AnswerGetKeyState(const int32_t& aVirtKey, int16_t* aRet) override;
+
     virtual bool RecvReturnClearSiteData(const NPError& aRv,
                                          const uint64_t& aCallbackId) override;
 
     virtual bool RecvReturnSitesWithData(nsTArray<nsCString>&& aSites,
                                          const uint64_t& aCallbackId) override;
 
     void SetPluginFuncs(NPPluginFuncs* aFuncs);
 
@@ -493,16 +495,19 @@ class PluginModuleChromeParent
     void GatheredAsyncProfile(nsIProfileSaveEvent* aSaveEvent);
     void StartProfiler(nsIProfilerStartParams* aParams);
     void StopProfiler();
 #endif
 
     virtual bool
     RecvProfile(const nsCString& aProfile) override;
 
+    virtual bool
+    AnswerGetKeyState(const int32_t& aVirtKey, int16_t* aRet) override;
+
 private:
     virtual void
     EnteredCxxStack() override;
 
     void
     ExitedCxxStack() override;
 
     mozilla::ipc::IProtocol* GetInvokingProtocol();
--- a/dom/plugins/ipc/PluginQuirks.cpp
+++ b/dom/plugins/ipc/PluginQuirks.cpp
@@ -30,16 +30,19 @@ int GetQuirksFromMimeTypeAndFilename(con
         quirks |= QUIRK_FLASH_RETURN_EMPTY_DOCUMENT_ORIGIN;
 #ifdef OS_WIN
         quirks |= QUIRK_WINLESS_TRACKPOPUP_HOOK;
         quirks |= QUIRK_FLASH_THROTTLE_WMUSER_EVENTS;
         quirks |= QUIRK_FLASH_HOOK_SETLONGPTR;
         quirks |= QUIRK_FLASH_HOOK_GETWINDOWINFO;
         quirks |= QUIRK_FLASH_FIXUP_MOUSE_CAPTURE;
         quirks |= QUIRK_WINLESS_HOOK_IME;
+#if defined(_M_X64) || defined(__x86_64__)
+        quirks |= QUIRK_FLASH_HOOK_GETKEYSTATE;
+#endif
 #endif
     }
 
 #ifdef OS_WIN
     // QuickTime plugin usually loaded with audio/mpeg mimetype
     NS_NAMED_LITERAL_CSTRING(quicktime, "npqtplugin");
     if (FindInReadable(quicktime, aPluginFilename)) {
         quirks |= QUIRK_QUICKTIME_AVOID_SETWINDOW;
--- a/dom/plugins/ipc/PluginQuirks.h
+++ b/dom/plugins/ipc/PluginQuirks.h
@@ -50,16 +50,18 @@ enum PluginQuirks {
   // Work around a Flash bug where it fails to check the error code of a
   // NPN_GetValue(NPNVdocumentOrigin) call before trying to dereference
   // its char* output.
   QUIRK_FLASH_RETURN_EMPTY_DOCUMENT_ORIGIN        = 1 << 10,
   // Win: Addresses a Unity bug with mouse capture.
   QUIRK_UNITY_FIXUP_MOUSE_CAPTURE                 = 1 << 11,
   // Win: Hook IMM32 API to handle IME event on windowless plugin
   QUIRK_WINLESS_HOOK_IME                          = 1 << 12,
+  // Win: Hook GetKeyState to get keyboard state on sandbox process
+  QUIRK_FLASH_HOOK_GETKEYSTATE                    = 1 << 13,
 };
 
 int GetQuirksFromMimeTypeAndFilename(const nsCString& aMimeType,
                                      const nsCString& aPluginFilename);
 
 } /* namespace plugins */
 } /* namespace mozilla */