Bug 1594215 - Make `PuppetWidget::GetEditCommands()` check `mBrowserChild` before using it r=smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 08 Nov 2019 11:32:51 +0000
changeset 501307 fce96cf0927052cadd5e04f190fd7a6728fdc88a
parent 501306 a2efa664360f899762b56993cfd0fa6f8c3f31cf
child 501308 0694c0c467584e42b9abb3d05b78f9c764cd6b18
push id114168
push userdluca@mozilla.com
push dateSun, 10 Nov 2019 03:08:55 +0000
treeherdermozilla-inbound@33f64c1ef3e4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1594215
milestone72.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 1594215 - Make `PuppetWidget::GetEditCommands()` check `mBrowserChild` before using it r=smaug The reason of the crash is, the window may have already been destroyed and `PuppetWidget::mBrowserChild` was set to `nullptr` when synthesizing key event. This patch makes `PuppetWidget::GetEditCommands()` check whether it's `nullptr` and returns whether it's succeeded or not. Therefore, `TextInputProcessor` can throw exception in such case. Differential Revision: https://phabricator.services.mozilla.com/D52308
dom/base/TextInputProcessor.cpp
dom/ipc/BrowserParent.cpp
widget/PuppetWidget.cpp
widget/PuppetWidget.h
widget/TextEvents.h
widget/WidgetEventImpl.cpp
widget/cocoa/nsChildView.h
widget/cocoa/nsChildView.mm
widget/cocoa/nsCocoaWindow.h
widget/cocoa/nsCocoaWindow.mm
widget/gtk/nsWindow.cpp
widget/gtk/nsWindow.h
widget/headless/HeadlessWidget.cpp
widget/headless/HeadlessWidget.h
widget/nsBaseWidget.cpp
widget/nsIWidget.h
--- a/dom/base/TextInputProcessor.cpp
+++ b/dom/base/TextInputProcessor.cpp
@@ -994,22 +994,28 @@ nsresult TextInputProcessor::PrepareKeyb
   if (aKeyboardEvent.mIsSynthesizedByTIP && !XRE_IsParentProcess()) {
     // Note that retrieving edit commands from content process is expensive.
     // Let's skip it when the keyboard event is inputting text.
     if (!aKeyboardEvent.IsInputtingText()) {
       // FYI: WidgetKeyboardEvent::InitAllEditCommands() isn't available here
       //      since it checks whether it's called in the main process to
       //      avoid performance issues so that we need to initialize each
       //      command manually here.
-      aKeyboardEvent.InitEditCommandsFor(
-          nsIWidget::NativeKeyBindingsForSingleLineEditor);
-      aKeyboardEvent.InitEditCommandsFor(
-          nsIWidget::NativeKeyBindingsForMultiLineEditor);
-      aKeyboardEvent.InitEditCommandsFor(
-          nsIWidget::NativeKeyBindingsForRichTextEditor);
+      if (NS_WARN_IF(!aKeyboardEvent.InitEditCommandsFor(
+              nsIWidget::NativeKeyBindingsForSingleLineEditor))) {
+        return NS_ERROR_NOT_AVAILABLE;
+      }
+      if (NS_WARN_IF(!aKeyboardEvent.InitEditCommandsFor(
+              nsIWidget::NativeKeyBindingsForMultiLineEditor))) {
+        return NS_ERROR_NOT_AVAILABLE;
+      }
+      if (NS_WARN_IF(!aKeyboardEvent.InitEditCommandsFor(
+              nsIWidget::NativeKeyBindingsForRichTextEditor))) {
+        return NS_ERROR_NOT_AVAILABLE;
+      }
     } else {
       aKeyboardEvent.PreventNativeKeyBindings();
     }
   }
 
   return NS_OK;
 }
 
--- a/dom/ipc/BrowserParent.cpp
+++ b/dom/ipc/BrowserParent.cpp
@@ -1605,18 +1605,19 @@ mozilla::ipc::IPCResult BrowserParent::R
 
   WidgetKeyboardEvent localEvent(aEvent);
   localEvent.mWidget = widget;
 
   if (NS_FAILED(widget->AttachNativeKeyEvent(localEvent))) {
     return IPC_OK();
   }
 
