Teach render_host about a mojo WidgetInputHandler.

Implement a WidgetInputHandler as a legacy interface over Chrome IPC.
This will then allow us to dynamically swap it with a mojo backed one.

This change does not provide a mojo backed implementation of this
interface but just an implementation of the interface backed by Chrome IPC.
The new implementation will come in another CL.

BUG=722928
[email protected]

Cq-Include-Trybots: master.tryserver.chromium.linux:linux_site_isolation
Change-Id: I03bb42524cec501a8b76f517629e0b3e3e76bba0
Reviewed-on: https://chromium-review.googlesource.com/541036
Commit-Queue: Dave Tapuska <[email protected]>
Reviewed-by: Daniel Cheng <[email protected]>
Reviewed-by: Antoine Labour <[email protected]>
Cr-Commit-Position: refs/heads/master@{#484707}
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 9d7600a..21861aa 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -1136,6 +1136,8 @@
     "renderer_host/input/input_router_config_helper.h",
     "renderer_host/input/legacy_input_router_impl.cc",
     "renderer_host/input/legacy_input_router_impl.h",
+    "renderer_host/input/legacy_ipc_widget_input_handler.cc",
+    "renderer_host/input/legacy_ipc_widget_input_handler.h",
     "renderer_host/input/legacy_touch_event_queue.cc",
     "renderer_host/input/legacy_touch_event_queue.h",
     "renderer_host/input/motion_event_web.cc",
diff --git a/content/browser/android/ime_adapter_android.cc b/content/browser/android/ime_adapter_android.cc
index c864386..5bd5f4b 100644
--- a/content/browser/android/ime_adapter_android.cc
+++ b/content/browser/android/ime_adapter_android.cc
@@ -27,7 +27,7 @@
 #include "jni/ImeAdapter_jni.h"
 #include "third_party/WebKit/public/platform/WebInputEvent.h"
 #include "third_party/WebKit/public/platform/WebTextInputType.h"
-#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
+#include "ui/base/ime/composition_underline.h"
 
 using base::android::AttachCurrentThread;
 using base::android::ConvertJavaStringToUTF16;
@@ -77,7 +77,7 @@
 }
 
 // Callback from Java to convert BackgroundColorSpan data to a
