Implement Linux IME support
diff --git a/mojo/services/keyboard/interfaces/BUILD.gn b/mojo/services/keyboard/interfaces/BUILD.gn
index 6aa9389..b3ca11d 100644
--- a/mojo/services/keyboard/interfaces/BUILD.gn
+++ b/mojo/services/keyboard/interfaces/BUILD.gn
@@ -9,4 +9,10 @@
   sources = [
     "keyboard.mojom",
   ]
+
+  import_dirs = [ get_path_info("../../", "abspath") ]
+
+  deps = [
+    "../../native_viewport/interfaces",
+  ]
 }
diff --git a/mojo/services/keyboard/interfaces/keyboard.mojom b/mojo/services/keyboard/interfaces/keyboard.mojom
index 9794220..2fa4515 100644
--- a/mojo/services/keyboard/interfaces/keyboard.mojom
+++ b/mojo/services/keyboard/interfaces/keyboard.mojom
@@ -5,6 +5,8 @@
 [DartPackage="mojo_services"]
 module keyboard;
 
+import "native_viewport/interfaces/native_viewport.mojom";
+
 struct CompletionData {
   int64 id;
   int32 position;
@@ -49,3 +51,9 @@
   SetText(string text);
   SetSelection(int32 start, int32 end);
 };
+
+interface KeyboardServiceFactory {
+  CreateKeyboardService(
+      mojo.NativeViewportEventDispatcher& keyEventDispatcher,
+      KeyboardService& serviceRequest);
+};
diff --git a/services/keyboard/linux/keyboard_service_impl.cc b/services/keyboard/linux/keyboard_service_impl.cc
index 8b004c0..74f942a 100644
--- a/services/keyboard/linux/keyboard_service_impl.cc
+++ b/services/keyboard/linux/keyboard_service_impl.cc
@@ -15,30 +15,9 @@
 
 LinuxKeyboardServiceImpl::LinuxKeyboardServiceImpl(
     mojo::InterfaceRequest<::keyboard::KeyboardService> request,
-    mojo::Shell* shell,
-    mojo::ApplicationConnection* connection)
-    : shell_(shell), connection_(connection),
-      binding_(this, request.Pass()),
-      event_dispatcher_binding_(this),
-      client_(nullptr) {
-  // Connect IME to provided client
-  mojo::NativeViewportPtr viewport_service_;
-  connection_->ConnectToService(&viewport_service_);
-
-  if (!viewport_service_) {
-    mojo::ServiceProviderPtr viewport_service_provider;
-    shell_->ConnectToApplication("mojo:native_viewport_service",
-                                 mojo::GetProxy(&viewport_service_provider),
-                                 nullptr);
-    mojo::ConnectToService(viewport_service_provider.get(), &viewport_service_);
-  }
-
-  if (viewport_service_) {
-    mojo::NativeViewportEventDispatcherPtr dispatcher;
-    event_dispatcher_binding_.Bind(GetProxy(&dispatcher));
-    viewport_service_->SetKeyEventDispatcher(dispatcher.Pass());
-  }
-
+    mojo::InterfaceRequest<NativeViewportEventDispatcher> dispatcher)
+    : binding_(this, request.Pass()),
+      event_dispatcher_binding_(this, dispatcher.Pass()) {
 }
 
 LinuxKeyboardServiceImpl::~LinuxKeyboardServiceImpl() {
@@ -56,8 +35,8 @@
   client_ = nullptr;
 }
 
