Bug 966395 - Use a puppet bidi keyboard in child processes. r=mrbkap/masayuki
☠☠ backed out by 07520461d3aa ☠ ☠
authorAlexandru Tifrea <alex.tifrea93@gmail.com>
Wed, 09 Jul 2014 16:28:51 -0700
changeset 214021 8be952fedc1e1947142affdea26ea0936a0f8aed
parent 214020 417723d8c2940003ece8af5edea723f2e824803d
child 214022 d3e052ab5a279cf4080378bc94a8a23edff7c8dc
push id3857
push userraliiev@mozilla.com
push dateTue, 02 Sep 2014 16:39:23 +0000
treeherdermozilla-beta@5638b907b505 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmrbkap, masayuki
bugs966395
milestone33.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 966395 - Use a puppet bidi keyboard in child processes. r=mrbkap/masayuki
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
widget/cocoa/TextInputHandler.h
widget/cocoa/TextInputHandler.mm
widget/cocoa/moz.build
widget/cocoa/nsWidgetFactory.mm
widget/nsWidgetsCID.h
widget/xpwidgets/PuppetBidiKeyboard.cpp
widget/xpwidgets/PuppetBidiKeyboard.h
widget/xpwidgets/moz.build
widget/xpwidgets/nsContentProcessWidgetFactory.cpp
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -147,30 +147,33 @@
 #include "nsDeviceStorage.h"
 #include "AudioChannelService.h"
 #include "JavaScriptChild.h"
 #include "mozilla/dom/DataStoreService.h"
 #include "mozilla/dom/telephony/PTelephonyChild.h"
 #include "mozilla/dom/time/DateCacheCleaner.h"
 #include "mozilla/net/NeckoMessageUtils.h"
 
+#include "PuppetBidiKeyboard.h"
+
 using namespace base;
 using namespace mozilla;
 using namespace mozilla::docshell;
 using namespace mozilla::dom::bluetooth;
 using namespace mozilla::dom::devicestorage;
 using namespace mozilla::dom::ipc;
 using namespace mozilla::dom::mobilemessage;
 using namespace mozilla::dom::indexedDB;
 using namespace mozilla::dom::telephony;
 using namespace mozilla::hal_sandbox;
 using namespace mozilla::ipc;
 using namespace mozilla::layers;
 using namespace mozilla::net;
 using namespace mozilla::jsipc;
+using namespace mozilla::widget;
 #if defined(MOZ_WIDGET_GONK)
 using namespace mozilla::system;
 #endif
 
 #ifdef MOZ_NUWA_PROCESS
 static bool sNuwaForking = false;
 
 // The size of the reserved stack (in unsigned ints). It's used to reserve space
@@ -669,18 +672,19 @@ ContentChild::InitXPCOM()
         NS_WARNING("Couldn't acquire console service");
         return;
     }
 
     mConsoleListener = new ConsoleListener(this);
     if (NS_FAILED(svc->RegisterListener(mConsoleListener)))
         NS_WARNING("Couldn't register console listener for child process");
 
-    bool isOffline;
-    SendGetXPCOMProcessAttributes(&isOffline);
+    bool isOffline, isLangRTL;
+    SendGetXPCOMProcessAttributes(&isOffline, &isLangRTL);
+    RecvBidiKeyboardNotify(isLangRTL);
     RecvSetOffline(isOffline);
 
     DebugOnly<FileUpdateDispatcher*> observer = FileUpdateDispatcher::GetSingleton();
     NS_ASSERTION(observer, "FileUpdateDispatcher is null");
 
     // This object is held alive by the observer service.
     nsRefPtr<SystemMessageHandledObserver> sysMsgObserver =
         new SystemMessageHandledObserver();
@@ -932,16 +936,28 @@ ContentChild::RecvSpeakerManagerNotify()
     if (service) {
         service->Notify();
     }
     return true;
 #endif
     return false;
 }
 