-// blink::WebCompositionUnderline instance, and append it to |underlines_ptr|.
+// ui::CompositionUnderline instance, and append it to |underlines_ptr|.
 void AppendBackgroundColorSpan(JNIEnv*,
                                const JavaParamRef<jclass>&,
                                jlong underlines_ptr,
@@ -87,16 +87,15 @@
   DCHECK_GE(start, 0);
   DCHECK_GE(end, 0);
   // Do not check |background_color|.
-  std::vector<blink::WebCompositionUnderline>* underlines =
-      reinterpret_cast<std::vector<blink::WebCompositionUnderline>*>(
-          underlines_ptr);
-  underlines->push_back(blink::WebCompositionUnderline(
+  std::vector<ui::CompositionUnderline>* underlines =
+      reinterpret_cast<std::vector<ui::CompositionUnderline>*>(underlines_ptr);
+  underlines->push_back(ui::CompositionUnderline(
       static_cast<unsigned>(start), static_cast<unsigned>(end),
       SK_ColorTRANSPARENT, false, static_cast<unsigned>(background_color)));
 }
 
 // Callback from Java to convert UnderlineSpan data to a
-// blink::WebCompositionUnderline instance, and append it to |underlines_ptr|.
+// ui::CompositionUnderline instance, and append it to |underlines_ptr|.
 void AppendUnderlineSpan(JNIEnv*,
                          const JavaParamRef<jclass>&,
                          jlong underlines_ptr,
@@ -104,10 +103,9 @@
                          jint end) {
   DCHECK_GE(start, 0);
   DCHECK_GE(end, 0);
-  std::vector<blink::WebCompositionUnderline>* underlines =
-      reinterpret_cast<std::vector<blink::WebCompositionUnderline>*>(
-          underlines_ptr);
-  underlines->push_back(blink::WebCompositionUnderline(
+  std::vector<ui::CompositionUnderline>* underlines =
+      reinterpret_cast<std::vector<ui::CompositionUnderline>*>(underlines_ptr);
+  underlines->push_back(ui::CompositionUnderline(
       static_cast<unsigned>(start), static_cast<unsigned>(end), SK_ColorBLACK,
       false, SK_ColorTRANSPARENT));
 }
@@ -216,12 +214,12 @@
 
   base::string16 text16 = ConvertJavaStringToUTF16(env, text_str);
 
-  std::vector<blink::WebCompositionUnderline> underlines =
+  std::vector<ui::CompositionUnderline> underlines =
       GetUnderlinesFromSpans(env, obj, text, text16);
 
   // Default to plain underline if we didn't find any span that we care about.
   if (underlines.empty()) {
-    underlines.push_back(blink::WebCompositionUnderline(
+    underlines.push_back(ui::CompositionUnderline(
         0, text16.length(), SK_ColorBLACK, false, SK_ColorTRANSPARENT));
   }
 
@@ -246,7 +244,7 @@
 
   base::string16 text16 = ConvertJavaStringToUTF16(env, text_str);
 
-  std::vector<blink::WebCompositionUnderline> underlines =
+  std::vector<ui::CompositionUnderline> underlines =
       GetUnderlinesFromSpans(env, obj, text, text16);
 
   // relative_cursor_pos is as described in the Android API for
@@ -288,7 +286,8 @@
 void ImeAdapterAndroid::AdvanceFocusInForm(JNIEnv* env,
                                            const JavaParamRef<jobject>& obj,
                                            jint focus_type) {
-  RenderFrameHost* rfh = GetFocusedFrame();
+  RenderFrameHostImpl* rfh =
+      static_cast<RenderFrameHostImpl*>(GetFocusedFrame());
   if (!rfh)
     return;
 
@@ -301,7 +300,8 @@
     const JavaParamRef<jobject>&,
     int start,
     int end) {
-  RenderFrameHost* rfh = GetFocusedFrame();
+  RenderFrameHostImpl* rfh =
+      static_cast<RenderFrameHostImpl*>(GetFocusedFrame());
   if (!rfh)
     return;
 
@@ -335,7 +335,8 @@
                                            const JavaParamRef<jobject>&,
                                            int start,
                                            int end) {
-  RenderFrameHost* rfh = GetFocusedFrame();
+  RenderFrameHostImpl* rfh =
+      static_cast<RenderFrameHostImpl*>(GetFocusedFrame());
   if (!rfh)
     return;
 
@@ -376,7 +377,7 @@
   RenderWidgetHostImpl* rwhi = GetFocusedWidget();
   if (!rwhi)
     return false;
-  rwhi->Send(new InputMsg_RequestTextInputStateUpdate(rwhi->GetRoutingID()));
+  rwhi->GetWidgetInputHandler()->RequestTextInputStateUpdate();
   return true;
 }
 
@@ -388,8 +389,8 @@
   RenderWidgetHostImpl* rwhi = GetFocusedWidget();
   if (!rwhi)
     return;
-  rwhi->Send(new InputMsg_RequestCompositionUpdates(
-      rwhi->GetRoutingID(), immediate_request, monitor_request));
+  rwhi->GetWidgetInputHandler()->RequestCompositionUpdates(immediate_request,
+                                                           monitor_request);
 }
 
 RenderWidgetHostImpl* ImeAdapterAndroid::GetFocusedWidget() {
@@ -415,13 +416,12 @@
   return nullptr;
 }
 
-std::vector<blink::WebCompositionUnderline>
-ImeAdapterAndroid::GetUnderlinesFromSpans(
+std::vector<ui::CompositionUnderline> ImeAdapterAndroid::GetUnderlinesFromSpans(
     JNIEnv* env,
     const base::android::JavaParamRef<jobject>& obj,
     const base::android::JavaParamRef<jobject>& text,
     const base::string16& text16) {
-  std::vector<blink::WebCompositionUnderline> underlines;
+  std::vector<ui::CompositionUnderline> underlines;
   // Iterate over spans in |text|, dispatch those that we care about (e.g.,
   // BackgroundColorSpan) to a matching callback (e.g.,
   // AppendBackgroundColorSpan()), and populate |underlines|.
diff --git a/content/browser/android/ime_adapter_android.h b/content/browser/android/ime_adapter_android.h
index 25012d8a..b0f775f 100644
--- a/content/browser/android/ime_adapter_android.h
+++ b/content/browser/android/ime_adapter_android.h
@@ -14,11 +14,11 @@
 #include "content/common/content_export.h"
 #include "ui/gfx/geometry/rect_f.h"
 
-namespace blink {
+namespace ui {
 
-struct WebCompositionUnderline;
+struct CompositionUnderline;
 
-}  // namespace blink
+}  // namespace ui
 
 namespace content {
 
@@ -113,7 +113,7 @@
  private:
   RenderWidgetHostImpl* GetFocusedWidget();
   RenderFrameHost* GetFocusedFrame();
-  std::vector<blink::WebCompositionUnderline> GetUnderlinesFromSpans(
+  std::vector<ui::CompositionUnderline> GetUnderlinesFromSpans(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& obj,
       const base::android::JavaParamRef<jobject>& text,
diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc
index 7e01f32..4889010 100644
--- a/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -60,6 +60,20 @@
 
 namespace content {
 
+namespace {
+
+std::vector<ui::CompositionUnderline> ConvertToUiUnderline(
+    const std::vector<blink::WebCompositionUnderline>& underlines) {
+  std::vector<ui::CompositionUnderline> ui_underlines;
+  for (const auto& underline : underlines) {
+    ui_underlines.emplace_back(ui::CompositionUnderline(
+        underline.start_offset, underline.end_offset, underline.color,
+        underline.thick, underline.background_color));
+  }
+  return ui_underlines;
+}
+};  // namespace
+
 class BrowserPluginGuest::EmbedderVisibilityObserver
     : public WebContentsObserver {
  public:
@@ -226,7 +240,7 @@
     static_cast<RenderViewHostImpl*>(RenderViewHost::From(rwh))
         ->SetInitialFocus(focus_type == blink::kWebFocusTypeBackward);
   }
-  rwh->Send(new InputMsg_SetFocus(rwh->GetRoutingID(), focused));
+  RenderWidgetHostImpl::From(rwh)->GetWidgetInputHandler()->SetFocus(focused);
   if (!focused && mouse_locked_)
     OnUnlockMouse();
 
@@ -680,7 +694,9 @@
   RenderViewHost* rvh = GetWebContents()->GetRenderViewHost();
   // TODO(fsamuel): Investigate whether it's possible to update state earlier
   // here (see http://crbug.com/158151).
-  Send(new InputMsg_SetFocus(routing_id(), focused_));
+  RenderWidgetHostImpl::From(rvh->GetWidget())
+      ->GetWidgetInputHandler()
+      ->SetFocus(focused_);
   UpdateVisibility();
 
   // In case we've created a new guest render process after a crash, let the
@@ -907,7 +923,8 @@
 
 void BrowserPluginGuest::OnExecuteEditCommand(int browser_plugin_instance_id,
                                               const std::string& name) {
-  RenderFrameHost* focused_frame = web_contents()->GetFocusedFrame();
+  RenderFrameHostImpl* focused_frame =
+      static_cast<RenderFrameHostImpl*>(web_contents()->GetFocusedFrame());
   if (!focused_frame)
     return;
 
@@ -918,9 +935,14 @@
 void BrowserPluginGuest::OnImeSetComposition(
     int browser_plugin_instance_id,
     const BrowserPluginHostMsg_SetComposition_Params& params) {
-  Send(new InputMsg_ImeSetComposition(
-      routing_id(), params.text, params.underlines, params.replacement_range,
-      params.selection_start, params.selection_end));
+  std::vector<ui::CompositionUnderline> ui_underlines =
+      ConvertToUiUnderline(params.underlines);
+  GetWebContents()
+      ->GetRenderViewHost()
+      ->GetWidget()
+      ->GetWidgetInputHandler()
+      ->ImeSetComposition(params.text, ui_underlines, params.replacement_range,
+                          params.selection_start, params.selection_end);
 }
 
 void BrowserPluginGuest::OnImeCommitText(
@@ -929,15 +951,25 @@
     const std::vector<blink::WebCompositionUnderline>& underlines,
     const gfx::Range& replacement_range,
     int relative_cursor_pos) {
-  Send(new InputMsg_ImeCommitText(routing_id(), text, underlines,
-                                  replacement_range, relative_cursor_pos));
+  std::vector<ui::CompositionUnderline> ui_underlines =
+      ConvertToUiUnderline(underlines);
+  GetWebContents()
+      ->GetRenderViewHost()
+      ->GetWidget()
+      ->GetWidgetInputHandler()
+      ->ImeCommitText(text, ui_underlines, replacement_range,
+                      relative_cursor_pos);
 }
 
 void BrowserPluginGuest::OnImeFinishComposingText(
     int browser_plugin_instance_id,
     bool keep_selection) {
   DCHECK_EQ(browser_plugin_instance_id_, browser_plugin_instance_id);
-  Send(new InputMsg_ImeFinishComposingText(routing_id(), keep_selection));
+  GetWebContents()
+      ->GetRenderViewHost()
+      ->GetWidget()
+      ->GetWidgetInputHandler()
+      ->ImeFinishComposingText(keep_selection);
 }
 
 void BrowserPluginGuest::OnExtendSelectionAndDelete(
@@ -990,8 +1022,11 @@
 void BrowserPluginGuest::OnSetEditCommandsForNextKeyEvent(
     int browser_plugin_instance_id,
     const std::vector<EditCommand>& edit_commands) {
-  Send(new InputMsg_SetEditCommandsForNextKeyEvent(routing_id(),
-                                                   edit_commands));
+  GetWebContents()
+      ->GetRenderViewHost()
+      ->GetWidget()
+      ->GetWidgetInputHandler()
+      ->SetEditCommandsForNextKeyEvent(edit_commands);
 }
 
 void BrowserPluginGuest::OnSetVisibility(int browser_plugin_instance_id,
diff --git a/content/browser/frame_host/input/legacy_ipc_frame_input_handler.cc b/content/browser/frame_host/input/legacy_ipc_frame_input_handler.cc
index 51dc7f1..849d9c1 100644
--- a/content/browser/frame_host/input/legacy_ipc_frame_input_handler.cc
+++ b/content/browser/frame_host/input/legacy_ipc_frame_input_handler.cc
@@ -12,11 +12,8 @@
 namespace content {
 
 LegacyIPCFrameInputHandler::LegacyIPCFrameInputHandler(
-    RenderFrameHostImpl* frame_host,
-    int routing_id)
-    : frame_host_(frame_host), routing_id_(routing_id) {
-  DCHECK(frame_host);
-}
+    RenderFrameHostImpl* frame_host)
+    : frame_host_(frame_host), routing_id_(frame_host->GetRoutingID()) {}
 
 LegacyIPCFrameInputHandler::~LegacyIPCFrameInputHandler() {}
 
@@ -138,6 +135,16 @@
       base::MakeUnique<InputMsg_MoveRangeSelectionExtent>(routing_id_, extent));
 }
 
+void LegacyIPCFrameInputHandler::ScrollFocusedEditableNodeIntoRect(
+    const gfx::Rect& rect) {
+  SendInput(base::MakeUnique<InputMsg_ScrollFocusedEditableNodeIntoRect>(
+      routing_id_, rect));
+}
+
+void LegacyIPCFrameInputHandler::MoveCaret(const gfx::Point& point) {
+  SendInput(base::MakeUnique<InputMsg_MoveCaret>(routing_id_, point));
+}
+
 void LegacyIPCFrameInputHandler::SendInput(
     std::unique_ptr<IPC::Message> message) {
   static_cast<LegacyInputRouterImpl*>(
diff --git a/content/browser/frame_host/input/legacy_ipc_frame_input_handler.h b/content/browser/frame_host/input/legacy_ipc_frame_input_handler.h
index 6ea79e8..7a10e51 100644
--- a/content/browser/frame_host/input/legacy_ipc_frame_input_handler.h
+++ b/content/browser/frame_host/input/legacy_ipc_frame_input_handler.h
@@ -17,9 +17,10 @@
 class CONTENT_EXPORT LegacyIPCFrameInputHandler
     : public mojom::FrameInputHandler {
  public:
-  LegacyIPCFrameInputHandler(RenderFrameHostImpl* frame_host, int routing_id);
+  explicit LegacyIPCFrameInputHandler(RenderFrameHostImpl* frame_host);
   ~LegacyIPCFrameInputHandler() override;
 
+  // mojom::FrameInputHandler overrides.
   void SetCompositionFromExistingText(
       int32_t start,
       int32_t end,
@@ -46,6 +47,8 @@
   void SelectRange(const gfx::Point& base, const gfx::Point& extent) override;
   void AdjustSelectionByCharacterOffset(int32_t start, int32_t end) override;
   void MoveRangeSelectionExtent(const gfx::Point& extent) override;
+  void ScrollFocusedEditableNodeIntoRect(const gfx::Rect& rect) override;
+  void MoveCaret(const gfx::Point& point) override;
 
  private:
   void SendInput(std::unique_ptr<IPC::Message> message);
diff --git a/content/browser/frame_host/interstitial_page_impl.cc b/content/browser/frame_host/interstitial_page_impl.cc
index d41d52b..96c4267 100644
--- a/content/browser/frame_host/interstitial_page_impl.cc
+++ b/content/browser/frame_host/interstitial_page_impl.cc
@@ -442,6 +442,18 @@
   RecordAction(base::UserMetricsAction("Cut"));
 }
 
+void InterstitialPageImpl::ExecuteEditCommand(
+    const std::string& command,
+    const base::Optional<base::string16>& value) {
+  FrameTreeNode* focused_node = frame_tree_->GetFocusedFrame();
+  if (!focused_node)
+    return;
+
+  focused_node->current_frame_host()
+      ->GetFrameInputHandler()
+      ->ExecuteEditCommand(command, value);
+}
+
 void InterstitialPageImpl::Copy() {
   FrameTreeNode* focused_node = frame_tree_->GetFocusedFrame();
   if (!focused_node)
diff --git a/content/browser/frame_host/interstitial_page_impl.h b/content/browser/frame_host/interstitial_page_impl.h
index 2fd048a..cbab206 100644
--- a/content/browser/frame_host/interstitial_page_impl.h
+++ b/content/browser/frame_host/interstitial_page_impl.h
@@ -115,6 +115,8 @@
                    base::i18n::TextDirection title_direction) override;
   InterstitialPage* GetAsInterstitialPage() override;
   AccessibilityMode GetAccessibilityMode() const override;
+  void ExecuteEditCommand(const std::string& command,
+                          const base::Optional<base::string16>& value) override;
   void Cut() override;
   void Copy() override;
   void Paste() override;
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 1f3d428..0a39d52 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -786,11 +786,7 @@
 }
 
 bool RenderFrameHostImpl::Send(IPC::Message* message) {
-  if (IPC_MESSAGE_ID_CLASS(message->type()) == InputMsgStart) {
-    return GetRenderWidgetHost()->input_router()->SendInput(
-        base::WrapUnique(message));
-  }
-
+  DCHECK(IPC_MESSAGE_ID_CLASS(message->type()) != InputMsgStart);
   return GetProcess()->Send(message);
 }
 
@@ -3333,8 +3329,7 @@
   if (base::FeatureList::IsEnabled(features::kMojoInputMessages)) {
     GetRemoteInterfaces()->GetInterface(&frame_input_handler_);
   } else {
-    legacy_frame_input_handler_.reset(
-        new LegacyIPCFrameInputHandler(this, routing_id_));
+    legacy_frame_input_handler_.reset(new LegacyIPCFrameInputHandler(this));
   }
 }
 
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index b326ec43..0ee5e67 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -40,6 +40,7 @@
 #include "content/common/frame_message_enums.h"
 #include "content/common/frame_replication_state.h"
 #include "content/common/image_downloader/image_downloader.mojom.h"
+#include "content/common/input/input_handler.mojom.h"
 #include "content/common/navigation_params.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/common/javascript_dialog_type.h"
@@ -231,7 +232,7 @@
       GURL* blocked_url,
       SourceLocation* source_location) const override;
 
-  mojom::FrameInputHandler* GetFrameInputHandler() override;
+  mojom::FrameInputHandler* GetFrameInputHandler();
 
   // Creates a RenderFrame in the renderer process.
   bool CreateRenderFrame(int proxy_routing_id,
diff --git a/content/browser/frame_host/render_frame_host_manager_browsertest.cc b/content/browser/frame_host/render_frame_host_manager_browsertest.cc
index e6e38c2..de272050 100644
--- a/content/browser/frame_host/render_frame_host_manager_browsertest.cc
+++ b/content/browser/frame_host/render_frame_host_manager_browsertest.cc
@@ -2655,7 +2655,7 @@
   // message.
   RenderProcessHostWatcher watcher(
       rvh->GetProcess(), RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
-  rvh->Send(new InputMsg_SetFocus(rvh->GetRoutingID(), true));
+  rvh->GetWidget()->GetWidgetInputHandler()->SetFocus(true);
 
   // The test must wait for a process to exit, but if the IPC message is
   // properly ignored, there will be no crash. Therefore, navigate the
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc b/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc
index ceb9813..f85b047 100644
--- a/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc
+++ b/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc
@@ -47,6 +47,10 @@
   MockRenderWidgetHostDelegate() {}
   ~MockRenderWidgetHostDelegate() override {}
  private:
+  void ExecuteEditCommand(
+      const std::string& command,
+      const base::Optional<base::string16>& value) override {}
+
   void Cut() override {}
   void Copy() override {}
   void Paste() override {}
diff --git a/content/browser/frame_host/render_widget_host_view_guest_unittest.cc b/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
index 0453cdd2..2e2a4cd0 100644
--- a/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
+++ b/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
@@ -41,6 +41,9 @@
 
  private:
   // RenderWidgetHostDelegate:
+  void ExecuteEditCommand(
+      const std::string& command,
+      const base::Optional<base::string16>& value) override {}
   void Cut() override {}
   void Copy() override {}
   void Paste() override {}
diff --git a/content/browser/renderer_host/input/input_router.h b/content/browser/renderer_host/input/input_router.h
index d26541b..47e3b0c 100644
--- a/content/browser/renderer_host/input/input_router.h
+++ b/content/browser/renderer_host/input/input_router.h
@@ -30,11 +30,6 @@
 
   ~InputRouter() override {}
 
-  // Send and take ownership of the the given InputMsg_*. This should be used
-  // only for event types not associated with a WebInputEvent.  Returns true on
-  // success and false otherwise.
-  virtual bool SendInput(std::unique_ptr<IPC::Message> message) = 0;
-
   // WebInputEvents
   virtual void SendMouseEvent(
       const MouseEventWithLatencyInfo& mouse_event) = 0;
diff --git a/content/browser/renderer_host/input/legacy_input_router_impl.h b/content/browser/renderer_host/input/legacy_input_router_impl.h
index a285754..bd3189b 100644
--- a/content/browser/renderer_host/input/legacy_input_router_impl.h
+++ b/content/browser/renderer_host/input/legacy_input_router_impl.h
@@ -58,8 +58,9 @@
                         const Config& config);
   ~LegacyInputRouterImpl() override;
 
+  bool SendInput(std::unique_ptr<IPC::Message> message);
+
   // InputRouter
-  bool SendInput(std::unique_ptr<IPC::Message> message) override;
   void SendMouseEvent(const MouseEventWithLatencyInfo& mouse_event) override;
   void SendWheelEvent(
       const MouseWheelEventWithLatencyInfo& wheel_event) override;
@@ -80,6 +81,8 @@
 
   cc::TouchAction AllowedTouchAction() override;
 
+  int routing_id() const { return routing_id_; }
+
  private:
   friend class LegacyInputRouterImplTest;
   FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
@@ -194,8 +197,6 @@
   // non-zero touch timeout configuration.
   void UpdateTouchAckTimeoutEnabled();
 
-  int routing_id() const { return routing_id_; }
-
   IPC::Sender* sender_;
   InputRouterClient* client_;
   InputAckHandler* ack_handler_;
diff --git a/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.cc b/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.cc
new file mode 100644
index 0000000..fa69e4ad
--- /dev/null
+++ b/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.cc
@@ -0,0 +1,117 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/legacy_ipc_widget_input_handler.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "content/browser/renderer_host/input/legacy_input_router_impl.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/common/input_messages.h"
+
+namespace content {
+
+namespace {
+std::vector<blink::WebCompositionUnderline> ConvertToBlinkUnderline(
+    const std::vector<ui::CompositionUnderline>& ui_underlines) {
+  std::vector<blink::WebCompositionUnderline> underlines;
+  for (const auto& underline : ui_underlines) {
+    underlines.emplace_back(blink::WebCompositionUnderline(
+        underline.start_offset, underline.end_offset, underline.color,
+        underline.thick, underline.background_color));
+  }
+  return underlines;
+}
+
+}  // namespace
+
+LegacyIPCWidgetInputHandler::LegacyIPCWidgetInputHandler(
+    LegacyInputRouterImpl* input_router)
+    : input_router_(input_router) {}
+
+LegacyIPCWidgetInputHandler::~LegacyIPCWidgetInputHandler() {}
+
+void LegacyIPCWidgetInputHandler::SetFocus(bool focused) {
+  SendInput(base::MakeUnique<InputMsg_SetFocus>(input_router_->routing_id(),
+                                                focused));
+}
+
+void LegacyIPCWidgetInputHandler::MouseCaptureLost() {}
+
+void LegacyIPCWidgetInputHandler::SetEditCommandsForNextKeyEvent(
+    const std::vector<EditCommand>& commands) {
+  SendInput(base::MakeUnique<InputMsg_SetEditCommandsForNextKeyEvent>(
+      input_router_->routing_id(), commands));
+}
+
+void LegacyIPCWidgetInputHandler::CursorVisibilityChanged(bool visible) {
+  SendInput(base::MakeUnique<InputMsg_CursorVisibilityChange>(
+      input_router_->routing_id(), visible));
+}
+
+void LegacyIPCWidgetInputHandler::ImeSetComposition(
+    const base::string16& text,
+    const std::vector<ui::CompositionUnderline>& ui_underlines,
+    const gfx::Range& range,
+    int32_t start,
+    int32_t end) {
+  std::vector<blink::WebCompositionUnderline> underlines =
+      ConvertToBlinkUnderline(ui_underlines);
+  SendInput(base::MakeUnique<InputMsg_ImeSetComposition>(
+      input_router_->routing_id(), text, underlines, range, start, end));
+}
+
+void LegacyIPCWidgetInputHandler::ImeCommitText(
+    const base::string16& text,
+    const std::vector<ui::CompositionUnderline>& ui_underlines,
+    const gfx::Range& range,
+    int32_t relative_cursor_position) {
+  std::vector<blink::WebCompositionUnderline> underlines =
+      ConvertToBlinkUnderline(ui_underlines);
+  SendInput(base::MakeUnique<InputMsg_ImeCommitText>(
+      input_router_->routing_id(), text, underlines, range,
+      relative_cursor_position));
+}
+
+void LegacyIPCWidgetInputHandler::ImeFinishComposingText(bool keep_selection) {
+  SendInput(base::MakeUnique<InputMsg_ImeFinishComposingText>(
+      input_router_->routing_id(), keep_selection));
+}
+void LegacyIPCWidgetInputHandler::RequestTextInputStateUpdate() {
+#if defined(OS_ANDROID)
+  SendInput(base::MakeUnique<InputMsg_RequestTextInputStateUpdate>(
+      input_router_->routing_id()));
+#endif
+}
+
+void LegacyIPCWidgetInputHandler::RequestCompositionUpdates(
+    bool immediate_request,
+    bool monitor_request) {
+  SendInput(base::MakeUnique<InputMsg_RequestCompositionUpdates>(
+      input_router_->routing_id(), immediate_request, monitor_request));
+}
+
+void LegacyIPCWidgetInputHandler::SendInput(
+    std::unique_ptr<IPC::Message> message) {
+  input_router_->SendInput(std::move(message));
+}
+
+void LegacyIPCWidgetInputHandler::DispatchEvent(
+    content::mojom::EventPtr event,
+    DispatchEventCallback callback) {
+  // We only expect these events to be called with the mojo enabled input
+  // channel. The LegacyInputRouterImpl will handle sending the events
+  // directly.
+  NOTREACHED();
+}
+
+void LegacyIPCWidgetInputHandler::DispatchNonBlockingEvent(
+    content::mojom::EventPtr) {
+  // We only expect these events to be called with the mojo enabled input
+  // channel. The LegacyInputRouterImpl will handle sending the events
+  // directly.
+  NOTREACHED();
+}
+
+}  // namespace content
diff --git a/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.h b/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.h
new file mode 100644
index 0000000..af0ee2d
--- /dev/null
+++ b/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.h
@@ -0,0 +1,58 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_LEGACY_IPC_WIDGET_INPUT_HANDLER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_LEGACY_IPC_WIDGET_INPUT_HANDLER_H_
+
+#include "content/common/input/input_handler.mojom.h"
+
+namespace content {
+
+class LegacyInputRouterImpl;
+
+// An instance of a mojom::WidgetInputHandler based on chrome IPC.
+// This class is a temporary class to allow the input messages to
+// remain as Chrome IPC messages but progressively work at moving
+// them to mojo.
+class CONTENT_EXPORT LegacyIPCWidgetInputHandler
+    : public mojom::WidgetInputHandler {
+ public:
+  explicit LegacyIPCWidgetInputHandler(LegacyInputRouterImpl* input_router);
+  ~LegacyIPCWidgetInputHandler() override;
+
+  // mojom::WidgetInputHandler overrides.
+  void SetFocus(bool focused) override;
+  void MouseCaptureLost() override;
+  void SetEditCommandsForNextKeyEvent(
+      const std::vector<EditCommand>& commands) override;
+  void CursorVisibilityChanged(bool visible) override;
+  void ImeSetComposition(
+      const base::string16& text,
+      const std::vector<ui::CompositionUnderline>& underlines,
+      const gfx::Range& range,
+      int32_t start,
+      int32_t end) override;
+  void ImeCommitText(const base::string16& text,
+                     const std::vector<ui::CompositionUnderline>& underlines,
+                     const gfx::Range& range,
+                     int32_t relative_cursor_position) override;
+  void ImeFinishComposingText(bool keep_selection) override;
+  void RequestTextInputStateUpdate() override;
+  void RequestCompositionUpdates(bool immediate_request,
+                                 bool monitor_request) override;
+  void DispatchEvent(content::mojom::EventPtr event,
+                     DispatchEventCallback callback) override;
+  void DispatchNonBlockingEvent(content::mojom::EventPtr) override;
+
+ private:
+  void SendInput(std::unique_ptr<IPC::Message> message);
+
+  LegacyInputRouterImpl* input_router_;
+
+  DISALLOW_COPY_AND_ASSIGN(LegacyIPCWidgetInputHandler);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_RENDERER_HOST_INPUT_LEGACY_IPC_WIDGET_INPUT_HANDLER_H_
diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc b/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
index 199df16..19cc95df2 100644
--- a/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
+++ b/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
@@ -323,9 +323,10 @@
 
 void TouchSelectionControllerClientAura::InternalClient::MoveCaret(
     const gfx::PointF& position) {
-  RenderWidgetHostImpl* host =
-      RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost());
-  host->MoveCaret(gfx::ToRoundedPoint(position));
+  RenderWidgetHostDelegate* host_delegate =
+      RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost())->delegate();
+  if (host_delegate)
+    host_delegate->MoveCaret(gfx::ToRoundedPoint(position));
 }
 
 void TouchSelectionControllerClientAura::MoveRangeSelectionExtent(
diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc b/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc
index 8dcb229..0cd3bf9b 100644
--- a/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc
+++ b/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc
@@ -86,9 +86,10 @@
 
 void TouchSelectionControllerClientChildFrame::MoveCaret(
     const gfx::PointF& position) {
-  RenderWidgetHostImpl* host =
-      RenderWidgetHostImpl::From(rwhv_->GetRenderWidgetHost());
-  host->MoveCaret(ConvertFromRoot(position));
+  RenderWidgetHostDelegate* host_delegate =
+      RenderWidgetHostImpl::From(rwhv_->GetRenderWidgetHost())->delegate();
+  if (host_delegate)
+    host_delegate->MoveCaret(ConvertFromRoot(position));
 }
 
 void TouchSelectionControllerClientChildFrame::MoveRangeSelectionExtent(
diff --git a/content/browser/renderer_host/render_widget_host_delegate.h b/content/browser/renderer_host/render_widget_host_delegate.h
index 8b98a64a..3083f04 100644
--- a/content/browser/renderer_host/render_widget_host_delegate.h
+++ b/content/browser/renderer_host/render_widget_host_delegate.h
@@ -126,6 +126,9 @@
       GetOrCreateRootBrowserAccessibilityManager();
 
   // Send OS Cut/Copy/Paste actions to the focused frame.
+  virtual void ExecuteEditCommand(
+      const std::string& command,
+      const base::Optional<base::string16>& value) = 0;
   virtual void Cut() = 0;
   virtual void Copy() = 0;
   virtual void Paste() = 0;
@@ -138,6 +141,9 @@
   // currently focused frame.
   virtual void SelectRange(const gfx::Point& base, const gfx::Point& extent) {}
 
+  // Request the renderer to Move the caret to the new position.
+  virtual void MoveCaret(const gfx::Point& extent) {}
+
   virtual RenderWidgetHostInputEventRouter* GetInputEventRouter();
 
   // Send page-level focus state to all SiteInstances involved in rendering the
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 2146b973..84d1bc1 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -336,6 +336,8 @@
 
   input_router_.reset(new LegacyInputRouterImpl(
       process_, this, this, routing_id_, GetInputRouterConfigForPlatform()));
+  legacy_widget_input_handler_ = base::MakeUnique<LegacyIPCWidgetInputHandler>(
+      static_cast<LegacyInputRouterImpl*>(input_router_.get()));
 
   touch_emulator_.reset();
 
@@ -591,9 +593,7 @@
 }
 
 bool RenderWidgetHostImpl::Send(IPC::Message* msg) {
-  if (IPC_MESSAGE_ID_CLASS(msg->type()) == InputMsgStart)
-    return input_router_->SendInput(base::WrapUnique(msg));
-
+  DCHECK(IPC_MESSAGE_ID_CLASS(msg->type()) != InputMsgStart);
   return process_->Send(msg);
 }
 
@@ -814,7 +814,7 @@
       touch_emulator_->CancelTouch();
   }
 
-  Send(new InputMsg_SetFocus(routing_id_, focused));
+  GetWidgetInputHandler()->SetFocus(focused);
 
   // Also send page-level focus state to other SiteInstances involved in
   // rendering the current FrameTree.
@@ -826,7 +826,7 @@
   if (touch_emulator_)
     touch_emulator_->CancelTouch();
 
-  Send(new InputMsg_MouseCaptureLost(routing_id_));
+  GetWidgetInputHandler()->MouseCaptureLost();
 
   if (delegate_)
     delegate_->LostCapture(this);
@@ -1303,8 +1303,7 @@
   // InputMsg_HandleInputEvent is, but has to be sent first.
   // https://crbug.com/684298
   if (commands && !commands->empty()) {
-    Send(
-        new InputMsg_SetEditCommandsForNextKeyEvent(GetRoutingID(), *commands));
+    GetWidgetInputHandler()->SetEditCommandsForNextKeyEvent(*commands);
   }
   input_router_->SendKeyboardEvent(key_event_with_latency);
 }
@@ -1336,7 +1335,7 @@
 }
 
 void RenderWidgetHostImpl::SendCursorVisibilityState(bool is_visible) {
-  Send(new InputMsg_CursorVisibilityChange(GetRoutingID(), is_visible));
+  GetWidgetInputHandler()->CursorVisibilityChanged(is_visible);
 }
 
 int64_t RenderWidgetHostImpl::GetLatencyComponentId() const {
@@ -1480,6 +1479,10 @@
   SetCursor(cursor);
 }
 
+mojom::WidgetInputHandler* RenderWidgetHostImpl::GetWidgetInputHandler() {
+  return legacy_widget_input_handler_.get();
+}
+
 void RenderWidgetHostImpl::NotifyScreenInfoChanged() {
   if (delegate_)
     delegate_->ScreenInfoChanged();
@@ -1690,6 +1693,8 @@
   // destroy the aura window, which may dispatch a synthetic mouse move.)
   input_router_.reset(new LegacyInputRouterImpl(
       process_, this, this, routing_id_, GetInputRouterConfigForPlatform()));
+  legacy_widget_input_handler_ = base::MakeUnique<LegacyIPCWidgetInputHandler>(
+      static_cast<LegacyInputRouterImpl*>(input_router_.get()));
 
   synthetic_gesture_controller_.reset();
 
@@ -1718,32 +1723,31 @@
 
 void RenderWidgetHostImpl::ImeSetComposition(
     const base::string16& text,
-    const std::vector<blink::WebCompositionUnderline>& underlines,
+    const std::vector<ui::CompositionUnderline>& underlines,
     const gfx::Range& replacement_range,
     int selection_start,
     int selection_end) {
-  Send(new InputMsg_ImeSetComposition(
-            GetRoutingID(), text, underlines, replacement_range,
-            selection_start, selection_end));
+  GetWidgetInputHandler()->ImeSetComposition(
+      text, underlines, replacement_range, selection_start, selection_end);
 }
 
 void RenderWidgetHostImpl::ImeCommitText(
     const base::string16& text,
-    const std::vector<blink::WebCompositionUnderline>& underlines,
+    const std::vector<ui::CompositionUnderline>& underlines,
     const gfx::Range& replacement_range,
     int relative_cursor_pos) {
-  Send(new InputMsg_ImeCommitText(GetRoutingID(), text, underlines,
-                                  replacement_range, relative_cursor_pos));
+  GetWidgetInputHandler()->ImeCommitText(text, underlines, replacement_range,
+                                         relative_cursor_pos);
 }
 
 void RenderWidgetHostImpl::ImeFinishComposingText(bool keep_selection) {
-  Send(new InputMsg_ImeFinishComposingText(GetRoutingID(), keep_selection));
+  GetWidgetInputHandler()->ImeFinishComposingText(keep_selection);
 }
 
 void RenderWidgetHostImpl::ImeCancelComposition() {
-  Send(new InputMsg_ImeSetComposition(GetRoutingID(), base::string16(),
-            std::vector<blink::WebCompositionUnderline>(),
-            gfx::Range::InvalidRange(), 0, 0));
+  GetWidgetInputHandler()->ImeSetComposition(
+      base::string16(), std::vector<ui::CompositionUnderline>(),
+      gfx::Range::InvalidRange(), 0, 0);
 }
 
 void RenderWidgetHostImpl::RejectMouseLockOrUnlockIfNecessary() {
@@ -2354,7 +2358,9 @@
 
 void RenderWidgetHostImpl::OnSyntheticGestureCompleted(
     SyntheticGesture::Result result) {
-  Send(new InputMsg_SyntheticGestureCompleted(GetRoutingID()));
+  // TODO(dtapuska): Define mojo interface for InputHostMsg's and this will be a
+  // callback for completing InputHostMsg_QueueSyntheticGesture.
+  process_->Send(new InputMsg_SyntheticGestureCompleted(GetRoutingID()));
 }
 
 bool RenderWidgetHostImpl::ShouldDropInputEvents() const {
@@ -2365,20 +2371,6 @@
   Send(new ViewMsg_SetBackgroundOpaque(GetRoutingID(), opaque));
 }
 
-void RenderWidgetHostImpl::ExecuteEditCommand(const std::string& command,
-                                              const std::string& value) {
-  Send(new InputMsg_ExecuteEditCommand(GetRoutingID(), command, value));
-}
-
-void RenderWidgetHostImpl::ScrollFocusedEditableNodeIntoRect(
-    const gfx::Rect& rect) {
-  Send(new InputMsg_ScrollFocusedEditableNodeIntoRect(GetRoutingID(), rect));
-}
-
-void RenderWidgetHostImpl::MoveCaret(const gfx::Point& point) {
-  Send(new InputMsg_MoveCaret(GetRoutingID(), point));
-}
-
 bool RenderWidgetHostImpl::GotResponseToLockMouseRequest(bool allowed) {
   if (!allowed) {
     RejectMouseLockOrUnlockIfNecessary();
@@ -2557,8 +2549,8 @@
   if (!immediate_request && monitor_updates == monitoring_composition_info_)
     return;
   monitoring_composition_info_ = monitor_updates;
-  Send(new InputMsg_RequestCompositionUpdates(routing_id_, immediate_request,
-                                              monitor_updates));
+  GetWidgetInputHandler()->RequestCompositionUpdates(immediate_request,
+                                                     monitor_updates);
 }
 
 void RenderWidgetHostImpl::RequestCompositorFrameSink(
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h
index 62299ad..87deb32f 100644
--- a/content/browser/renderer_host/render_widget_host_impl.h
+++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -31,6 +31,7 @@
 #include "content/browser/renderer_host/event_with_latency_info.h"
 #include "content/browser/renderer_host/input/input_ack_handler.h"
 #include "content/browser/renderer_host/input/input_router_client.h"
+#include "content/browser/renderer_host/input/legacy_ipc_widget_input_handler.h"
 #include "content/browser/renderer_host/input/render_widget_host_latency_tracker.h"
 #include "content/browser/renderer_host/input/synthetic_gesture.h"
 #include "content/browser/renderer_host/input/synthetic_gesture_controller.h"
@@ -39,6 +40,7 @@
 #include "content/browser/renderer_host/render_widget_host_view_base.h"
 #include "content/common/drag_event_source_info.h"
 #include "content/common/input/input_event_ack_state.h"
+#include "content/common/input/input_handler.mojom.h"
 #include "content/common/input/synthetic_gesture_packet.h"
 #include "content/common/render_widget_surface_properties.h"
 #include "content/common/view_message_enums.h"
@@ -67,7 +69,6 @@
 namespace blink {
 class WebInputEvent;
 class WebMouseEvent;
-struct WebCompositionUnderline;
 }
 
 namespace cc {
@@ -209,6 +210,7 @@
   void DragSourceSystemDragEnded() override;
   void FilterDropData(DropData* drop_data) override;
   void SetCursor(const CursorInfo& cursor_info) override;
+  mojom::WidgetInputHandler* GetWidgetInputHandler();
 
   // Notification that the screen info has changed.
   void NotifyScreenInfoChanged();
@@ -411,7 +413,7 @@
   // * when markedText of NSTextInput is called (on Mac).
   void ImeSetComposition(
       const base::string16& text,
-      const std::vector<blink::WebCompositionUnderline>& underlines,
+      const std::vector<ui::CompositionUnderline>& underlines,
       const gfx::Range& replacement_range,
       int selection_start,
       int selection_end);
@@ -423,11 +425,10 @@
   //   (on Windows);
   // * when it receives a "commit" signal of GtkIMContext (on Linux);
   // * when insertText of NSTextInput is called (on Mac).
-  void ImeCommitText(
-      const base::string16& text,
-      const std::vector<blink::WebCompositionUnderline>& underlines,
-      const gfx::Range& replacement_range,
-      int relative_cursor_pos);
+  void ImeCommitText(const base::string16& text,
+                     const std::vector<ui::CompositionUnderline>& underlines,
+                     const gfx::Range& replacement_range,
+                     int relative_cursor_pos);
 
   // Finishes an ongoing composition.
   // A browser should call this function or ImeCommitText:
@@ -452,18 +453,6 @@
   // Set the RenderView background transparency.
   void SetBackgroundOpaque(bool opaque);
 
-  // Executes the edit command.
-  void ExecuteEditCommand(const std::string& command,
-                          const std::string& value);
-
-  // Tells the renderer to scroll the currently focused node into rect only if
-  // the currently focused node is a Text node (textfield, text area or content
-  // editable divs).
-  void ScrollFocusedEditableNodeIntoRect(const gfx::Rect& rect);
-
-  // Requests the renderer to move the caret selection towards the point.
-  void MoveCaret(const gfx::Point& point);
-
   // Called when the reponse to a pending mouse lock request has arrived.
   // Returns true if |allowed| is true and the mouse has been successfully
   // locked.
@@ -992,6 +981,8 @@
   // Sorted by frame token.
   std::queue<std::pair<uint32_t, std::vector<IPC::Message>>> queued_messages_;
 
+  std::unique_ptr<LegacyIPCWidgetInputHandler> legacy_widget_input_handler_;
+
   base::WeakPtrFactory<RenderWidgetHostImpl> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostImpl);
diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc
index ded5ede..e342df3 100644
--- a/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -94,22 +94,16 @@
 class MockInputRouter : public InputRouter {
  public:
   explicit MockInputRouter(InputRouterClient* client)
-      : send_event_called_(false),
-        sent_mouse_event_(false),
+      : sent_mouse_event_(false),
         sent_wheel_event_(false),
         sent_keyboard_event_(false),
         sent_gesture_event_(false),
         send_touch_event_not_cancelled_(false),
         message_received_(false),
-        client_(client) {
-  }
+        client_(client) {}
   ~MockInputRouter() override {}
 
   // InputRouter
-  bool SendInput(std::unique_ptr<IPC::Message> message) override {
-    send_event_called_ = true;
-    return true;
-  }
   void SendMouseEvent(const MouseEventWithLatencyInfo& mouse_event) override {
     sent_mouse_event_ = true;
   }
@@ -146,7 +140,6 @@
     return false;
   }
 
-  bool send_event_called_;
   bool sent_mouse_event_;
   bool sent_wheel_event_;
   bool sent_keyboard_event_;
@@ -205,6 +198,9 @@
   void DisableGestureDebounce() {
     input_router_.reset(new LegacyInputRouterImpl(
         process_, this, this, routing_id_, InputRouter::Config()));
+    legacy_widget_input_handler_ =
+        base::MakeUnique<LegacyIPCWidgetInputHandler>(
+            static_cast<LegacyInputRouterImpl*>(input_router_.get()));
   }
 
   WebInputEvent::Type acked_touch_event_type() const {
@@ -213,6 +209,9 @@
 
   void SetupForInputRouterTest() {
     input_router_.reset(new MockInputRouter(this));
+    legacy_widget_input_handler_ =
+        base::MakeUnique<LegacyIPCWidgetInputHandler>(
+            static_cast<LegacyInputRouterImpl*>(input_router_.get()));
   }
 
   MockInputRouter* mock_input_router() {
@@ -487,6 +486,10 @@
     unresponsive_timer_fired_ = true;
   }
 
+  void ExecuteEditCommand(
+      const std::string& command,
+      const base::Optional<base::string16>& value) override {}
+
   void Cut() override {}
   void Copy() override {}
   void Paste() override {}
@@ -1682,54 +1685,6 @@
   EXPECT_EQ(0U, process_->sink().message_count());
 }
 
-#define TEST_InputRouterRoutes_NOARGS(INPUTMSG) \
-  TEST_F(RenderWidgetHostTest, InputRouterRoutes##INPUTMSG) { \
-    host_->SetupForInputRouterTest(); \
-    host_->INPUTMSG(); \
-    EXPECT_TRUE(host_->mock_input_router()->send_event_called_); \
-  }
-
-TEST_InputRouterRoutes_NOARGS(Focus);
-TEST_InputRouterRoutes_NOARGS(Blur);
-TEST_InputRouterRoutes_NOARGS(LostCapture);
-
-#undef TEST_InputRouterRoutes_NOARGS
-
-#define TEST_InputRouterRoutes_NOARGS_FromRFH(INPUTMSG) \
-  TEST_F(RenderWidgetHostTest, InputRouterRoutes##INPUTMSG) { \
-    host_->SetupForInputRouterTest(); \
-    host_->Send(new INPUTMSG(host_->GetRoutingID())); \
-    EXPECT_TRUE(host_->mock_input_router()->send_event_called_); \
-  }
-
-TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_Undo);
-TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_Redo);
-TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_Cut);
-TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_Copy);
-#if defined(OS_MACOSX)
-TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_CopyToFindPboard);
-#endif
-TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_Paste);
-TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_PasteAndMatchStyle);
-TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_Delete);
-TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_SelectAll);
-TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_CollapseSelection);
-
-#undef TEST_InputRouterRoutes_NOARGS_FromRFH
-
-TEST_F(RenderWidgetHostTest, InputRouterRoutesReplace) {
-  host_->SetupForInputRouterTest();
-  host_->Send(new InputMsg_Replace(host_->GetRoutingID(), base::string16()));
-  EXPECT_TRUE(host_->mock_input_router()->send_event_called_);
-}
-
-TEST_F(RenderWidgetHostTest, InputRouterRoutesReplaceMisspelling) {
-  host_->SetupForInputRouterTest();
-  host_->Send(new InputMsg_ReplaceMisspelling(host_->GetRoutingID(),
-                                              base::string16()));
-  EXPECT_TRUE(host_->mock_input_router()->send_event_called_);
-}
-
 TEST_F(RenderWidgetHostTest, IgnoreInputEvent) {
   host_->SetupForInputRouterTest();
 
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index b11b0aa..d4b5e98 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -1955,8 +1955,8 @@
 }
 
 void RenderWidgetHostViewAndroid::MoveCaret(const gfx::Point& point) {
-  if (host_)
-    host_->MoveCaret(point);
+  if (host_ && host_->delegate())
+    host_->delegate()->MoveCaret(point);
 }
 
 void RenderWidgetHostViewAndroid::ShowContextMenuAtPoint(
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index 2c426e7..a6c969f 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -145,15 +145,15 @@
 // is obscured by the on screen keyboard.
 class WinScreenKeyboardObserver : public ui::OnScreenKeyboardObserver {
  public:
-  WinScreenKeyboardObserver(RenderWidgetHostImpl* host,
+  WinScreenKeyboardObserver(RenderWidgetHostViewAura* host_view,
                             const gfx::Point& location_in_screen,
                             float scale_factor,
                             aura::Window* window)
-      : host_(host),
+      : host_view_(host_view),
         location_in_screen_(location_in_screen),
         device_scale_factor_(scale_factor),
         window_(window) {
-    host_->GetView()->SetInsets(gfx::Insets());
+    host_view_->SetInsets(gfx::Insets());
   }
 
   // base::win::OnScreenKeyboardObserver overrides.
@@ -162,7 +162,7 @@
         gfx::ConvertPointToPixel(device_scale_factor_, location_in_screen_);
 
     // Restore the viewport.
-    host_->GetView()->SetInsets(gfx::Insets());
+    host_view_->SetInsets(gfx::Insets());
 
     if (keyboard_rect_pixels.Contains(location_in_pixels)) {
       aura::client::ScreenPositionClient* screen_position_client =
@@ -187,7 +187,7 @@
       if (viewport_bottom > bounds_in_screen.height())
         return;
 
-      host_->GetView()->SetInsets(gfx::Insets(0, 0, viewport_bottom, 0));
+      host_view_->SetInsets(gfx::Insets(0, 0, viewport_bottom, 0));
 
       gfx::Point origin(location_in_screen_);
       screen_position_client->ConvertPointFromScreen(window_, &origin);
@@ -197,17 +197,18 @@
       // We want to scroll the node into a rectangle which originates from
       // the touch point and a small offset (10) in either direction.
       gfx::Rect node_rect(origin.x(), origin.y(), 10, 10);
-      host_->ScrollFocusedEditableNodeIntoRect(node_rect);
+
+      host_view_->ScrollFocusedEditableNodeIntoRect(node_rect);
     }
   }
 
   void OnKeyboardHidden(const gfx::Rect& keyboard_rect_pixels) override {
     // Restore the viewport.
-    host_->GetView()->SetInsets(gfx::Insets());
+    host_view_->SetInsets(gfx::Insets());
   }
 
  private:
-  RenderWidgetHostImpl* host_;
+  RenderWidgetHostViewAura* host_view_;
   // The location in DIPs where the touch occurred.
   gfx::Point location_in_screen_;
   // The current device scale factor.
@@ -770,7 +771,7 @@
   DCHECK(osk_display_manager);
   if (editable && host_->GetView() && host_->delegate()) {
     keyboard_observer_.reset(new WinScreenKeyboardObserver(
-        host_, location_dips_screen, device_scale_factor_, window_));
+        this, location_dips_screen, device_scale_factor_, window_));
     virtual_keyboard_requested_ =
         osk_display_manager->DisplayVirtualKeyboard(keyboard_observer_.get());
   } else {
@@ -1168,25 +1169,10 @@
   if (!text_input_manager_ || !text_input_manager_->GetActiveWidget())
     return;
 
-  // TODO(suzhe): convert both renderer_host and renderer to use
-  // ui::CompositionText.
-  std::vector<blink::WebCompositionUnderline> underlines;
-  underlines.reserve(composition.underlines.size());
-  for (std::vector<ui::CompositionUnderline>::const_iterator it =
-           composition.underlines.begin();
-       it != composition.underlines.end(); ++it) {
-    underlines.push_back(
-        blink::WebCompositionUnderline(static_cast<unsigned>(it->start_offset),
-                                       static_cast<unsigned>(it->end_offset),
-                                       it->color,
-                                       it->thick,
-                                       it->background_color));
-  }
-
   // TODO(suzhe): due to a bug of webkit, we can't use selection range with
   // composition string. See: https://bugs.webkit.org/show_bug.cgi?id=37788
   text_input_manager_->GetActiveWidget()->ImeSetComposition(
-      composition.text, underlines, gfx::Range::InvalidRange(),
+      composition.text, composition.underlines, gfx::Range::InvalidRange(),
       composition.selection.end(), composition.selection.end());
 
   has_composition_text_ = !composition.text.empty();
@@ -1213,7 +1199,7 @@
   if (text_input_manager_ && text_input_manager_->GetActiveWidget()) {
     if (text.length())
       text_input_manager_->GetActiveWidget()->ImeCommitText(
-          text, std::vector<blink::WebCompositionUnderline>(),
+          text, std::vector<ui::CompositionUnderline>(),
           gfx::Range::InvalidRange(), 0);
     else if (has_composition_text_)
       text_input_manager_->GetActiveWidget()->ImeFinishComposingText(false);
@@ -1443,7 +1429,7 @@
       window_->GetBoundsInScreen(), hidden_window_bounds_in_screen);
   visible_area_in_local_space =
       ConvertRectFromScreen(visible_area_in_local_space);
-  host_->ScrollFocusedEditableNodeIntoRect(visible_area_in_local_space);
+  ScrollFocusedEditableNodeIntoRect(visible_area_in_local_space);
 }
 
 bool RenderWidgetHostViewAura::IsTextEditCommandEnabled(
@@ -2421,4 +2407,12 @@
   delegated_frame_host_->SetNeedsBeginFrames(needs_begin_frames_);
 }
 
+void RenderWidgetHostViewAura::ScrollFocusedEditableNodeIntoRect(
+    const gfx::Rect& node_rect) {
+  RenderFrameHostImpl* rfh = GetFocusedFrame();
+  if (rfh) {
+    rfh->GetFrameInputHandler()->ScrollFocusedEditableNodeIntoRect(node_rect);
+  }
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index 3db5e41..9c4f3d4 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -332,6 +332,8 @@
     return event_handler_.get();
   }
 
+  void ScrollFocusedEditableNodeIntoRect(const gfx::Rect& rect);
+
  protected:
   ~RenderWidgetHostViewAura() override;
 
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index 72315fe..2e142be 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -243,6 +243,9 @@
     last_event_.reset(new NativeWebKeyboardEvent(event));
     return pre_handle_keyboard_event_result_;
   }
+  void ExecuteEditCommand(
+      const std::string& command,
+      const base::Optional<base::string16>& value) override {}
   void Cut() override {}
   void Copy() override {}
   void Paste() override {}
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h
index 9dcacd2..031508c 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.h
+++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -32,12 +32,12 @@
 #include "content/common/cursors/webcursor.h"
 #include "content/common/edit_command.h"
 #include "ipc/ipc_sender.h"
-#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
 #include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
 #include "ui/accelerated_widget_mac/display_link_mac.h"
 #import "ui/base/cocoa/command_dispatcher.h"
 #include "ui/base/cocoa/remote_layer_api.h"
 #import "ui/base/cocoa/tool_tip_base_view.h"
+#include "ui/base/ime/composition_underline.h"
 #include "ui/display/display_observer.h"
 
 namespace content {
@@ -124,7 +124,7 @@
   NSRange markedTextSelectedRange_;
 
   // Underline information of the |markedText_|.
-  std::vector<blink::WebCompositionUnderline> underlines_;
+  std::vector<ui::CompositionUnderline> underlines_;
 
   // Replacement range information received from |setMarkedText:|.
   gfx::Range setMarkedTextReplacementRange_;
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index 18561991..1c48e6b 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -279,9 +279,8 @@
 
 // Extract underline information from an attributed string. Mostly copied from
 // third_party/WebKit/Source/WebKit/mac/WebView/WebHTMLView.mm
-void ExtractUnderlines(
-    NSAttributedString* string,
-    std::vector<blink::WebCompositionUnderline>* underlines) {
+void ExtractUnderlines(NSAttributedString* string,
+                       std::vector<ui::CompositionUnderline>* underlines) {
   int length = [[string string] length];
   int i = 0;
   while (i < length) {
@@ -297,11 +296,8 @@
             [colorAttr colorUsingColorSpaceName:NSDeviceRGBColorSpace]);
       }
       underlines->push_back(
-          blink::WebCompositionUnderline(range.location,
-                                         NSMaxRange(range),
-                                         color,
-                                         [style intValue] > 1,
-                                         SK_ColorTRANSPARENT));
+          ui::CompositionUnderline(range.location, NSMaxRange(range), color,
+                                   [style intValue] > 1, SK_ColorTRANSPARENT));
     }
     i = range.location + range.length;
   }
@@ -2244,7 +2240,7 @@
   if (textToBeInserted_.length() >
       ((hasMarkedText_ || oldHasMarkedText) ? 0u : 1u)) {
     widgetHost->ImeCommitText(textToBeInserted_,
-                              std::vector<blink::WebCompositionUnderline>(),
+                              std::vector<ui::CompositionUnderline>(),
                               gfx::Range::InvalidRange(), 0);
     textInserted = YES;
   }
@@ -3263,8 +3259,8 @@
     ExtractUnderlines(string, &underlines_);
   } else {
     // Use a thin black underline by default.
-    underlines_.push_back(blink::WebCompositionUnderline(
-        0, length, SK_ColorBLACK, false, SK_ColorTRANSPARENT));
+    underlines_.push_back(ui::CompositionUnderline(0, length, SK_ColorBLACK,
+                                                   false, SK_ColorTRANSPARENT));
   }
 
   // If we are handling a key down event, then SetComposition() will be
@@ -3307,9 +3303,10 @@
                           base::CompareCase::INSENSITIVE_ASCII))
       editCommands_.push_back(EditCommand(command, ""));
   } else {
-    RenderWidgetHostImpl* rwh = renderWidgetHostView_->render_widget_host_;
-    rwh->Send(new InputMsg_ExecuteEditCommand(rwh->GetRoutingID(),
-                                              command, ""));
+    if (renderWidgetHostView_->render_widget_host_->delegate()) {
+      renderWidgetHostView_->render_widget_host_->delegate()
+          ->ExecuteEditCommand(command, base::nullopt);
+    }
   }
 }
 
