1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/ui/ash/ash_keyboard_controller_proxy.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ash/display/display_controller.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ash/shell.h"
9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/extensions/event_names.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/extensions/extension_function_dispatcher.h"
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/extensions/extension_system.h"
138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/extensions/extension_web_contents_observer.h"
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/media/media_capture_devices_dispatcher.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/profiles/profile.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/profiles/profile_manager.h"
1768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "chrome/common/extensions/api/virtual_keyboard_private.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/extensions/extension_messages.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/site_instance.h"
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/web_contents.h"
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/web_contents_view.h"
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/event_router.h"
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "extensions/browser/view_type_utils.h"
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "extensions/common/constants.h"
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ipc/ipc_message_macros.h"
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/aura/client/aura_constants.h"
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/aura/root_window.h"
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/aura/window.h"
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/ime/input_method.h"
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/ime/text_input_client.h"
31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/compositor/scoped_layer_animation_settings.h"
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/keyboard/keyboard_controller.h"
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace virtual_keyboard_private = extensions::api::virtual_keyboard_private;
3568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)typedef virtual_keyboard_private::OnTextInputBoxFocused::Context Context;
3668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace {
3868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char* kVirtualKeyboardExtensionID = "mppnpdlheglhdfmldimlhpnegondlapf";
4068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// The virtual keyboard show/hide animation duration.
42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const int kAnimationDurationMs = 1000;
43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
4468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)Context::Type TextInputTypeToGeneratedInputTypeEnum(ui::TextInputType type) {
4568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  switch (type) {
4668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case ui::TEXT_INPUT_TYPE_NONE:
4768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return Context::TYPE_NONE;
4868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case ui::TEXT_INPUT_TYPE_PASSWORD:
4968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return Context::TYPE_PASSWORD;
5068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case ui::TEXT_INPUT_TYPE_EMAIL:
5168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return Context::TYPE_EMAIL;
5268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case ui::TEXT_INPUT_TYPE_NUMBER:
5368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return Context::TYPE_NUMBER;
5468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case ui::TEXT_INPUT_TYPE_TELEPHONE:
5568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return Context::TYPE_TEL;
5668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case ui::TEXT_INPUT_TYPE_URL:
5768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return Context::TYPE_URL;
5868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case ui::TEXT_INPUT_TYPE_DATE:
5968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return Context::TYPE_DATE;
6068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case ui::TEXT_INPUT_TYPE_TEXT:
6168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case ui::TEXT_INPUT_TYPE_SEARCH:
6268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case ui::TEXT_INPUT_TYPE_DATE_TIME:
6368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL:
6468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case ui::TEXT_INPUT_TYPE_MONTH:
6568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case ui::TEXT_INPUT_TYPE_TIME:
6668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case ui::TEXT_INPUT_TYPE_WEEK:
6768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case ui::TEXT_INPUT_TYPE_TEXT_AREA:
6868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case ui::TEXT_INPUT_TYPE_CONTENT_EDITABLE:
6968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case ui::TEXT_INPUT_TYPE_DATE_TIME_FIELD:
7068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return Context::TYPE_TEXT;
7168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
7268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  NOTREACHED();
7368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return Context::TYPE_NONE;
7468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
7568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
7668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}  // namespace
7768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)AshKeyboardControllerProxy::AshKeyboardControllerProxy() {}
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)AshKeyboardControllerProxy::~AshKeyboardControllerProxy() {}
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AshKeyboardControllerProxy::OnRequest(
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ExtensionHostMsg_Request_Params& params) {
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  extension_function_dispatcher_->Dispatch(
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      params, web_contents()->GetRenderViewHost());
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)content::BrowserContext* AshKeyboardControllerProxy::GetBrowserContext() {
89d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return ProfileManager::GetActiveUserProfileOrOffTheRecord();
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ui::InputMethod* AshKeyboardControllerProxy::GetInputMethod() {
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  aura::Window* root_window = ash::Shell::GetInstance()->GetPrimaryRootWindow();
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(root_window);
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return root_window->GetProperty(aura::client::kRootWindowInputMethodKey);
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void AshKeyboardControllerProxy::RequestAudioInput(
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      content::WebContents* web_contents,
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      const content::MediaStreamRequest& request,
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      const content::MediaResponseCallback& callback) {
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const extensions::Extension* extension = NULL;
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  GURL origin(request.security_origin);
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (origin.SchemeIs(extensions::kExtensionScheme)) {
10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ExtensionService* extensions_service =
106d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)        extensions::ExtensionSystem::GetForBrowserContext(
107d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)            GetBrowserContext())->extension_service();
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    extension = extensions_service->extensions()->GetByID(origin.host());
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DCHECK(extension);
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  MediaCaptureDevicesDispatcher::GetInstance()->ProcessMediaAccessRequest(
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      web_contents, request, callback, extension);
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AshKeyboardControllerProxy::SetupWebContents(
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    content::WebContents* contents) {
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  extension_function_dispatcher_.reset(
119d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      new ExtensionFunctionDispatcher(GetBrowserContext(), this));
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  extensions::SetViewType(contents, extensions::VIEW_TYPE_VIRTUAL_KEYBOARD);
1218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  extensions::ExtensionWebContentsObserver::CreateForWebContents(contents);
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Observe(contents);
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)extensions::WindowController*
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    AshKeyboardControllerProxy::GetExtensionWindowController() const {
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The keyboard doesn't have a window controller.
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return NULL;
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)content::WebContents*
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    AshKeyboardControllerProxy::GetAssociatedWebContents() const {
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return web_contents();
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool AshKeyboardControllerProxy::OnMessageReceived(
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const IPC::Message& message) {
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool handled = true;
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP(AshKeyboardControllerProxy, message)
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest)
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    IPC_MESSAGE_UNHANDLED(handled = false)
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IPC_END_MESSAGE_MAP()
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return handled;
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
146b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void AshKeyboardControllerProxy::ShowKeyboardContainer(
147b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    aura::Window* container) {
1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // TODO(bshe): Implement logic to decide which root window should display
1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // virtual keyboard. http://crbug.com/303429
1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (container->GetRootWindow() != ash::Shell::GetPrimaryRootWindow())
1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    NOTIMPLEMENTED();
1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ui::LayerAnimator* container_animator = container->layer()->GetAnimator();
154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // If the container is not animating, transform the keyboard window off screen
155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // before start animating. Otherwise, start animating from current state to
156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // new state immediately (IMMEDIATELY_ANIMATE_TO_NEW_TARGET).
157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!container_animator->is_animating()) {
158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)     gfx::Transform transform;
159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)     transform.Translate(0, GetKeyboardWindow()->bounds().height());
160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)     container->SetTransform(transform);
161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  container_animator->set_preemption_strategy(
164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
166a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  {
167a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Scope the following animation settings as we don't want to animate
168a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // visibility change that triggered by a call to the base class function
169a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // ShowKeyboardContainer with these settings. The container should become
170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // visible immediately.
171a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ui::ScopedLayerAnimationSettings settings(container_animator);
172a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    settings.SetTweenType(gfx::Tween::EASE_IN);
173a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    settings.SetTransitionDuration(
174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        base::TimeDelta::FromMilliseconds(kAnimationDurationMs));
175a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    container->SetTransform(gfx::Transform());
176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // TODO(bshe): Add animation observer and do the workspace resizing after
179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // animation finished.
180b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  KeyboardControllerProxy::ShowKeyboardContainer(container);
181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // GetTextInputClient may return NULL when keyboard-usability-experiment flag
182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // is set.
1831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (GetInputMethod()->GetTextInputClient()) {
1841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    gfx::Rect showing_area =
1851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        ash::DisplayController::GetPrimaryDisplay().work_area();
1861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    GetInputMethod()->GetTextInputClient()->EnsureCaretInRect(showing_area);
1871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
18968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void AshKeyboardControllerProxy::HideKeyboardContainer(
191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    aura::Window* container) {
192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // The following animation settings should persist within this function scope.
193a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Otherwise, a call to base class function HideKeyboardContainer will hide
194a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // the container immediately.
195a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ui::ScopedLayerAnimationSettings
196a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      settings(container->layer()->GetAnimator());
197a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  settings.SetTweenType(gfx::Tween::EASE_OUT);
198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  settings.SetTransitionDuration(
199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::TimeDelta::FromMilliseconds(kAnimationDurationMs));
200a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  gfx::Transform transform;
201a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  transform.Translate(0, GetKeyboardWindow()->bounds().height());
202a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  container->SetTransform(transform);
203a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  KeyboardControllerProxy::HideKeyboardContainer(container);
204a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
205a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
20668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void AshKeyboardControllerProxy::SetUpdateInputType(ui::TextInputType type) {
20768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // TODO(bshe): Need to check the affected window's profile once multi-profile
20868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // is supported.
209d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  content::BrowserContext* context = GetBrowserContext();
21068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  extensions::EventRouter* router =
211d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      extensions::ExtensionSystem::GetForBrowserContext(context)->
212d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      event_router();
21368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
21468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!router->HasEventListener(
21568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          virtual_keyboard_private::OnTextInputBoxFocused::kEventName)) {
21668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
21768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
21868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
21968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  scoped_ptr<base::ListValue> event_args(new base::ListValue());
22068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  scoped_ptr<base::DictionaryValue> input_context(new base::DictionaryValue());
22168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  input_context->SetString("type",
22268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      Context::ToString(TextInputTypeToGeneratedInputTypeEnum(type)));
22368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  event_args->Append(input_context.release());
22468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
22568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  scoped_ptr<extensions::Event> event(new extensions::Event(
22668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      virtual_keyboard_private::OnTextInputBoxFocused::kEventName,
22768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      event_args.Pass()));
228d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  event->restrict_to_browser_context = context;
22968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  router->DispatchEventToExtension(kVirtualKeyboardExtensionID, event.Pass());
23068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
231