+bool
+ContentChild::RecvBidiKeyboardNotify(const bool& aIsLangRTL)
+{
+    // bidi is always of type PuppetBidiKeyboard* (because in the child, the only
+    // possible implementation of nsIBidiKeyboard is PuppetBidiKeyboard).
+    PuppetBidiKeyboard* bidi = static_cast<PuppetBidiKeyboard*>(nsContentUtils::GetBidiKeyboard());
+    if (bidi) {
+        bidi->SetIsLangRTL(aIsLangRTL);
+    }
+    return true;
+}
+
 static CancelableTask* sFirstIdleTask;
 
 static void FirstIdle(void)
 {
     MOZ_ASSERT(sFirstIdleTask);
     sFirstIdleTask = nullptr;
     ContentChild::GetSingleton()->SendFirstIdle();
 }
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -237,16 +237,18 @@ public:
 
     virtual mozilla::jsipc::PJavaScriptChild* AllocPJavaScriptChild() MOZ_OVERRIDE;
     virtual bool DeallocPJavaScriptChild(mozilla::jsipc::PJavaScriptChild*) MOZ_OVERRIDE;
 
     virtual bool RecvSetOffline(const bool& offline) MOZ_OVERRIDE;
 
     virtual bool RecvSpeakerManagerNotify() MOZ_OVERRIDE;
 
+    virtual bool RecvBidiKeyboardNotify(const bool& isLangRTL) MOZ_OVERRIDE;
+
     virtual bool RecvNotifyVisited(const URIParams& aURI) MOZ_OVERRIDE;
     // auto remove when alertfinished is received.
     nsresult AddRemoteAlertObserver(const nsString& aData, nsIObserver* aObserver);
 
     virtual bool RecvSystemMemoryAvailable(const uint64_t& aGetterId,
                                            const uint32_t& aMemoryAvailable) MOZ_OVERRIDE;
 
     virtual bool RecvPreferenceUpdate(const PrefSetting& aPref) MOZ_OVERRIDE;
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -118,16 +118,18 @@
 #include "URIUtils.h"
 #include "nsIWebBrowserChrome.h"
 #include "nsIDocShell.h"
 #include "mozilla/net/NeckoMessageUtils.h"
 #include "gfxPrefs.h"
 #include "prio.h"
 #include "private/pprio.h"
 
+#include "nsBidiKeyboard.h"
+
 #if defined(ANDROID) || defined(LINUX)
 #include "nsSystemInfo.h"
 #endif
 
 #if defined(XP_LINUX)
 #include "mozilla/Hal.h"
 #endif
 
@@ -2595,23 +2597,30 @@ ContentParent::RecvGetProcessAttributes(
     *aId = mChildID;
     *aIsForApp = IsForApp();
     *aIsForBrowser = mIsForBrowser;
 
     return true;
 }
 
 bool
-ContentParent::RecvGetXPCOMProcessAttributes(bool* aIsOffline)
+ContentParent::RecvGetXPCOMProcessAttributes(bool* aIsOffline, bool* aIsLangRTL)
 {
     nsCOMPtr<nsIIOService> io(do_GetIOService());
     NS_ASSERTION(io, "No IO service?");
     DebugOnly<nsresult> rv = io->GetOffline(aIsOffline);
     NS_ASSERTION(NS_SUCCEEDED(rv), "Failed getting offline?");
 
+    nsIBidiKeyboard* bidi = nsContentUtils::GetBidiKeyboard();
+
+    *aIsLangRTL = false;
+    if (bidi) {
+        bidi->IsLangRTL(aIsLangRTL);
+    }
+
     return true;
 }
 
 mozilla::jsipc::PJavaScriptParent *
 ContentParent::AllocPJavaScriptParent()
 {
     MOZ_ASSERT(!ManagedPJavaScriptParent().Length());
     return nsIContentParent::AllocPJavaScriptParent();
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -380,17 +380,17 @@ private:
                                      base::ProcessId aOtherProcess) MOZ_OVERRIDE;
     PBackgroundParent*
     AllocPBackgroundParent(Transport* aTransport, ProcessId aOtherProcess)
                            MOZ_OVERRIDE;
 
     virtual bool RecvGetProcessAttributes(uint64_t* aId,
                                           bool* aIsForApp,
                                           bool* aIsForBrowser) MOZ_OVERRIDE;
-    virtual bool RecvGetXPCOMProcessAttributes(bool* aIsOffline) MOZ_OVERRIDE;
+    virtual bool RecvGetXPCOMProcessAttributes(bool* aIsOffline, bool* aIsLangRTL) MOZ_OVERRIDE;
 
     virtual bool DeallocPJavaScriptParent(mozilla::jsipc::PJavaScriptParent*) MOZ_OVERRIDE;
 
     virtual PBrowserParent* AllocPBrowserParent(const IPCTabContext& aContext,
                                                 const uint32_t& aChromeFlags,
                                                 const uint64_t& aId,
                                                 const bool& aIsForApp,
                                                 const bool& aIsForBrowser) MOZ_OVERRIDE;
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -356,16 +356,22 @@ child:
 
     /**
      * Notify the AudioChannelService in the child processes.
      */
     async AudioChannelNotify();
 
     async SpeakerManagerNotify();
 