@@ -3338,7 +3335,7 @@
     if (renderWidgetHostView_->GetActiveWidget()) {
       renderWidgetHostView_->GetActiveWidget()->ImeCommitText(
           base::SysNSStringToUTF16(im_text),
-          std::vector<blink::WebCompositionUnderline>(), replacement_range, 0);
+          std::vector<ui::CompositionUnderline>(), replacement_range, 0);
     }
   }
 
diff --git a/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.mm b/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.mm
index b6923ee..72cbc1c2 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.mm
@@ -142,10 +142,10 @@
       renderWidgetHostViewMac];
   DCHECK(rwhv);
 
-  RenderWidgetHostImpl* rwh =
-      RenderWidgetHostImpl::From(rwhv->GetRenderWidgetHost());
-  // The second parameter is the core command value which isn't used here.
-  rwh->ExecuteEditCommand(command, "");
+  RenderWidgetHostDelegate* host_delegate =
+      RenderWidgetHostImpl::From(rwhv->GetRenderWidgetHost())->delegate();
+  if (host_delegate)
+    host_delegate->ExecuteEditCommand(command, base::nullopt);
 }
 
 }  // namespace
diff --git a/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
index 3c513e0..b24bdafb 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
@@ -74,34 +74,24 @@
   return true;
 }
 