-void LinuxKeyboardServiceImpl::SetText(const mojo::String&) {
-  // Not applicable for physical keyboards
+void LinuxKeyboardServiceImpl::SetText(const mojo::String& text) {
+  text_ = text;
 }
 
 void LinuxKeyboardServiceImpl::SetSelection(int32_t start, int32_t end) {
@@ -79,7 +58,7 @@
 void LinuxKeyboardServiceImpl::OnEvent(mojo::EventPtr event,
                                        const mojo::Callback<void()>& callback) {
   if (event->action == mojo::EventType::KEY_PRESSED && event->key_data->is_char) {
-    if (client_ != nullptr) {
+    if (client_) {
       switch(event->key_data->windows_key_code) {
         case mojo::KeyboardCode::BACK: // backspace
           client_->DeleteSurroundingText(1, 0);
@@ -91,7 +70,7 @@
           client_->SetSelection(0, 0);
           break;
         case mojo::KeyboardCode::END:
-          client_->SetSelection(1, 1);
+          client_->SetSelection(text_.size()-1, text_.size()-1);
           break;
         case mojo::KeyboardCode::TAB: // tab
           // TODO: Advance focus, in reverse if shifted
@@ -102,8 +81,9 @@
         default:
           base::string16 character;
           character.push_back(event->key_data->character);
-          mojo::String text(base::UTF16ToUTF8(character));
-          client_->CommitText(text, 1);
+          std::string s = base::UTF16ToUTF8(character);
+          text_ += s;
+          client_->CommitText(mojo::String(s), 1);
           break;
       }
     }
diff --git a/services/keyboard/linux/keyboard_service_impl.h b/services/keyboard/linux/keyboard_service_impl.h
index dc1b4bd..85f756e 100644
--- a/services/keyboard/linux/keyboard_service_impl.h
+++ b/services/keyboard/linux/keyboard_service_impl.h
@@ -19,8 +19,7 @@
  public:
   explicit LinuxKeyboardServiceImpl(
       mojo::InterfaceRequest<::keyboard::KeyboardService> request,
-      mojo::Shell* shell,
-      mojo::ApplicationConnection* connection);
+      mojo::InterfaceRequest<NativeViewportEventDispatcher> dispatcher);
   ~LinuxKeyboardServiceImpl() override;
   void Show(::keyboard::KeyboardClientPtr client,
             ::keyboard::KeyboardType type) override;
@@ -39,6 +38,7 @@
   mojo::Binding<mojo::NativeViewportEventDispatcher> event_dispatcher_binding_;
 
   ::keyboard::KeyboardClientPtr client_;
+  std::string text_;
 
   DISALLOW_COPY_AND_ASSIGN(LinuxKeyboardServiceImpl);
 };
diff --git a/services/keyboard/linux/main.cc b/services/keyboard/linux/main.cc
index c7a0bbb..6388df0 100644
--- a/services/keyboard/linux/main.cc
+++ b/services/keyboard/linux/main.cc
@@ -16,48 +16,45 @@
 
 namespace keyboard {
 
+class KeyboardServiceFactoryImpl : public ::keyboard::KeyboardServiceFactory {
+public:
+  KeyboardServiceFactoryImpl(mojo::InterfaceRequest<KeyboardServiceFactory> request)
+    : binding_(this, request.Pass()) {}
+
+  // |InterfaceFactory<KeyboardService>| implementation:
+  void CreateKeyboardService(
+      mojo::InterfaceRequest<mojo::NativeViewportEventDispatcher> keyEventDispatcher,
+      mojo::InterfaceRequest<KeyboardService> serviceRequest) override {
+    new LinuxKeyboardServiceImpl(serviceRequest.Pass(), keyEventDispatcher.Pass());
+  }
+
+private:
+  mojo::StrongBinding<::keyboard::KeyboardServiceFactory> binding_;
+
+};
+
 class KeyboardServiceApp : public mojo::ApplicationDelegate,
-                           public mojo::InterfaceFactory<KeyboardService> {
+                           public mojo::InterfaceFactory<KeyboardServiceFactory> {
  public:
   KeyboardServiceApp() {}
   ~KeyboardServiceApp() override {}
 
  private:
-  // |ApplicationDelegate| override:
-  void Initialize(mojo::ApplicationImpl* app) override {
-    shell_ = app->shell();
-
-  /*
-  // WRONG TROUSERS
-    mojo::ServiceProviderPtr viewport_service_provider;
-    shell_->ConnectToApplication("mojo:native_viewport_service",
-                                 mojo::GetProxy(&viewport_service_provider),
-                                 nullptr);
-    mojo::NativeViewportPtr viewport_service_;
-    mojo::ConnectToService(viewport_service_provider.get(), &viewport_service_);
-
-    mojo::NativeViewportEventDispatcherPtr dispatcher;
-    mojo::Binding<mojo::NativeViewportEventDispatcher> event_dispatcher_binding_(this);
-    event_dispatcher_binding_.Bind(GetProxy(&dispatcher));
-    viewport_service_->SetKeyEventDispatcher(dispatcher.Pass());
-  */
-  }
 
   // |ApplicationDelegate| override:
   bool ConfigureIncomingConnection(mojo::ApplicationConnection* connection) override {
-    connection->AddService<KeyboardService>(this);
+    connection->AddService<KeyboardServiceFactory>(this);
     return true;
   }
 
   // |InterfaceFactory<KeyboardService>| implementation:
   void Create(mojo::ApplicationConnection* connection,
-              mojo::InterfaceRequest<KeyboardService> request) override {
-    new LinuxKeyboardServiceImpl(request.Pass(), shell_, connection);
+              mojo::InterfaceRequest<KeyboardServiceFactory> request) override {
+    new KeyboardServiceFactoryImpl(request.Pass());
   }
 
  private:
 
-  mojo::Shell* shell_;
   DISALLOW_COPY_AND_ASSIGN(KeyboardServiceApp);
 };
 
diff --git a/services/keyboard_native/main.cc b/services/keyboard_native/main.cc
index 1ad2537..7df486d 100644
--- a/services/keyboard_native/main.cc
+++ b/services/keyboard_native/main.cc
@@ -17,16 +17,16 @@
 
 namespace keyboard {
 
-class KeyboardServiceFactory : public mojo::InterfaceFactory<KeyboardService> {
+class NativeKeyboardServiceFactory : public mojo::InterfaceFactory<KeyboardService> {
  public:
-  explicit KeyboardServiceFactory(
+  explicit NativeKeyboardServiceFactory(
       mojo::InterfaceRequest<mojo::ServiceProvider> service_provider_request) {
     if (service_provider_request.is_pending()) {
       service_provider_impl_.Bind(service_provider_request.Pass());
       service_provider_impl_.AddService<KeyboardService>(this);
     }
   }
-  ~KeyboardServiceFactory() override {}
+  ~NativeKeyboardServiceFactory() override {}
 
   void OnViewCreated(mojo::View* view, mojo::Shell* shell) {
     view_observer_delegate_.OnViewCreated(view, shell);
@@ -68,8 +68,8 @@
   void OnEmbed(mojo::View* root,
                mojo::InterfaceRequest<mojo::ServiceProvider> services,
                mojo::ServiceProviderPtr exposed_services) override {
-    KeyboardServiceFactory* keyboard_service_factory =
-        new KeyboardServiceFactory(services.Pass());
+    NativeKeyboardServiceFactory* keyboard_service_factory =
+        new NativeKeyboardServiceFactory(services.Pass());
     keyboard_service_factory->OnViewCreated(root, shell_);
   }