+    /**
+     * Communication between the PuppetBidiKeyboard and the actual
+     * BidiKeyboard hosted by the parent
+     */
+    async BidiKeyboardNotify(bool isLangRTL);
+
     async DataStoreNotify(uint32_t aAppId, nsString aName,
                           nsString aManifestURL);
 
     /**
      * Dump this process's GC and CC logs to the provided files.
      *
      * For documentation on the other args, see dumpGCAndCCLogsToFile in
      * nsIMemoryInfoDumper.idl
@@ -448,17 +454,17 @@ parent:
      * |isForBrowser|, we're loading <browser>.  When |!isForApp &&
      * !isForBrowser|, we're probably loading <xul:browser remote>.
      *
      * Keep the return values in sync with PBrowser()!
      */
     sync GetProcessAttributes()
         returns (uint64_t id, bool isForApp, bool isForBrowser);
     sync GetXPCOMProcessAttributes()
-        returns (bool isOffline);
+        returns (bool isOffline, bool isLangRTL);
 
     sync CreateChildProcess(IPCTabContext context,
                             ProcessPriority priority)
         returns (uint64_t id, bool isForApp, bool isForBrowser);
     intr BridgeToChildProcess(uint64_t id);
 
     async PJavaScript();
 
--- a/widget/cocoa/TextInputHandler.h
+++ b/widget/cocoa/TextInputHandler.h
@@ -1111,16 +1111,18 @@ private:
   void OnEndIMEComposition();
 
   // The focused IME handler.  Please note that the handler might lost the
   // actual focus by deactivating the application.  If we are active, this
   // must have the actual focused handle.
   // We cannot access to the NSInputManager during we aren't active, so, the
   // focused handler can have an IME transaction even if we are deactive.
   static IMEInputHandler* sFocusedIMEHandler;
+
+  static bool sCachedIsForRTLLangage;
 };
 
 /**
  * TextInputHandler implements the NSTextInput protocol.
  */
 class TextInputHandler : public IMEInputHandler
 {
 public:
--- a/widget/cocoa/TextInputHandler.mm
+++ b/widget/cocoa/TextInputHandler.mm
@@ -19,16 +19,18 @@
 
 #include "nsChildView.h"
 #include "nsObjCExceptions.h"
 #include "nsBidiUtils.h"
 #include "nsToolkit.h"
 #include "nsCocoaUtils.h"
 #include "WidgetUtils.h"
 #include "nsPrintfCString.h"
+#include "mozilla/unused.h"
+#include "mozilla/dom/ContentParent.h"
 
 #ifdef __LP64__
 #include "ComplexTextInputPanel.h"
 #include <objc/runtime.h>
 #endif // __LP64__
 
 #ifdef MOZ_LOGGING
 #define FORCE_PR_LOG
@@ -2225,16 +2227,17 @@ TextInputHandler::DoCommandBySelector(co
 
 /******************************************************************************
  *
  *  IMEInputHandler implementation (static methods)
  *
  ******************************************************************************/
 
 bool IMEInputHandler::sStaticMembersInitialized = false;
+bool IMEInputHandler::sCachedIsForRTLLangage = false;
 CFStringRef IMEInputHandler::sLatestIMEOpenedModeInputSourceID = nullptr;
 IMEInputHandler* IMEInputHandler::sFocusedIMEHandler = nullptr;
 
 // static
 void
 IMEInputHandler::InitStaticMembers()
 {
   if (sStaticMembersInitialized)
@@ -2313,16 +2316,30 @@ IMEInputHandler::OnCurrentTextInputSourc
          GetCharacters(type0), tis.IsASCIICapable() ? "- ASCII capable " : "",
          GetCharacters(is4), GetCharacters(is5),
          GetCharacters(lang0), GetCharacters(bundleID0),
          GetCharacters(is2), GetCharacters(is1), GetCharacters(is3)));
     }
     sLastTIS = newTIS;
   }
 #endif // #ifdef PR_LOGGING