-class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
+class RenderWidgetHostDelegateEditCommandCounter
+    : public RenderWidgetHostDelegate {
  public:
-  MockRenderWidgetHostDelegate() {}
-  ~MockRenderWidgetHostDelegate() override {}
-
-  private:
-   void Cut() override {}
-   void Copy() override {}
-   void Paste() override {}
-   void SelectAll() override {}
-};
-
-// Create a RenderWidget for which we can filter messages.
-class RenderWidgetHostEditCommandCounter : public RenderWidgetHostImpl {
- public:
-  RenderWidgetHostEditCommandCounter(RenderWidgetHostDelegate* delegate,
-                                     RenderProcessHost* process,
-                                     int32_t routing_id)
-      : RenderWidgetHostImpl(delegate, process, routing_id, false),
-        edit_command_message_count_(0) {}
-
-  bool Send(IPC::Message* message) override {
-    if (message->type() == InputMsg_ExecuteEditCommand::ID)
-      edit_command_message_count_++;
-    return RenderWidgetHostImpl::Send(message);
-  }
-
+  RenderWidgetHostDelegateEditCommandCounter()
+      : edit_command_message_count_(0) {}
+  ~RenderWidgetHostDelegateEditCommandCounter() override {}
   unsigned int edit_command_message_count_;
+
+ private:
+  void ExecuteEditCommand(
+      const std::string& command,
+      const base::Optional<base::string16>& value) override {
+    edit_command_message_count_++;
+  }
+  void Cut() override {}
+  void Copy() override {}
+  void Paste() override {}
+  void SelectAll() override {}
 };
 
 class RenderWidgetHostViewMacEditCommandHelperTest : public PlatformTest {
@@ -136,7 +126,7 @@
 // RenderWidgetHost.
 TEST_F(RenderWidgetHostViewMacEditCommandHelperWithTaskEnvTest,
        TestEditingCommandDelivery) {
-  MockRenderWidgetHostDelegate delegate;
+  RenderWidgetHostDelegateEditCommandCounter delegate;
   TestBrowserContext browser_context;
   MockRenderProcessHostFactory process_host_factory;
   RenderProcessHost* process_host =
@@ -150,9 +140,9 @@
   base::mac::ScopedNSAutoreleasePool pool;
 
   int32_t routing_id = process_host->GetNextRoutingID();
-  RenderWidgetHostEditCommandCounter* render_widget =
-      new RenderWidgetHostEditCommandCounter(&delegate, process_host,
-                                             routing_id);
+
+  RenderWidgetHostImpl* render_widget =
+      new RenderWidgetHostImpl(&delegate, process_host, routing_id, false);
 
   ui::WindowResizeHelperMac::Get()->Init(base::ThreadTaskRunnerHandle::Get());
 
@@ -176,7 +166,7 @@
   }
 
   size_t num_edit_commands = [edit_command_strings count];
-  EXPECT_EQ(render_widget->edit_command_message_count_, num_edit_commands);
+  EXPECT_EQ(delegate.edit_command_message_count_, num_edit_commands);
   rwhv_cocoa.reset();
   pool.Recycle();
 
diff --git a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
index cd5e5117..87946bc29 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
@@ -210,6 +210,9 @@
   }
 
  private:
+  void ExecuteEditCommand(
+      const std::string& command,
+      const base::Optional<base::string16>& value) override {}
   void Cut() override {}
   void Copy() override {}
   void Paste() override {}
diff --git a/content/browser/renderer_host/text_input_client_mac_unittest.mm b/content/browser/renderer_host/text_input_client_mac_unittest.mm
index c74fc6db..73c1be83 100644
--- a/content/browser/renderer_host/text_input_client_mac_unittest.mm
+++ b/content/browser/renderer_host/text_input_client_mac_unittest.mm
@@ -34,6 +34,9 @@
   ~MockRenderWidgetHostDelegate() override {}
 
  private:
+  void ExecuteEditCommand(
+      const std::string& command,
+      const base::Optional<base::string16>& value) override {}
   void Cut() override {}
   void Copy() override {}
   void Paste() override {}
diff --git a/content/browser/web_contents/web_contents_android.cc b/content/browser/web_contents/web_contents_android.cc
index 6e28ceb..84ea2af 100644
--- a/content/browser/web_contents/web_contents_android.cc
+++ b/content/browser/web_contents/web_contents_android.cc
@@ -415,11 +415,10 @@
 void WebContentsAndroid::ScrollFocusedEditableNodeIntoView(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj) {
-  RenderViewHost* host = web_contents_->GetRenderViewHost();
-  if (!host)
+  RenderFrameHostImpl* frame = web_contents_->GetFocusedFrame();
+  if (!frame)
     return;
-  host->Send(new InputMsg_ScrollFocusedEditableNodeIntoRect(
-      host->GetRoutingID(), gfx::Rect()));
+  frame->GetFrameInputHandler()->ScrollFocusedEditableNodeIntoRect(gfx::Rect());
 }
 
 void WebContentsAndroid::SelectWordAroundCaret(
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 3be78992..9738d39b 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -2753,8 +2753,18 @@
   return rfh ? rfh->GetOrCreateBrowserAccessibilityManager() : nullptr;
 }
 