-  localEvent.InitEditCommandsFor(keyBindingsType);
-  *aCommands = localEvent.EditCommandsConstRef(keyBindingsType);
+  if (localEvent.InitEditCommandsFor(keyBindingsType)) {
+    *aCommands = localEvent.EditCommandsConstRef(keyBindingsType);
+  }
 
   return IPC_OK();
 }
 
 class SynthesizedEventObserver : public nsIObserver {
   NS_DECL_ISUPPORTS
 
  public:
--- a/widget/PuppetWidget.cpp
+++ b/widget/PuppetWidget.cpp
@@ -523,23 +523,28 @@ void PuppetWidget::UpdateZoomConstraints
     mBrowserChild->DoUpdateZoomConstraints(aPresShellId, aViewId, aConstraints);
   }
 }
 
 bool PuppetWidget::AsyncPanZoomEnabled() const {
   return mBrowserChild && mBrowserChild->AsyncPanZoomEnabled();
 }
 
-void PuppetWidget::GetEditCommands(NativeKeyBindingsType aType,
+bool PuppetWidget::GetEditCommands(NativeKeyBindingsType aType,
                                    const WidgetKeyboardEvent& aEvent,
                                    nsTArray<CommandInt>& aCommands) {
   // Validate the arguments.
-  nsIWidget::GetEditCommands(aType, aEvent, aCommands);
-
+  if (NS_WARN_IF(!nsIWidget::GetEditCommands(aType, aEvent, aCommands))) {
+    return false;
+  }
+  if (NS_WARN_IF(!mBrowserChild)) {
+    return false;
+  }
   mBrowserChild->RequestEditCommands(aType, aEvent, aCommands);
+  return true;
 }
 
 LayerManager* PuppetWidget::GetLayerManager(
     PLayerTransactionChild* aShadowManager, LayersBackend aBackendHint,
     LayerManagerPersistence aPersistence) {
   if (!mLayerManager) {
     if (XRE_IsParentProcess()) {
       // On the parent process there is no CompositorBridgeChild which confuses
--- a/widget/PuppetWidget.h
+++ b/widget/PuppetWidget.h
@@ -151,17 +151,17 @@ class PuppetWidget : public nsBaseWidget
   void SetConfirmedTargetAPZC(
       uint64_t aInputBlockId,
       const nsTArray<SLGuidAndRenderRoot>& aTargets) const override;
   void UpdateZoomConstraints(
       const uint32_t& aPresShellId, const ScrollableLayerGuid::ViewID& aViewId,
       const mozilla::Maybe<ZoomConstraints>& aConstraints) override;
   bool AsyncPanZoomEnabled() const override;
 
-  virtual void GetEditCommands(
+  virtual bool GetEditCommands(
       NativeKeyBindingsType aType, const mozilla::WidgetKeyboardEvent& aEvent,
       nsTArray<mozilla::CommandInt>& aCommands) override;
 
   friend struct AutoCacheNativeKeyCommands;
 
   //
   // nsBaseWidget methods we override
   //
--- a/widget/TextEvents.h
+++ b/widget/TextEvents.h
@@ -449,18 +449,22 @@ class WidgetKeyboardEvent : public Widge
    * the instance is an untrusted event, doesn't have widget or in non-chrome
    * process.
    */
   void InitAllEditCommands();
 
   /**
    * Retrieves edit commands from mWidget only for aType.  This shouldn't be
    * called when the instance is an untrusted event or doesn't have widget.
+   *
+   * @return            false if some resource is not available to get
+   *                    commands unexpectedly.  Otherwise, true even if
+   *                    retrieved command is nothing.
    */
-  void InitEditCommandsFor(nsIWidget::NativeKeyBindingsType aType);
+  bool InitEditCommandsFor(nsIWidget::NativeKeyBindingsType aType);
 
   /**
    * PreventNativeKeyBindings() makes the instance to not cause any edit
    * actions even if it matches with a native key binding.
    */
   void PreventNativeKeyBindings() {
     mEditCommandsForSingleLineEditor.Clear();
     mEditCommandsForMultiLineEditor.Clear();
--- a/widget/WidgetEventImpl.cpp
+++ b/widget/WidgetEventImpl.cpp
@@ -745,34 +745,49 @@ void WidgetKeyboardEvent::InitAllEditCom
   }
 
   MOZ_ASSERT(
       XRE_IsParentProcess(),
       "It's too expensive to retrieve all edit commands from remote process");
   MOZ_ASSERT(!AreAllEditCommandsInitialized(),
              "Shouldn't be called two or more times");
 
-  InitEditCommandsFor(nsIWidget::NativeKeyBindingsForSingleLineEditor);
-  InitEditCommandsFor(nsIWidget::NativeKeyBindingsForMultiLineEditor);
-  InitEditCommandsFor(nsIWidget::NativeKeyBindingsForRichTextEditor);
+  DebugOnly<bool> okIgnored =
+      InitEditCommandsFor(nsIWidget::NativeKeyBindingsForSingleLineEditor);
+  NS_WARNING_ASSERTION(
+      okIgnored,
+      "InitEditCommandsFor(nsIWidget::NativeKeyBindingsForSingleLineEditor) "
+      "failed, but ignored");
+  okIgnored =
+      InitEditCommandsFor(nsIWidget::NativeKeyBindingsForMultiLineEditor);
+  NS_WARNING_ASSERTION(
+      okIgnored,
+      "InitEditCommandsFor(nsIWidget::NativeKeyBindingsForMultiLineEditor) "
+      "failed, but ignored");
+  okIgnored =
+      InitEditCommandsFor(nsIWidget::NativeKeyBindingsForRichTextEditor);
+  NS_WARNING_ASSERTION(
+      okIgnored,
+      "InitEditCommandsFor(nsIWidget::NativeKeyBindingsForRichTextEditor) "
+      "failed, but ignored");
 }
 
-void WidgetKeyboardEvent::InitEditCommandsFor(
+bool WidgetKeyboardEvent::InitEditCommandsFor(
     nsIWidget::NativeKeyBindingsType aType) {
   if (NS_WARN_IF(!mWidget) || NS_WARN_IF(!IsTrusted())) {
-    return;
+    return false;
   }
 
   bool& initialized = IsEditCommandsInitializedRef(aType);
   if (initialized) {
-    return;
+    return true;
   }
   nsTArray<CommandInt>& commands = EditCommandsRef(aType);
-  mWidget->GetEditCommands(aType, *this, commands);
-  initialized = true;
+  initialized = mWidget->GetEditCommands(aType, *this, commands);
+  return initialized;
 }
 
 bool WidgetKeyboardEvent::ExecuteEditCommands(
     nsIWidget::NativeKeyBindingsType aType, DoCommandCallback aCallback,
     void* aCallbackData) {
   // If the event was created without widget, e.g., created event in chrome
   // script, this shouldn't execute native key bindings.
   if (NS_WARN_IF(!mWidget)) {
@@ -780,17 +795,19 @@ bool WidgetKeyboardEvent::ExecuteEditCom
   }
 
   // This event should be trusted event here and we shouldn't expose native
   // key binding information to web contents with untrusted events.
   if (NS_WARN_IF(!IsTrusted())) {
     return false;
   }
 
-  InitEditCommandsFor(aType);
+  if (NS_WARN_IF(!InitEditCommandsFor(aType))) {
+    return false;
+  }
 
   const nsTArray<CommandInt>& commands = EditCommandsRef(aType);
   if (commands.IsEmpty()) {
     return false;
   }
 
   for (CommandInt command : commands) {
     aCallback(static_cast<Command>(command), aCallbackData);
--- a/widget/cocoa/nsChildView.h
+++ b/widget/cocoa/nsChildView.h
@@ -424,17 +424,17 @@ class nsChildView final : public nsBaseW
   virtual nsresult ForceUpdateNativeMenuAt(const nsAString& indexString) override;
   virtual MOZ_MUST_USE nsresult GetSelectionAsPlaintext(nsAString& aResult) override;
 
   virtual void SetInputContext(const InputContext& aContext,
                                const InputContextAction& aAction) override;
   virtual InputContext GetInputContext() override;
   virtual TextEventDispatcherListener* GetNativeTextEventDispatcherListener() override;
   virtual MOZ_MUST_USE nsresult AttachNativeKeyEvent(mozilla::WidgetKeyboardEvent& aEvent) override;
-  virtual void GetEditCommands(NativeKeyBindingsType aType,
+  virtual bool GetEditCommands(NativeKeyBindingsType aType,
                                const mozilla::WidgetKeyboardEvent& aEvent,
                                nsTArray<mozilla::CommandInt>& aCommands) override;
   void GetEditCommandsRemapped(NativeKeyBindingsType aType,
                                const mozilla::WidgetKeyboardEvent& aEvent,
                                nsTArray<mozilla::CommandInt>& aCommands, uint32_t aGeckoKeyCode,
                                uint32_t aCocoaKeyCode);
 
   virtual nsTransparencyMode GetTransparencyMode() override;
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -1756,20 +1756,22 @@ void nsChildView::GetEditCommandsRemappe
                                 charactersIgnoringModifiers:chars
                                                   isARepeat:[originalEvent isARepeat]
                                                     keyCode:aCocoaKeyCode];
 
   NativeKeyBindings* keyBindings = NativeKeyBindings::GetInstance(aType);
   keyBindings->GetEditCommands(modifiedEvent, aCommands);
 }
 
-void nsChildView::GetEditCommands(NativeKeyBindingsType aType, const WidgetKeyboardEvent& aEvent,
+bool nsChildView::GetEditCommands(NativeKeyBindingsType aType, const WidgetKeyboardEvent& aEvent,
                                   nsTArray<CommandInt>& aCommands) {
   // Validate the arguments.
-  nsIWidget::GetEditCommands(aType, aEvent, aCommands);
+  if (NS_WARN_IF(!nsIWidget::GetEditCommands(aType, aEvent, aCommands))) {
+    return false;
+  }
 
   // If the key is a cursor-movement arrow, and the current selection has
   // vertical writing-mode, we'll remap so that the movement command
   // generated (in terms of characters/lines) will be appropriate for
   // the physical direction of the arrow.
   if (aEvent.mKeyCode >= NS_VK_LEFT && aEvent.mKeyCode <= NS_VK_DOWN) {
     // XXX This may be expensive. Should use the cache in TextInputHandler.
     WidgetQueryContentEvent query(true, eQuerySelectedText, this);
@@ -1807,22 +1809,23 @@ void nsChildView::GetEditCommands(Native
 
         case NS_VK_DOWN:
           geckoKey = NS_VK_RIGHT;
           cocoaKey = kVK_RightArrow;
           break;
       }
 
       GetEditCommandsRemapped(aType, aEvent, aCommands, geckoKey, cocoaKey);
-      return;
+      return true;
     }
   }
 
   NativeKeyBindings* keyBindings = NativeKeyBindings::GetInstance(aType);
   keyBindings->GetEditCommands(aEvent, aCommands);
+  return true;
 }
 
 NSView<mozView>* nsChildView::GetEditorView() {
   NSView<mozView>* editorView = mView;
   // We need to get editor's view. E.g., when the focus is in the bookmark
   // dialog, the view is <panel> element of the dialog.  At this time, the key
   // events are processed the parent window's view that has native focus.
   WidgetQueryContentEvent queryContentState(true, eQueryContentState, this);
--- a/widget/cocoa/nsCocoaWindow.h
+++ b/widget/cocoa/nsCocoaWindow.h
@@ -323,17 +323,17 @@ class nsCocoaWindow final : public nsBas
   NSWindow* GetCocoaWindow() { return mWindow; }
 
   void SetMenuBar(nsMenuBarX* aMenuBar);
   nsMenuBarX* GetMenuBar();
 
   virtual void SetInputContext(const InputContext& aContext,
                                const InputContextAction& aAction) override;
   virtual InputContext GetInputContext() override { return mInputContext; }
-  virtual void GetEditCommands(NativeKeyBindingsType aType,
+  virtual bool GetEditCommands(NativeKeyBindingsType aType,
                                const mozilla::WidgetKeyboardEvent& aEvent,
                                nsTArray<mozilla::CommandInt>& aCommands) override;
 
   void SetPopupWindowLevel();
 
   bool InFullScreenMode() const { return mInFullScreenMode; }
 
  protected:
--- a/widget/cocoa/nsCocoaWindow.mm
+++ b/widget/cocoa/nsCocoaWindow.mm
@@ -2252,23 +2252,26 @@ void nsCocoaWindow::SetInputContext(cons
                                     const InputContextAction& aAction) {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   mInputContext = aContext;
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
-void nsCocoaWindow::GetEditCommands(NativeKeyBindingsType aType, const WidgetKeyboardEvent& aEvent,
+bool nsCocoaWindow::GetEditCommands(NativeKeyBindingsType aType, const WidgetKeyboardEvent& aEvent,
                                     nsTArray<CommandInt>& aCommands) {
   // Validate the arguments.
-  nsIWidget::GetEditCommands(aType, aEvent, aCommands);
+  if (NS_WARN_IF(!nsIWidget::GetEditCommands(aType, aEvent, aCommands))) {
+    return false;
+  }
 
   NativeKeyBindings* keyBindings = NativeKeyBindings::GetInstance(aType);
   keyBindings->GetEditCommands(aEvent, aCommands);
+  return true;
 }
 
 already_AddRefed<nsIWidget> nsIWidget::CreateTopLevelWindow() {
   nsCOMPtr<nsIWidget> window = new nsCocoaWindow();
   return window.forget();
 }
 
 already_AddRefed<nsIWidget> nsIWidget::CreateChildWindow() {
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -6389,21 +6389,23 @@ void nsWindow::GetEditCommandsRemapped(N
   modifiedEvent.mKeyCode = aGeckoKeyCode;
   static_cast<GdkEventKey*>(modifiedEvent.mNativeKeyEvent)->keyval =
       aNativeKeyCode;
 
   NativeKeyBindings* keyBindings = NativeKeyBindings::GetInstance(aType);
   keyBindings->GetEditCommands(modifiedEvent, aCommands);
 }
 
-void nsWindow::GetEditCommands(NativeKeyBindingsType aType,
+bool nsWindow::GetEditCommands(NativeKeyBindingsType aType,
                                const WidgetKeyboardEvent& aEvent,
                                nsTArray<CommandInt>& aCommands) {
   // Validate the arguments.
-  nsIWidget::GetEditCommands(aType, aEvent, aCommands);
+  if (NS_WARN_IF(!nsIWidget::GetEditCommands(aType, aEvent, aCommands))) {
+    return false;
+  }
 
   if (aEvent.mKeyCode >= NS_VK_LEFT && aEvent.mKeyCode <= NS_VK_DOWN) {
     // Check if we're targeting content with vertical writing mode,
     // and if so remap the arrow keys.
     // XXX This may be expensive.
     WidgetQueryContentEvent query(true, eQuerySelectedText, this);
     nsEventStatus status;
     DispatchEvent(&query, status);
@@ -6439,22 +6441,23 @@ void nsWindow::GetEditCommands(NativeKey
 
         case NS_VK_DOWN:
           geckoCode = NS_VK_RIGHT;
           gdkCode = GDK_Right;
           break;
       }
 
       GetEditCommandsRemapped(aType, aEvent, aCommands, geckoCode, gdkCode);
-      return;
+      return true;
     }
   }
 
   NativeKeyBindings* keyBindings = NativeKeyBindings::GetInstance(aType);
   keyBindings->GetEditCommands(aEvent, aCommands);
+  return true;
 }
 
 already_AddRefed<DrawTarget> nsWindow::StartRemoteDrawingInRegion(
     LayoutDeviceIntRegion& aInvalidRegion, BufferMode* aBufferMode) {
   return mSurfaceProvider.StartRemoteDrawingInRegion(aInvalidRegion,
                                                      aBufferMode);
 }
 
--- a/widget/gtk/nsWindow.h
+++ b/widget/gtk/nsWindow.h
@@ -295,17 +295,17 @@ class nsWindow final : public nsBaseWidg
                                const InputContextAction& aAction) override;
   virtual InputContext GetInputContext() override;
   virtual TextEventDispatcherListener* GetNativeTextEventDispatcherListener()
       override;
   void GetEditCommandsRemapped(NativeKeyBindingsType aType,
                                const mozilla::WidgetKeyboardEvent& aEvent,
                                nsTArray<mozilla::CommandInt>& aCommands,
                                uint32_t aGeckoKeyCode, uint32_t aNativeKeyCode);
-  virtual void GetEditCommands(
+  virtual bool GetEditCommands(
       NativeKeyBindingsType aType, const mozilla::WidgetKeyboardEvent& aEvent,
       nsTArray<mozilla::CommandInt>& aCommands) override;
 
   // These methods are for toplevel windows only.
   void ResizeTransparencyBitmap();
   void ApplyTransparencyBitmap();
   void ClearTransparencyBitmap();
 
--- a/widget/headless/HeadlessWidget.cpp
+++ b/widget/headless/HeadlessWidget.cpp
@@ -386,24 +386,27 @@ nsresult HeadlessWidget::MakeFullScreen(
   return NS_OK;
 }
 
 nsresult HeadlessWidget::AttachNativeKeyEvent(WidgetKeyboardEvent& aEvent) {
   HeadlessKeyBindings& bindings = HeadlessKeyBindings::GetInstance();
   return bindings.AttachNativeKeyEvent(aEvent);
 }
 
-void HeadlessWidget::GetEditCommands(NativeKeyBindingsType aType,
+bool HeadlessWidget::GetEditCommands(NativeKeyBindingsType aType,
                                      const WidgetKeyboardEvent& aEvent,
                                      nsTArray<CommandInt>& aCommands) {
   // Validate the arguments.
-  nsIWidget::GetEditCommands(aType, aEvent, aCommands);
+  if (NS_WARN_IF(!nsIWidget::GetEditCommands(aType, aEvent, aCommands))) {
+    return false;
+  }
 
   HeadlessKeyBindings& bindings = HeadlessKeyBindings::GetInstance();
   bindings.GetEditCommands(aType, aEvent, aCommands);
+  return true;
 }
 
 nsresult HeadlessWidget::DispatchEvent(WidgetGUIEvent* aEvent,
                                        nsEventStatus& aStatus) {
 #ifdef DEBUG
   debug_DumpEvent(stdout, aEvent->mWidget, aEvent, "HeadlessWidget", 0);
 #endif
 
--- a/widget/headless/HeadlessWidget.h
+++ b/widget/headless/HeadlessWidget.h
@@ -119,17 +119,17 @@ class HeadlessWidget : public nsBaseWidg
       PLayerTransactionChild* aShadowManager = nullptr,
       LayersBackend aBackendHint = mozilla::layers::LayersBackend::LAYERS_NONE,
       LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT) override;
 
   void SetCompositorWidgetDelegate(CompositorWidgetDelegate* delegate) override;
 
   virtual MOZ_MUST_USE nsresult
   AttachNativeKeyEvent(WidgetKeyboardEvent& aEvent) override;
-  virtual void GetEditCommands(NativeKeyBindingsType aType,
+  virtual bool GetEditCommands(NativeKeyBindingsType aType,
                                const WidgetKeyboardEvent& aEvent,
                                nsTArray<CommandInt>& aCommands) override;
 
   virtual nsresult DispatchEvent(WidgetGUIEvent* aEvent,
                                  nsEventStatus& aStatus) override;
 
   virtual nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint,
                                               uint32_t aNativeMessage,
--- a/widget/nsBaseWidget.cpp
+++ b/widget/nsBaseWidget.cpp
@@ -2212,21 +2212,22 @@ const IMENotificationRequests& nsIWidget
 nsresult nsIWidget::OnWindowedPluginKeyEvent(
     const NativeEventData& aKeyEventData,
     nsIKeyEventInPluginCallback* aCallback) {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 void nsIWidget::PostHandleKeyEvent(mozilla::WidgetKeyboardEvent* aEvent) {}
 
-void nsIWidget::GetEditCommands(nsIWidget::NativeKeyBindingsType aType,
+bool nsIWidget::GetEditCommands(nsIWidget::NativeKeyBindingsType aType,
                                 const WidgetKeyboardEvent& aEvent,
                                 nsTArray<CommandInt>& aCommands) {
   MOZ_ASSERT(aEvent.IsTrusted());
   MOZ_ASSERT(aCommands.IsEmpty());
+  return true;
 }
 
 already_AddRefed<nsIBidiKeyboard> nsIWidget::CreateBidiKeyboard() {
   if (XRE_IsContentProcess()) {
     return CreateBidiKeyboardContentProcess();
   }
   return CreateBidiKeyboardInner();
 }
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -1890,17 +1890,17 @@ class nsIWidget : public nsISupports {
    * Retrieve edit commands when the key combination of aEvent is used
    * in platform native applications.
    */
   enum NativeKeyBindingsType : uint8_t {
     NativeKeyBindingsForSingleLineEditor,
     NativeKeyBindingsForMultiLineEditor,
     NativeKeyBindingsForRichTextEditor
   };
-  virtual void GetEditCommands(NativeKeyBindingsType aType,
+  virtual bool GetEditCommands(NativeKeyBindingsType aType,
                                const mozilla::WidgetKeyboardEvent& aEvent,
                                nsTArray<mozilla::CommandInt>& aCommands);
 
   /*
    * Retrieves a reference to notification requests of IME.  Note that the
    * reference is valid while the nsIWidget instance is alive.  So, if you
    * need to store the reference for a long time, you need to grab the widget
    * instance too.