+
+  /**
+   * When the direction is changed, all the children are notified.
+   * No need to treat the initial case separately because it is covered
+   * by the general case (sCachedIsForRTLLangage is initially false)
+   */
+  if (sCachedIsForRTLLangage != tis.IsForRTLLanguage()) {
+    nsTArray<dom::ContentParent*> children;
+    dom::ContentParent::GetAll(children);
+    for (uint32_t i = 0; i < children.Length(); i++) {
+      unused << children[i]->SendBidiKeyboardNotify(tis.IsForRTLLanguage());
+    }
+    sCachedIsForRTLLangage = tis.IsForRTLLanguage();
+  }
 }
 
 // static
 void
 IMEInputHandler::FlushPendingMethods(nsITimer* aTimer, void* aClosure)
 {
   NS_ASSERTION(aClosure, "aClosure is null");
   static_cast<IMEInputHandler*>(aClosure)->ExecutePendingMethods();
--- a/widget/cocoa/moz.build
+++ b/widget/cocoa/moz.build
@@ -7,16 +7,17 @@
 XPIDL_SOURCES += [
     'nsPIWidgetCocoa.idl',
 ]
 
 XPIDL_MODULE = 'widget_cocoa'
 
 EXPORTS += [
     'mozView.h',
+    'nsBidiKeyboard.h',
     'nsChangeObserver.h',
     'nsCocoaFeatures.h',
     'nsCocoaUtils.h',
 ]
 
 LIBRARY_NAME = 'widget_mac'
 
 UNIFIED_SOURCES += [
--- a/widget/cocoa/nsWidgetFactory.mm
+++ b/widget/cocoa/nsWidgetFactory.mm
@@ -127,17 +127,18 @@ static const mozilla::Module::CIDEntry k
     mozilla::Module::MAIN_PROCESS_ONLY },
   { &kNS_TRANSFERABLE_CID, false, NULL, nsTransferableConstructor },
   { &kNS_HTMLFORMATCONVERTER_CID, false, NULL, nsHTMLFormatConverterConstructor },
   { &kNS_CLIPBOARD_CID, false, NULL, nsClipboardConstructor,
     mozilla::Module::MAIN_PROCESS_ONLY },
   { &kNS_CLIPBOARDHELPER_CID, false, NULL, nsClipboardHelperConstructor },
   { &kNS_DRAGSERVICE_CID, false, NULL, nsDragServiceConstructor,
     mozilla::Module::MAIN_PROCESS_ONLY },
-  { &kNS_BIDIKEYBOARD_CID, false, NULL, nsBidiKeyboardConstructor },
+  { &kNS_BIDIKEYBOARD_CID, false, NULL, nsBidiKeyboardConstructor,
+    mozilla::Module::MAIN_PROCESS_ONLY },
   { &kNS_THEMERENDERER_CID, false, NULL, nsNativeThemeCocoaConstructor },
   { &kNS_SCREENMANAGER_CID, false, NULL, nsScreenManagerCocoaConstructor },
   { &kNS_DEVICE_CONTEXT_SPEC_CID, false, NULL, nsDeviceContextSpecXConstructor,
     mozilla::Module::MAIN_PROCESS_ONLY },
   { &kNS_PRINTSESSION_CID, false, NULL, nsPrintSessionConstructor,
     mozilla::Module::MAIN_PROCESS_ONLY },
   { &kNS_PRINTSETTINGSSERVICE_CID, false, NULL, nsPrintOptionsXConstructor },
   { &kNS_PRINTDIALOGSERVICE_CID, false, NULL, nsPrintDialogServiceXConstructor,
@@ -165,17 +166,18 @@ static const mozilla::Module::ContractID
     mozilla::Module::MAIN_PROCESS_ONLY },
   { "@mozilla.org/widget/transferable;1", &kNS_TRANSFERABLE_CID },
   { "@mozilla.org/widget/htmlformatconverter;1", &kNS_HTMLFORMATCONVERTER_CID },
   { "@mozilla.org/widget/clipboard;1", &kNS_CLIPBOARD_CID,
     mozilla::Module::MAIN_PROCESS_ONLY },
   { "@mozilla.org/widget/clipboardhelper;1", &kNS_CLIPBOARDHELPER_CID },
   { "@mozilla.org/widget/dragservice;1", &kNS_DRAGSERVICE_CID,
     mozilla::Module::MAIN_PROCESS_ONLY },
-  { "@mozilla.org/widget/bidikeyboard;1", &kNS_BIDIKEYBOARD_CID },
+  { "@mozilla.org/widget/bidikeyboard;1", &kNS_BIDIKEYBOARD_CID,
+    mozilla::Module::MAIN_PROCESS_ONLY },
   { "@mozilla.org/chrome/chrome-native-theme;1", &kNS_THEMERENDERER_CID },
   { "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID },
   { "@mozilla.org/gfx/devicecontextspec;1", &kNS_DEVICE_CONTEXT_SPEC_CID,
     mozilla::Module::MAIN_PROCESS_ONLY },
   { "@mozilla.org/gfx/printsession;1", &kNS_PRINTSESSION_CID,
     mozilla::Module::MAIN_PROCESS_ONLY },
   { "@mozilla.org/gfx/printsettings-service;1", &kNS_PRINTSETTINGSSERVICE_CID },
   { NS_PRINTDIALOGSERVICE_CONTRACTID, &kNS_PRINTDIALOGSERVICE_CID,
--- a/widget/nsWidgetsCID.h
+++ b/widget/nsWidgetsCID.h
@@ -99,16 +99,19 @@
 // {B148EED2-236D-11d3-B35C-00A0CC3C1CDE}
 #define NS_SOUND_CID \
 { 0xb148eed2, 0x236d, 0x11d3, { 0xb3, 0x5c, 0x0, 0xa0, 0xcc, 0x3c, 0x1c, 0xde } }
 
 // {9f1800ab-f428-4207-b40c-e832e77b01fc}
 #define NS_BIDIKEYBOARD_CID \
 { 0x9f1800ab, 0xf428, 0x4207, { 0xb4, 0x0c, 0xe8, 0x32, 0xe7, 0x7b, 0x01, 0xfc } }
 
+#define PUPPETBIDIKEYBOARD_CID \
+{ 0x689e2586, 0x0344, 0x40b2, {0x83, 0x75, 0x13, 0x67, 0x2d, 0x3b, 0x71, 0x9a } }
+
 #define NS_SCREENMANAGER_CID \
 { 0xc401eb80, 0xf9ea, 0x11d3, { 0xbb, 0x6f, 0xe7, 0x32, 0xb7, 0x3e, 0xbe, 0x7c } }
 
 // {6987230e-0089-4e78-bc5f-1493ee7519fa}
 #define NS_IDLE_SERVICE_CID \
 { 0x6987230e, 0x0098, 0x4e78, { 0xbc, 0x5f, 0x14, 0x93, 0xee, 0x75, 0x19, 0xfa } }
 
 #define NS_WIN_TASKBAR_CID \
new file mode 100644
--- /dev/null
+++ b/widget/xpwidgets/PuppetBidiKeyboard.cpp
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "PuppetBidiKeyboard.h"
+
+using namespace mozilla::widget;
+
+NS_IMPL_ISUPPORTS(PuppetBidiKeyboard, nsIBidiKeyboard)
+
+PuppetBidiKeyboard::PuppetBidiKeyboard() : nsIBidiKeyboard()
+{
+}
+
+PuppetBidiKeyboard::~PuppetBidiKeyboard()
+{
+}
+
+NS_IMETHODIMP
+PuppetBidiKeyboard::Reset()
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PuppetBidiKeyboard::IsLangRTL(bool* aIsRTL)
+{
+  *aIsRTL = mIsLangRTL;
+  return NS_OK;
+}
+
+void
+PuppetBidiKeyboard::SetIsLangRTL(bool aIsLangRTL)
+{
+  mIsLangRTL = aIsLangRTL;
+}
+
+NS_IMETHODIMP
+PuppetBidiKeyboard::GetHaveBidiKeyboards(bool* aResult)
+{
+  // not implemented yet
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
new file mode 100644
--- /dev/null
+++ b/widget/xpwidgets/PuppetBidiKeyboard.h
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_widget_PuppetBidiKeyboard_h_
+#define mozilla_widget_PuppetBidiKeyboard_h_
+
+#include "nsIBidiKeyboard.h"
+
+namespace mozilla {
+namespace widget {
+
+class PuppetBidiKeyboard MOZ_FINAL : public nsIBidiKeyboard
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIBIDIKEYBOARD
+
+  PuppetBidiKeyboard();
+
+  void SetIsLangRTL(bool aIsLangRTL);
+
+private:
+  ~PuppetBidiKeyboard();
+
+  bool mIsLangRTL;
+};
+
+} // namespace widget
+} // namespace mozilla
+
+#endif // mozilla_widget_PuppetBidiKeyboard_h_
--- a/widget/xpwidgets/moz.build
+++ b/widget/xpwidgets/moz.build
@@ -6,16 +6,20 @@
 
 EXPORTS += [
     'ContentHelper.h',
     'GfxDriverInfo.h',
     'GfxInfoBase.h',
     'GfxInfoCollector.h',
 ]
 
+EXPORTS.mozilla.widget += [
+    'PuppetBidiKeyboard.h',
+]
+
 UNIFIED_SOURCES += [
     'ContentHelper.cpp',
     'GfxDriverInfo.cpp',
     'GfxInfoBase.cpp',
     'GfxInfoCollector.cpp',
     'GfxInfoWebGL.cpp',
     'InputData.cpp',
     'nsBaseAppShell.cpp',
@@ -31,16 +35,17 @@ UNIFIED_SOURCES += [
     'nsIdleService.cpp',
     'nsIWidgetListener.cpp',
     'nsPrimitiveHelpers.cpp',
     'nsPrintOptionsImpl.cpp',
     'nsPrintSession.cpp',
     'nsPrintSettingsImpl.cpp',
     'nsTransferable.cpp',
     'nsXPLookAndFeel.cpp',
+    'PuppetBidiKeyboard.cpp',
     'PuppetWidget.cpp',
     'WidgetUtils.cpp',
 ]
 
 # nsBaseWidget.cpp needs to be built separately because of name clashes in the OS X headers
 SOURCES += [
     'nsBaseWidget.cpp',
 ]
--- a/widget/xpwidgets/nsContentProcessWidgetFactory.cpp
+++ b/widget/xpwidgets/nsContentProcessWidgetFactory.cpp
@@ -5,43 +5,50 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/ModuleUtils.h"
 #include "nsWidgetsCID.h"
 #include "nsClipboardProxy.h"
 #include "nsColorPickerProxy.h"
 #include "nsFilePickerProxy.h"
+#include "PuppetBidiKeyboard.h"
 
 using namespace mozilla;
+using namespace mozilla::widget;
 
 #ifndef MOZ_B2G
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardProxy)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsColorPickerProxy)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePickerProxy)
+NS_GENERIC_FACTORY_CONSTRUCTOR(PuppetBidiKeyboard)
 
 NS_DEFINE_NAMED_CID(NS_CLIPBOARD_CID);
 NS_DEFINE_NAMED_CID(NS_COLORPICKER_CID);
 NS_DEFINE_NAMED_CID(NS_FILEPICKER_CID);
+NS_DEFINE_NAMED_CID(PUPPETBIDIKEYBOARD_CID);
 
 static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
     { &kNS_CLIPBOARD_CID, false, nullptr, nsClipboardProxyConstructor,
       Module::CONTENT_PROCESS_ONLY },
     { &kNS_COLORPICKER_CID, false, nullptr, nsColorPickerProxyConstructor,
       Module::CONTENT_PROCESS_ONLY },
     { &kNS_FILEPICKER_CID, false, nullptr, nsFilePickerProxyConstructor,
       Module::CONTENT_PROCESS_ONLY },
+    { &kPUPPETBIDIKEYBOARD_CID, false, NULL, PuppetBidiKeyboardConstructor,
+      mozilla::Module::CONTENT_PROCESS_ONLY },
     { nullptr }
 };
 
 static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
     { "@mozilla.org/widget/clipboard;1", &kNS_CLIPBOARD_CID, Module::CONTENT_PROCESS_ONLY },
     { "@mozilla.org/colorpicker;1", &kNS_COLORPICKER_CID, Module::CONTENT_PROCESS_ONLY },
     { "@mozilla.org/filepicker;1", &kNS_FILEPICKER_CID, Module::CONTENT_PROCESS_ONLY },
+    { "@mozilla.org/widget/bidikeyboard;1", &kPUPPETBIDIKEYBOARD_CID, Module::CONTENT_PROCESS_ONLY },
     { nullptr }
 };
 
 static const mozilla::Module kWidgetModule = {
     mozilla::Module::kVersion,
     kWidgetCIDs,
     kWidgetContracts
 };