+void WebContentsImpl::ExecuteEditCommand(
+    const std::string& command,
+    const base::Optional<base::string16>& value) {
+  RenderFrameHostImpl* focused_frame = GetFocusedFrame();
+  if (!focused_frame)
+    return;
+
+  focused_frame->GetFrameInputHandler()->ExecuteEditCommand(command, value);
+}
+
 void WebContentsImpl::MoveRangeSelectionExtent(const gfx::Point& extent) {
-  RenderFrameHost* focused_frame = GetFocusedFrame();
+  RenderFrameHostImpl* focused_frame = GetFocusedFrame();
   if (!focused_frame)
     return;
 
@@ -2763,16 +2773,24 @@
 
 void WebContentsImpl::SelectRange(const gfx::Point& base,
                                   const gfx::Point& extent) {
-  RenderFrameHost* focused_frame = GetFocusedFrame();
+  RenderFrameHostImpl* focused_frame = GetFocusedFrame();
   if (!focused_frame)
     return;
 
   focused_frame->GetFrameInputHandler()->SelectRange(base, extent);
 }
 
+void WebContentsImpl::MoveCaret(const gfx::Point& extent) {
+  RenderFrameHostImpl* focused_frame = GetFocusedFrame();
+  if (!focused_frame)
+    return;
+
+  focused_frame->GetFrameInputHandler()->MoveCaret(extent);
+}
+
 void WebContentsImpl::AdjustSelectionByCharacterOffset(int start_adjust,
                                                        int end_adjust) {
-  RenderFrameHost* focused_frame = GetFocusedFrame();
+  RenderFrameHostImpl* focused_frame = GetFocusedFrame();
   if (!focused_frame)
     return;
 
@@ -2953,7 +2971,7 @@
 }
 
 void WebContentsImpl::Undo() {
-  RenderFrameHost* focused_frame = GetFocusedFrame();
+  RenderFrameHostImpl* focused_frame = GetFocusedFrame();
   if (!focused_frame)
     return;
 
@@ -2962,7 +2980,7 @@
 }
 
 void WebContentsImpl::Redo() {
-  RenderFrameHost* focused_frame = GetFocusedFrame();
+  RenderFrameHostImpl* focused_frame = GetFocusedFrame();
   if (!focused_frame)
     return;
   focused_frame->GetFrameInputHandler()->Redo();
@@ -2970,7 +2988,7 @@
 }
 
 void WebContentsImpl::Cut() {
-  RenderFrameHost* focused_frame = GetFocusedFrame();
+  RenderFrameHostImpl* focused_frame = GetFocusedFrame();
   if (!focused_frame)
     return;
 
@@ -2979,7 +2997,7 @@
 }
 
 void WebContentsImpl::Copy() {
-  RenderFrameHost* focused_frame = GetFocusedFrame();
+  RenderFrameHostImpl* focused_frame = GetFocusedFrame();
   if (!focused_frame)
     return;
 
@@ -2989,7 +3007,7 @@
 
 void WebContentsImpl::CopyToFindPboard() {
 #if defined(OS_MACOSX)
-  RenderFrameHost* focused_frame = GetFocusedFrame();
+  RenderFrameHostImpl* focused_frame = GetFocusedFrame();
   if (!focused_frame)
     return;
 
@@ -3000,7 +3018,7 @@
 }
 
 void WebContentsImpl::Paste() {
-  RenderFrameHost* focused_frame = GetFocusedFrame();
+  RenderFrameHostImpl* focused_frame = GetFocusedFrame();
   if (!focused_frame)
     return;
 
@@ -3009,7 +3027,7 @@
 }
 
 void WebContentsImpl::PasteAndMatchStyle() {
-  RenderFrameHost* focused_frame = GetFocusedFrame();
+  RenderFrameHostImpl* focused_frame = GetFocusedFrame();
   if (!focused_frame)
     return;
 
@@ -3018,7 +3036,7 @@
 }
 
 void WebContentsImpl::Delete() {
-  RenderFrameHost* focused_frame = GetFocusedFrame();
+  RenderFrameHostImpl* focused_frame = GetFocusedFrame();
   if (!focused_frame)
     return;
 
@@ -3027,7 +3045,7 @@
 }
 
 void WebContentsImpl::SelectAll() {
-  RenderFrameHost* focused_frame = GetFocusedFrame();
+  RenderFrameHostImpl* focused_frame = GetFocusedFrame();
   if (!focused_frame)
     return;
 
@@ -3036,7 +3054,7 @@
 }
 
 void WebContentsImpl::CollapseSelection() {
-  RenderFrameHost* focused_frame = GetFocusedFrame();
+  RenderFrameHostImpl* focused_frame = GetFocusedFrame();
   if (!focused_frame)
     return;
 
@@ -3044,7 +3062,7 @@
 }
 
 void WebContentsImpl::Replace(const base::string16& word) {
-  RenderFrameHost* focused_frame = GetFocusedFrame();
+  RenderFrameHostImpl* focused_frame = GetFocusedFrame();
   if (!focused_frame)
     return;
 
@@ -3052,7 +3070,7 @@
 }
 
 void WebContentsImpl::ReplaceMisspelling(const base::string16& word) {
-  RenderFrameHost* focused_frame = GetFocusedFrame();
+  RenderFrameHostImpl* focused_frame = GetFocusedFrame();
   if (!focused_frame)
     return;
 
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 12b4c25..db555e4 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -691,8 +691,11 @@
   // void Copy() override;
   // void Paste() override;
   // void SelectAll() override;
+  void ExecuteEditCommand(const std::string& command,
+                          const base::Optional<base::string16>& value) override;
   void MoveRangeSelectionExtent(const gfx::Point& extent) override;
   void SelectRange(const gfx::Point& base, const gfx::Point& extent) override;
+  void MoveCaret(const gfx::Point& extent) override;
   void AdjustSelectionByCharacterOffset(int start_adjust, int end_adjust)
       override;
   RenderWidgetHostInputEventRouter* GetInputEventRouter() override;
diff --git a/content/common/input/input_handler.mojom b/content/common/input/input_handler.mojom
index fae10f96..39cc748 100644
--- a/content/common/input/input_handler.mojom
+++ b/content/common/input/input_handler.mojom
@@ -4,12 +4,207 @@
 
 module content.mojom;
 
+import "content/common/native_types.mojom";
 import "mojo/common/string16.mojom";
 import "services/ui/public/interfaces/ime/ime.mojom";
+import "ui/events/mojo/event.mojom";
+import "ui/events/mojo/event_constants.mojom";
+import "ui/latency/mojo/latency_info.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
+import "ui/gfx/range/mojo/range.mojom";
+
+
+// These structs are purposely duplicated from ui/events/mojom/event.mojom.
+// They map WebInputEvent <-> WebInputEvent across mojo.
+// We have to work at unifying them. The current problem is that the browser
+// uses WebInputEvents inside the render widget host and input router. Once
+// we move these to ui::Event's then we can get rid of these duplicated
+// mojom structs. Ideally the browser would use ui::Event up until we
+// pass the events into the renderer and just use a StructTraits to perform
+// conversion from ui::mojom::Event --> blink::WebInputEvent.
+struct KeyData {
+  int32 dom_key;
+  int32 dom_code;
+  int32 windows_key_code;
+  int32 native_key_code;
+  bool is_system_key;
+  bool is_browser_shortcut;
+  mojo.common.mojom.String16 text;
+  mojo.common.mojom.String16 unmodified_text;
+};
+
+struct PointerData {
+  int32 pointer_id;
+  float force;
+  int32 tilt_x;
+  int32 tilt_y;
+  float tangential_pressure;
+  int32 twist;
+  Button button;
+  PointerType pointer_type;
+  int32 movement_x;
+  int32 movement_y;
+  gfx.mojom.PointF widget_position;
+  gfx.mojom.PointF screen_position;
+  MouseData? mouse_data;
+};
+
+struct WheelData {
+  float delta_x;
+  float delta_y;
+  float wheel_ticks_x;
+  float wheel_ticks_y;
+  float acceleration_ratio_x;
+  float acceleration_ratio_y;
+  int32 resending_plugin_id;
+  uint8 phase;
+  uint8 momentum_phase;
+  bool scroll_by_page;
+  bool has_precise_scrolling_deltas;
+  Cancelability cancelable;
+};
+
+struct MouseData {
+  int32 click_count;
+  WheelData? wheel_data;
+};
+
+struct ScrollUpdate {
+  float velocity_x;
+  float velocity_y;
+  bool previous_update_in_sequence_prevented;
+  bool prevent_propagation;
+};
+
+struct ScrollData {
+  float delta_x;
+  float delta_y;
+  ScrollUnits delta_units;
+  bool target_viewport;
+  InertialPhaseState inertial_phase;
+  bool synthetic;
+  int32 pointer_count;
+  ScrollUpdate? update_details;
+};
+
+struct PinchData {
+  bool zoom_disabled;
+  float scale;
+};
+
+struct FlingData {
+  float velocity_x;
+  float velocity_y;
+  bool target_viewport;
+  bool prevent_boosting;
+};
+
+struct TapData {
+  int32 tap_count;
+};
+
+struct GestureData {
+  gfx.mojom.PointF screen_position;
+  gfx.mojom.PointF widget_position;
+  GestureDevice source_device;
+  int32 unique_touch_event_id;
+  int32 resending_plugin_id;
+  gfx.mojom.Size? contact_size;
+  ScrollData? scroll_data;
+  PinchData? pinch_data;
+  TapData? tap_data;
+  FlingData? fling_data;
+};
+
+struct TouchPoint {
+  TouchState state;
+  float radius_x;
+  float radius_y;
+  float rotation_angle;
+  PointerData pointer_data;
+};
+
+struct TouchData {
+  Cancelability cancelable;
+  bool moved_beyond_slop_region;
+  bool touch_start_or_first_move;
+  uint32 unique_touch_event_id;
+  array<TouchPoint> touches;
+};
+
+struct Event {
+  EventType type;
+  int32 modifiers;
+  double timestamp_seconds;
+  ui.mojom.LatencyInfo latency;
+  KeyData? key_data;
+  PointerData? pointer_data;
+  GestureData? gesture_data;
+  TouchData? touch_data;
+};
 
 interface WidgetInputHandler {
-  // TODO(dtapuska): Implement me.
+  // Tells widget focus has been changed.
+  SetFocus(bool focused);
+
+  // Tells widget mouse capture has been lost.
+  MouseCaptureLost();
+
+  // This message notifies the renderer that the next key event is bound to one
+  // or more pre-defined edit commands. If the next key event is not handled
+  // by webkit, the specified edit commands shall be executed against current
+  // focused frame.
+  // Parameters
+  // * edit_commands (see chrome/common/edit_command_types.h)
+  //   Contains one or more edit commands.
+  // See third_party/WebKit/Source/WebCore/editing/EditorCommand.cpp for
+  // detailed definition of webkit edit commands.
+  //
+  // This message must be sent just before sending a key event.
+
+  SetEditCommandsForNextKeyEvent(array<content.mojom.EditCommand> commands);
+
+  // Sends the cursor visibility state to the render widget.
+  CursorVisibilityChanged(bool visible);
+
+  // This message sends a string being composed with an input method.
+  ImeSetComposition(mojo.common.mojom.String16 text,
+                    array<ui.mojom.CompositionUnderline> underlines,
+                    gfx.mojom.Range range, int32 start, int32 end);
+
+  // This message deletes the current composition, inserts specified text, and
+  // moves the cursor.
+  ImeCommitText(mojo.common.mojom.String16 text,
+                array<ui.mojom.CompositionUnderline> underlines,
+                gfx.mojom.Range range, int32 relative_cursor_position);
+
+  // This message inserts the ongoing composition.
+  ImeFinishComposingText(bool keep_selection);
+
+  // Request from browser to update text input state.
+  RequestTextInputStateUpdate();
+
+  // Request from browser to update the cursor and composition information which
+  // will be sent through InputHostMsg_ImeCompositionRangeChanged. Setting
+  // |immediate_request| to true  will lead to an immediate update. If
+  // |monitor_updates| is set to true then changes to text selection or regular
+  // updates in each compositor frame (when there is a change in composition
+  // info) will lead to updates being sent to the browser.
+  RequestCompositionUpdates(bool immediate_request, bool monitor_request);
+
+  // Sends an input event to the render widget. The browser should use this
+  // API if it wants to know about the result of the rendering handling
+  // the event. The callback may be delayed based on the event running on
+  // the main thread so DispatchNonBlockingEvent is always preferred if
+  // you don't require notification.
+  DispatchEvent(Event event)
+      => (InputEventAckSource source, ui.mojom.LatencyInfo updated_latency,
+         InputEventAckState state, DidOverscrollParams? overscroll);
+
+  // Sends a non-blocking input event to the render widget. The behaviour
+  // of this API is the same as DispatchEvent just that there is no callback
+  // after the event is processed.
+  DispatchNonBlockingEvent(Event event);
 };
 
 // This interface provides the input actions associated with the RenderFrame.
@@ -79,6 +274,14 @@
   // Expects a MoveRangeSelectionExtent_ACK message when finished.
   MoveRangeSelectionExtent(gfx.mojom.Point extent);
 
+  // Tells the renderer to scroll the currently focused node into rect only if
+  // the currently focused node is a Text node (textfield, text area or content
+  // editable divs).
+  ScrollFocusedEditableNodeIntoRect(gfx.mojom.Rect rect);
+
+  // Requests the renderer to move the caret selection toward the point.
+  MoveCaret(gfx.mojom.Point point);
+
   // TODO(dtapuska): Implement WidgetInputHandler.
   // GetWidgetInputHandler(associated WidgetInputHandler& interface_request);
 };
diff --git a/content/common/input_messages.h b/content/common/input_messages.h
index 6d4ce02..a28a307 100644
--- a/content/common/input_messages.h
+++ b/content/common/input_messages.h
@@ -70,6 +70,17 @@
                               blink::WebPointerProperties::Button::kLastEntry)
 IPC_ENUM_TRAITS_MAX_VALUE(blink::WebPointerProperties::PointerType,
                           blink::WebPointerProperties::PointerType::kLastEntry)
+IPC_ENUM_TRAITS_MAX_VALUE(blink::WebGestureDevice,
+                          (blink::WebGestureDevice::kWebGestureDeviceCount - 1))
+IPC_ENUM_TRAITS_MAX_VALUE(blink::WebInputEvent::DispatchType,
+                          blink::WebInputEvent::DispatchType::kLastDispatchType)
+IPC_ENUM_TRAITS_MAX_VALUE(blink::WebGestureEvent::ScrollUnits,
+                          blink::WebGestureEvent::ScrollUnits::kLastScrollUnit)
+IPC_ENUM_TRAITS_MAX_VALUE(
+    blink::WebGestureEvent::InertialPhaseState,
+    blink::WebGestureEvent::InertialPhaseState::kLastPhase)
+IPC_ENUM_TRAITS_MAX_VALUE(blink::WebTouchPoint::State,
+                          blink::WebTouchPoint::State::kStateMax)
 
 IPC_STRUCT_TRAITS_BEGIN(ui::DidOverscrollParams)
   IPC_STRUCT_TRAITS_MEMBER(accumulated_overscroll)
diff --git a/content/common/native_types.mojom b/content/common/native_types.mojom
index c848b95..cd0e90f 100644
--- a/content/common/native_types.mojom
+++ b/content/common/native_types.mojom
@@ -43,3 +43,39 @@
 
 [Native]
 enum WebPopupType;
+
+[Native]
+enum Button;
+
+[Native]
+enum PointerType;
+
+[Native]
+struct EditCommand;
+
+[Native]
+enum InputEventAckState;
+
+[Native]
+enum InputEventAckSource;
+
+[Native]
+enum EventType;
+
+[Native]
+enum Cancelability;
+
+[Native]
+enum GestureDevice;
+
+[Native]
+enum ScrollUnits;
+
+[Native]
+enum InertialPhaseState;
+
+[Native]
+enum TouchState;
+
+[Native]
+struct DidOverscrollParams;
diff --git a/content/common/native_types.typemap b/content/common/native_types.typemap
index 22be41a4f..9a14d13 100644
--- a/content/common/native_types.typemap
+++ b/content/common/native_types.typemap
@@ -4,17 +4,31 @@
 
 mojom = "//content/common/native_types.mojom"
 public_headers = [
+  "//content/common/edit_command.h",
   "//content/common/frame_owner_properties.h",
   "//content/common/frame_replication_state.h",
   "//content/common/resize_params.h",
+  "//content/common/input/input_event.h",
+  "//content/common/input/input_event_ack_source.h",
+  "//content/common/input/input_event_ack_state.h",
   "//content/public/common/renderer_preferences.h",
   "//content/public/common/web_preferences.h",
   "//net/base/network_change_notifier.h",
   "//net/nqe/effective_connection_type.h",
+  "//third_party/WebKit/public/platform/WebGestureDevice.h",
+  "//third_party/WebKit/public/platform/WebGestureEvent.h",
+  "//third_party/WebKit/public/platform/WebInputEvent.h",
+  "//third_party/WebKit/public/platform/WebMouseWheelEvent.h",
+  "//third_party/WebKit/public/platform/WebPointerProperties.h",
+  "//third_party/WebKit/public/platform/WebTouchPoint.h",
   "//third_party/WebKit/public/web/WebPopupType.h",
+  "//ui/events/blink/did_overscroll_params.h",
+  "//ui/events/blink/web_input_event_traits.h",
+  "//ui/latency/ipc/latency_info_param_traits.h",
 ]
 traits_headers = [
   "//content/common/frame_messages.h",
+  "//content/common/input_messages.h",
   "//content/common/view_messages.h",
   "//content/public/common/common_param_traits.h",
 ]
@@ -40,12 +54,24 @@
   "//url/ipc:url_ipc",
 ]
 type_mappings = [
+  "content.mojom.Button=blink::WebPointerProperties::Button",
+  "content.mojom.Cancelability=blink::WebInputEvent::DispatchType",
   "content.mojom.EffectiveConnectionType=net::EffectiveConnectionType",
+  "content.mojom.EditCommand=content::EditCommand",
+  "content.mojom.EventType=blink::WebInputEvent::Type",
   "content.mojom.FrameOwnerProperties=content::FrameOwnerProperties",
   "content.mojom.FrameReplicationState=content::FrameReplicationState",
+  "content.mojom.GestureDevice=blink::WebGestureDevice",
+  "content.mojom.InertialPhaseState=blink::WebGestureEvent::InertialPhaseState",
+  "content.mojom.InputEventAckSource=content::InputEventAckSource",
+  "content.mojom.InputEventAckState=content::InputEventAckState",
   "content.mojom.NetworkConnectionType=net::NetworkChangeNotifier::ConnectionType",
+  "content.mojom.DidOverscrollParams=ui::DidOverscrollParams",
+  "content.mojom.PointerType=blink::WebPointerProperties::PointerType",
   "content.mojom.RendererPreferences=content::RendererPreferences",
   "content.mojom.ResizeParams=content::ResizeParams",
+  "content.mojom.ScrollUnits=blink::WebGestureEvent::ScrollUnits",
+  "content.mojom.TouchState=blink::WebTouchPoint::State",
   "content.mojom.WebPopupType=blink::WebPopupType",
   "content.mojom.WebPreferences=content::WebPreferences",
 ]
diff --git a/content/public/browser/render_frame_host.h b/content/public/browser/render_frame_host.h
index 49baa59..4bcf78b6 100644
--- a/content/public/browser/render_frame_host.h
+++ b/content/public/browser/render_frame_host.h
@@ -10,7 +10,6 @@
 #include "base/callback_forward.h"
 #include "build/build_config.h"
 #include "content/common/content_export.h"
-#include "content/common/input/input_handler.mojom.h"
 #include "content/public/common/console_message_level.h"
 #include "content/public/common/file_chooser_params.h"
 #include "ipc/ipc_listener.h"
@@ -43,6 +42,7 @@
 }
 
 namespace content {
+
 class AssociatedInterfaceProvider;
 class RenderProcessHost;
 class RenderViewHost;
@@ -284,8 +284,6 @@
   // process to determine whether access to a feature is allowed.
   virtual bool IsFeatureEnabled(blink::WebFeaturePolicyFeature feature) = 0;
 
-  virtual mojom::FrameInputHandler* GetFrameInputHandler() = 0;
-
  private:
   // This interface should only be implemented inside content.
   friend class RenderFrameHostImpl;
diff --git a/content/public/test/text_input_test_utils.cc b/content/public/test/text_input_test_utils.cc
index 19527714..442ddea6 100644
--- a/content/public/test/text_input_test_utils.cc
+++ b/content/public/test/text_input_test_utils.cc
@@ -279,15 +279,8 @@
     const std::vector<ui::CompositionUnderline>& underlines,
     const gfx::Range& replacement_range,
     int relative_cursor_pos) {
-  std::vector<blink::WebCompositionUnderline> web_composition_underlines;
-  for (auto underline : underlines) {
-    web_composition_underlines.emplace_back(
-        static_cast<int>(underline.start_offset),
-        static_cast<int>(underline.end_offset), underline.color,
-        underline.thick, underline.background_color);
-  }
   RenderWidgetHostImpl::From(rwh)->ImeCommitText(
-      text, web_composition_underlines, replacement_range, relative_cursor_pos);
+      text, underlines, replacement_range, relative_cursor_pos);
 }
 
 void SendImeSetCompositionTextToWidget(
@@ -297,16 +290,8 @@
     const gfx::Range& replacement_range,
     int selection_start,
     int selection_end) {
-  std::vector<blink::WebCompositionUnderline> web_composition_underlines;
-  for (auto underline : underlines) {
-    web_composition_underlines.emplace_back(
-        static_cast<int>(underline.start_offset),
-        static_cast<int>(underline.end_offset), underline.color,
-        underline.thick, underline.background_color);
-  }
   RenderWidgetHostImpl::From(rwh)->ImeSetComposition(
-      text, web_composition_underlines, replacement_range, selection_start,
-      selection_end);
+      text, underlines, replacement_range, selection_start, selection_end);
 }
 
 bool DestroyRenderWidgetHost(int32_t process_id,
diff --git a/content/renderer/input/frame_input_handler_impl.cc b/content/renderer/input/frame_input_handler_impl.cc
index 79be471..52c00fa 100644
--- a/content/renderer/input/frame_input_handler_impl.cc
+++ b/content/renderer/input/frame_input_handler_impl.cc
@@ -337,6 +337,37 @@
       render_frame_->render_view()->ConvertWindowPointToViewport(extent));
 }
 
+void FrameInputHandlerImpl::ScrollFocusedEditableNodeIntoRect(
+    const gfx::Rect& rect) {
+  if (!main_thread_task_runner_->BelongsToCurrentThread()) {
+    RunOnMainThread(
+        base::Bind(&FrameInputHandlerImpl::ScrollFocusedEditableNodeIntoRect,
+                   weak_this_, rect));
+    return;
+  }
+
+  if (!render_frame_)
+    return;
+
+  RenderViewImpl* render_view = render_frame_->render_view();
+  render_view->ScrollFocusedEditableNodeIntoRect(rect);
+}
+
+void FrameInputHandlerImpl::MoveCaret(const gfx::Point& point) {
+  if (!main_thread_task_runner_->BelongsToCurrentThread()) {
+    RunOnMainThread(
+        base::Bind(&FrameInputHandlerImpl::MoveCaret, weak_this_, point));
+    return;
+  }
+
+  if (!render_frame_)
+    return;
+
+  RenderViewImpl* render_view = render_frame_->render_view();
+  render_frame_->GetWebFrame()->MoveCaretSelection(
+      render_view->ConvertWindowPointToViewport(point));
+}
+
 void FrameInputHandlerImpl::ExecuteCommandOnMainThread(
     const std::string& command,
     UpdateState update_state) {
diff --git a/content/renderer/input/frame_input_handler_impl.h b/content/renderer/input/frame_input_handler_impl.h
index 9c75602..66ca5e43 100644
--- a/content/renderer/input/frame_input_handler_impl.h
+++ b/content/renderer/input/frame_input_handler_impl.h
@@ -68,6 +68,8 @@
   void SelectRange(const gfx::Point& base, const gfx::Point& extent) override;
   void AdjustSelectionByCharacterOffset(int32_t start, int32_t end) override;
   void MoveRangeSelectionExtent(const gfx::Point& extent) override;
+  void ScrollFocusedEditableNodeIntoRect(const gfx::Rect& rect) override;
+  void MoveCaret(const gfx::Point& point) override;
 
  private:
   ~FrameInputHandlerImpl() override;
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index b5ab78a924..8bd2dbd 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -1609,6 +1609,9 @@
                         OnMoveRangeSelectionExtent)
     IPC_MESSAGE_HANDLER(InputMsg_Replace, OnReplace)
     IPC_MESSAGE_HANDLER(InputMsg_ReplaceMisspelling, OnReplaceMisspelling)
+    IPC_MESSAGE_HANDLER(InputMsg_MoveCaret, OnMoveCaret)
+    IPC_MESSAGE_HANDLER(InputMsg_ScrollFocusedEditableNodeIntoRect,
+                        OnScrollFocusedEditableNodeIntoRect)
     IPC_MESSAGE_HANDLER(FrameMsg_CopyImageAt, OnCopyImageAt)
     IPC_MESSAGE_HANDLER(FrameMsg_SaveImageAt, OnSaveImageAt)
     IPC_MESSAGE_HANDLER(InputMsg_ExtendSelectionAndDelete,
@@ -1900,6 +1903,18 @@
   }
 }
 
+void RenderFrameImpl::OnMoveCaret(const gfx::Point& point) {
+  Send(new InputHostMsg_MoveCaret_ACK(render_view_->GetRoutingID()));
+  frame_->MoveCaretSelection(render_view_->ConvertWindowPointToViewport(point));
+}
+
+void RenderFrameImpl::OnScrollFocusedEditableNodeIntoRect(
+    const gfx::Rect& rect) {
+  // TODO(dtapuska): Move the implementation of scroll focused
+  // editable node into rect into this class.
+  render_view_->ScrollFocusedEditableNodeIntoRect(rect);
+}
+
 void RenderFrameImpl::OnUndo() {
   frame_->ExecuteCommand(WebString::FromUTF8("Undo"));
 }
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 7683fb5..6db17694 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -858,6 +858,8 @@
   void OnContextMenuClosed(const CustomContextMenuContext& custom_context);
   void OnCustomContextMenuAction(const CustomContextMenuContext& custom_context,
                                  unsigned action);
+  void OnMoveCaret(const gfx::Point& point);
+  void OnScrollFocusedEditableNodeIntoRect(const gfx::Rect& rect);
   void OnUndo();
   void OnRedo();
   void OnCut();
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index d0f55d4..bc40880 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -1149,10 +1149,6 @@
 
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(RenderViewImpl, message)
-    IPC_MESSAGE_HANDLER(InputMsg_ExecuteEditCommand, OnExecuteEditCommand)
-    IPC_MESSAGE_HANDLER(InputMsg_MoveCaret, OnMoveCaret)
-    IPC_MESSAGE_HANDLER(InputMsg_ScrollFocusedEditableNodeIntoRect,
-                        OnScrollFocusedEditableNodeIntoRect)
     IPC_MESSAGE_HANDLER(ViewMsg_SetPageScale, OnSetPageScale)
     IPC_MESSAGE_HANDLER(ViewMsg_SetInitialFocus, OnSetInitialFocus)
     IPC_MESSAGE_HANDLER(ViewMsg_UpdateTargetURL_ACK, OnUpdateTargetURLAck)
@@ -1243,26 +1239,7 @@
   target_url_status_ = TARGET_NONE;
 }
 
-void RenderViewImpl::OnExecuteEditCommand(const std::string& name,
-    const std::string& value) {
-  if (!webview() || !webview()->FocusedFrame())
-    return;
-
-  webview()->FocusedFrame()->ExecuteCommand(WebString::FromUTF8(name),
-                                            WebString::FromUTF8(value));
-}
-
-void RenderViewImpl::OnMoveCaret(const gfx::Point& point) {
-  if (!webview())
-    return;
-
-  Send(new InputHostMsg_MoveCaret_ACK(GetRoutingID()));
-  webview()->FocusedFrame()->MoveCaretSelection(
-      ConvertWindowPointToViewport(point));
-}
-
-void RenderViewImpl::OnScrollFocusedEditableNodeIntoRect(
-    const gfx::Rect& rect) {
+void RenderViewImpl::ScrollFocusedEditableNodeIntoRect(const gfx::Rect& rect) {
   blink::WebAutofillClient* autofill_client = nullptr;
   if (auto* focused_frame = GetWebView()->FocusedFrame())
     autofill_client = focused_frame->AutofillClient();
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index 452aa15..ded94ab 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -381,6 +381,7 @@
   void HandleInputEvent(const blink::WebCoalescedInputEvent& input_event,
                         const ui::LatencyInfo& latency_info,
                         HandledEventCallback callback) override;
+  void ScrollFocusedEditableNodeIntoRect(const gfx::Rect& rect);
 
  protected:
   // RenderWidget overrides:
@@ -505,8 +506,6 @@
   // The documentation for these functions should be in
   // content/common/*_messages.h for the message that the function is handling.
   void OnExecuteEditCommand(const std::string& name, const std::string& value);
-  void OnMoveCaret(const gfx::Point& point);
-  void OnScrollFocusedEditableNodeIntoRect(const gfx::Rect& rect);
   void OnAllowScriptToClose(bool script_can_close);
   void OnCancelDownload(int32_t download_id);
   void OnClosePage();