// Copyright (c) 2012 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 "chrome/browser/chromeos/input_method/input_method_manager_impl.h"

#include <stdint.h>

#include <algorithm>  // std::find
#include <memory>
#include <set>
#include <sstream>
#include <utility>

#include "ash/public/cpp/ash_features.h"
#include "base/bind.h"
#include "base/feature_list.h"
#include "base/hash.h"
#include "base/location.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/system/sys_info.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_process_platform_part_chromeos.h"
#include "chrome/browser/chromeos/input_method/candidate_window_controller.h"
#include "chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.h"
#include "chrome/browser/chromeos/language_preferences.h"
#include "chrome/browser/chromeos/login/session/user_session_manager.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
#include "chromeos/system/devicemode.h"
#include "components/prefs/pref_service.h"
#include "components/user_manager/user_manager.h"
#include "third_party/icu/source/common/unicode/uloc.h"
#include "ui/base/ime/chromeos/component_extension_ime_manager.h"
#include "ui/base/ime/chromeos/extension_ime_util.h"
#include "ui/base/ime/chromeos/fake_ime_keyboard.h"
#include "ui/base/ime/chromeos/ime_keyboard.h"
#include "ui/base/ime/chromeos/ime_keyboard_mus.h"
#include "ui/base/ime/chromeos/input_method_delegate.h"
#include "ui/base/ime/ime_bridge.h"
#include "ui/base/ui_base_features.h"
#include "ui/chromeos/ime/input_method_menu_item.h"
#include "ui/chromeos/ime/input_method_menu_manager.h"
#include "ui/keyboard/keyboard_controller.h"

namespace chromeos {
namespace input_method {

namespace {

enum InputMethodCategory {
  INPUT_METHOD_CATEGORY_UNKNOWN = 0,
  INPUT_METHOD_CATEGORY_XKB,  // XKB input methods
  INPUT_METHOD_CATEGORY_ZH,   // Chinese input methods
  INPUT_METHOD_CATEGORY_JA,   // Japanese input methods
  INPUT_METHOD_CATEGORY_KO,   // Korean input methods
  INPUT_METHOD_CATEGORY_M17N, // Multilingualization input methods
  INPUT_METHOD_CATEGORY_T13N, // Transliteration input methods
  INPUT_METHOD_CATEGORY_MAX
};

InputMethodCategory GetInputMethodCategory(const std::string& input_method_id,
                                           char* first_char = NULL) {
  const std::string component_id =
      extension_ime_util::GetComponentIDByInputMethodID(input_method_id);
  InputMethodCategory category = INPUT_METHOD_CATEGORY_UNKNOWN;
  char ch = 0;
  if (base::StartsWith(component_id, "xkb:", base::CompareCase::SENSITIVE)) {
    ch = component_id[4];
    category = INPUT_METHOD_CATEGORY_XKB;
  } else if (base::StartsWith(component_id, "zh-",
                              base::CompareCase::SENSITIVE)) {
    size_t pos = component_id.find("-t-i0-");
    if (pos > 0)
      pos += 6;
    ch = component_id[pos];
    category = INPUT_METHOD_CATEGORY_ZH;
  } else if (base::StartsWith(component_id, "nacl_mozc_",
                              base::CompareCase::SENSITIVE)) {
    ch = component_id[10];
    category = INPUT_METHOD_CATEGORY_JA;
  } else if (base::StartsWith(component_id, "hangul_",
                              base::CompareCase::SENSITIVE)) {
    ch = component_id[7];
    category = INPUT_METHOD_CATEGORY_KO;
  } else if (base::StartsWith(component_id, "vkd_",
                              base::CompareCase::SENSITIVE)) {
    ch = component_id[4];
    category = INPUT_METHOD_CATEGORY_M17N;
  } else if (component_id.find("-t-i0-") > 0) {
    ch = component_id[0];
    category = INPUT_METHOD_CATEGORY_T13N;
  }

  if (first_char)
    *first_char = ch;
  return category;
}

std::string KeysetToString(mojom::ImeKeyset keyset) {
  switch (keyset) {
    case mojom::ImeKeyset::kNone:
      return "";
    case mojom::ImeKeyset::kEmoji:
      return "emoji";
    case mojom::ImeKeyset::kHandwriting:
      return "hwt";
    case mojom::ImeKeyset::kVoice:
      return "voice";
  }
}

}  // namespace

// ------------------------ InputMethodManagerImpl::StateImpl

InputMethodManagerImpl::StateImpl::StateImpl(InputMethodManagerImpl* manager,
                                             Profile* profile)
    : profile(profile), manager_(manager), menu_activated(false) {}

InputMethodManagerImpl::StateImpl::~StateImpl() {
}

void InputMethodManagerImpl::StateImpl::InitFrom(const StateImpl& other) {
  last_used_input_method = other.last_used_input_method;
  current_input_method = other.current_input_method;

  active_input_method_ids = other.active_input_method_ids;

  pending_input_method_id = other.pending_input_method_id;

  enabled_extension_imes = other.enabled_extension_imes;
  extra_input_methods = other.extra_input_methods;
  menu_activated = other.menu_activated;
  allowed_keyboard_layout_input_method_ids =
      other.allowed_keyboard_layout_input_method_ids;
  input_view_url = other.input_view_url;
}

bool InputMethodManagerImpl::StateImpl::IsActive() const {
  return manager_->state_.get() == this;
}

std::string InputMethodManagerImpl::StateImpl::Dump() const {
  std::ostringstream os;

  os << "################# "
     << (profile ? profile->GetProfileUserName() : std::string("NULL"))
     << " #################\n";

  os << "last_used_input_method: '"
     << last_used_input_method.GetPreferredKeyboardLayout() << "'\n";
  os << "current_input_method: '"
     << current_input_method.GetPreferredKeyboardLayout() << "'\n";
  os << "active_input_method_ids (size=" << active_input_method_ids.size()
     << "):";
  for (size_t i = 0; i < active_input_method_ids.size(); ++i) {
    os << " '" << active_input_method_ids[i] << "',";
  }
  os << "\n";
  os << "enabled_extension_imes (size=" << enabled_extension_imes.size()
     << "):";
  for (size_t i = 0; i < enabled_extension_imes.size(); ++i) {
    os << " '" << enabled_extension_imes[i] << "'\n";
  }
  os << "\n";
  os << "extra_input_methods (size=" << extra_input_methods.size() << "):";
  for (std::map<std::string, InputMethodDescriptor>::const_iterator it =
           extra_input_methods.begin();
       it != extra_input_methods.end();
       ++it) {
    os << " '" << it->first << "' => '" << it->second.id() << "',\n";
  }
  os << "pending_input_method_id: '" << pending_input_method_id << "'\n";
  os << "input_view_url: '" << input_view_url << "'\n";

  return os.str();
}

scoped_refptr<InputMethodManager::State>
InputMethodManagerImpl::StateImpl::Clone() const {
  scoped_refptr<StateImpl> new_state(new StateImpl(this->manager_, profile));
  new_state->InitFrom(*this);
  return scoped_refptr<InputMethodManager::State>(new_state.get());
}

std::unique_ptr<InputMethodDescriptors>
InputMethodManagerImpl::StateImpl::GetActiveInputMethods() const {
  std::unique_ptr<InputMethodDescriptors> result(new InputMethodDescriptors);
  // Build the active input method descriptors from the active input
  // methods cache |active_input_method_ids|.
  for (size_t i = 0; i < active_input_method_ids.size(); ++i) {
    const std::string& input_method_id = active_input_method_ids[i];
    const InputMethodDescriptor* descriptor =
        manager_->util_.GetInputMethodDescriptorFromId(input_method_id);
    if (descriptor) {
      result->push_back(*descriptor);
    } else {
      std::map<std::string, InputMethodDescriptor>::const_iterator ix =
          extra_input_methods.find(input_method_id);
      if (ix != extra_input_methods.end())
        result->push_back(ix->second);
      else
        DVLOG(1) << "Descriptor is not found for: " << input_method_id;
    }
  }
  if (result->empty()) {
    // Initially |active_input_method_ids| is empty. browser_tests might take
    // this path.
    result->push_back(
        InputMethodUtil::GetFallbackInputMethodDescriptor());
  }
  return result;
}

const std::vector<std::string>&
InputMethodManagerImpl::StateImpl::GetActiveInputMethodIds() const {
  return active_input_method_ids;
}

size_t InputMethodManagerImpl::StateImpl::GetNumActiveInputMethods() const {
  return active_input_method_ids.size();
}

const InputMethodDescriptor*
InputMethodManagerImpl::StateImpl::GetInputMethodFromId(
    const std::string& input_method_id) const {
  const InputMethodDescriptor* ime =
      manager_->util_.GetInputMethodDescriptorFromId(input_method_id);
  if (!ime) {
    std::map<std::string, InputMethodDescriptor>::const_iterator ix =
        extra_input_methods.find(input_method_id);
    if (ix != extra_input_methods.end())
      ime = &ix->second;
  }
  return ime;
}

void InputMethodManagerImpl::StateImpl::EnableLoginLayouts(
    const std::string& language_code,
    const std::vector<std::string>& initial_layouts) {
  if (manager_->ui_session_ == STATE_TERMINATING)
    return;

  // First, hardware keyboard layout should be shown.
  std::vector<std::string> candidates =
      manager_->util_.GetHardwareLoginInputMethodIds();

  // Second, locale based input method should be shown.
  // Add input methods associated with the language.
  std::vector<std::string> layouts_from_locale;
  manager_->util_.GetInputMethodIdsFromLanguageCode(
      language_code, kKeyboardLayoutsOnly, &layouts_from_locale);
  candidates.insert(candidates.end(), layouts_from_locale.begin(),
                    layouts_from_locale.end());

  std::vector<std::string> layouts;
  // First, add the initial input method ID, if it's requested, to
  // layouts, so it appears first on the list of active input
  // methods at the input language status menu.
  for (size_t i = 0; i < initial_layouts.size(); ++i) {
    if (manager_->util_.IsValidInputMethodId(initial_layouts[i])) {
      if (manager_->IsLoginKeyboard(initial_layouts[i])) {
        if (IsInputMethodAllowed(initial_layouts[i])) {
          layouts.push_back(initial_layouts[i]);
        } else {
          DVLOG(1) << "EnableLoginLayouts: ignoring layout disallowd by policy:"
                   << initial_layouts[i];
        }
      } else {
        DVLOG(1)
            << "EnableLoginLayouts: ignoring non-login initial keyboard layout:"
            << initial_layouts[i];
      }
    } else if (!initial_layouts[i].empty()) {
      DVLOG(1) << "EnableLoginLayouts: ignoring non-keyboard or invalid ID: "
               << initial_layouts[i];
    }
  }

  // Add candidates to layouts, while skipping duplicates.
  for (size_t i = 0; i < candidates.size(); ++i) {
    const std::string& candidate = candidates[i];
    // Not efficient, but should be fine, as the two vectors are very
    // short (2-5 items).
    if (!base::ContainsValue(layouts, candidate) &&
        manager_->IsLoginKeyboard(candidate) &&
        IsInputMethodAllowed(candidate)) {
      layouts.push_back(candidate);
    }
  }

  manager_->MigrateInputMethods(&layouts);
  active_input_method_ids.swap(layouts);

  if (IsActive()) {
    // Initialize candidate window controller and widgets such as
    // candidate window, infolist and mode indicator.  Note, mode
    // indicator is used by only keyboard layout input methods.
    if (active_input_method_ids.size() > 1)
      manager_->MaybeInitializeCandidateWindowController();

    // you can pass empty |initial_layout|.
    ChangeInputMethod(initial_layouts.empty()
                          ? std::string()
                          : extension_ime_util::GetInputMethodIDByEngineID(
                                initial_layouts[0]),
                      false);
  }
}

void InputMethodManagerImpl::StateImpl::EnableLockScreenLayouts() {
  std::set<std::string> added_ids;

  const std::vector<std::string>& hardware_keyboard_ids =
      manager_->util_.GetHardwareLoginInputMethodIds();

  std::vector<std::string> new_active_input_method_ids;
  for (size_t i = 0; i < active_input_method_ids.size(); ++i) {
    const std::string& input_method_id = active_input_method_ids[i];
    // Skip if it's not a keyboard layout. Drop input methods including
    // extension ones. We need to keep all IMEs to support inputting on inline
    // reply on a notification if notifications on lock screen is enabled.
    if ((!ash::features::IsLockScreenInlineReplyEnabled() &&
         !manager_->IsLoginKeyboard(input_method_id)) ||
        added_ids.count(input_method_id)) {
      continue;
    }
    new_active_input_method_ids.push_back(input_method_id);
    added_ids.insert(input_method_id);
  }

  // We'll add the hardware keyboard if it's not included in
  // |active_input_method_ids| so that the user can always use the hardware
  // keyboard on the screen locker.
  for (size_t i = 0; i < hardware_keyboard_ids.size(); ++i) {
    if (added_ids.count(hardware_keyboard_ids[i]))
      continue;
    new_active_input_method_ids.push_back(hardware_keyboard_ids[i]);
    added_ids.insert(hardware_keyboard_ids[i]);
  }

  active_input_method_ids.swap(new_active_input_method_ids);

  // Re-check current_input_method.
  ChangeInputMethod(current_input_method.id(), false);
}

// Adds new input method to given list.
bool InputMethodManagerImpl::StateImpl::EnableInputMethodImpl(
    const std::string& input_method_id,
    std::vector<std::string>* new_active_input_method_ids) const {
  if (!IsInputMethodAllowed(input_method_id)) {
    DVLOG(1) << "EnableInputMethod: " << input_method_id << " is not allowed.";
    return false;
  }

  DCHECK(new_active_input_method_ids);
  if (!manager_->util_.IsValidInputMethodId(input_method_id)) {
    DVLOG(1) << "EnableInputMethod: Invalid ID: " << input_method_id;
    return false;
  }

  if (!base::ContainsValue(*new_active_input_method_ids, input_method_id))
    new_active_input_method_ids->push_back(input_method_id);

  return true;
}

bool InputMethodManagerImpl::StateImpl::EnableInputMethod(
    const std::string& input_method_id) {
  if (!EnableInputMethodImpl(input_method_id, &active_input_method_ids))
    return false;

  manager_->ReconfigureIMFramework(this);
  return true;
}

bool InputMethodManagerImpl::StateImpl::ReplaceEnabledInputMethods(
    const std::vector<std::string>& new_active_input_method_ids) {
  if (manager_->ui_session_ == STATE_TERMINATING)
    return false;

  // Filter unknown or obsolete IDs.
  std::vector<std::string> new_active_input_method_ids_filtered;

  for (size_t i = 0; i < new_active_input_method_ids.size(); ++i)
    EnableInputMethodImpl(new_active_input_method_ids[i],
                          &new_active_input_method_ids_filtered);

  if (new_active_input_method_ids_filtered.empty()) {
    DVLOG(1) << "ReplaceEnabledInputMethods: No valid input method ID";
    return false;
  }

  // Copy extension IDs to |new_active_input_method_ids_filtered|. We have to
  // keep relative order of the extension input method IDs.
  for (size_t i = 0; i < active_input_method_ids.size(); ++i) {
    const std::string& input_method_id = active_input_method_ids[i];
    if (extension_ime_util::IsExtensionIME(input_method_id))
      new_active_input_method_ids_filtered.push_back(input_method_id);
  }
  active_input_method_ids.swap(new_active_input_method_ids_filtered);
  manager_->MigrateInputMethods(&active_input_method_ids);

  manager_->ReconfigureIMFramework(this);

  // If |current_input_method| is no longer in |active_input_method_ids|,
  // ChangeInputMethod() picks the first one in |active_input_method_ids|.
  ChangeInputMethod(current_input_method.id(), false);

  // Record histogram for active input method count.
  UMA_HISTOGRAM_COUNTS_1M("InputMethod.ActiveCount",
                          active_input_method_ids.size());

  return true;
}

bool InputMethodManagerImpl::StateImpl::SetAllowedInputMethods(
    const std::vector<std::string>& new_allowed_input_method_ids,
    bool enable_allowed_input_methods) {
  allowed_keyboard_layout_input_method_ids.clear();
  for (auto input_method_id : new_allowed_input_method_ids) {
    std::string migrated_id =
        manager_->util_.MigrateInputMethod(input_method_id);
    if (manager_->util_.IsValidInputMethodId(migrated_id)) {
      allowed_keyboard_layout_input_method_ids.push_back(migrated_id);
    }
  }

  if (allowed_keyboard_layout_input_method_ids.empty()) {
    // None of the passed input methods were valid, so allow everything.
    return false;
  }

  std::vector<std::string> new_active_input_method_ids;
  if (enable_allowed_input_methods) {
    // Enable all allowed keyboard layout input methods. Leave all non-keyboard
    // input methods enabled.
    new_active_input_method_ids = allowed_keyboard_layout_input_method_ids;
    for (auto active_input_method_id : active_input_method_ids) {
      if (!manager_->util_.IsKeyboardLayout(active_input_method_id))
        new_active_input_method_ids.push_back(active_input_method_id);
    }
  } else {
    // Filter all currently active input methods and leave only non-keyboard or
    // allowed keyboard layouts. If no input method remains, take a fallback
    // keyboard layout.
    bool has_keyboard_layout = false;
    for (auto active_input_method_id : active_input_method_ids) {
      if (IsInputMethodAllowed(active_input_method_id)) {
        new_active_input_method_ids.push_back(active_input_method_id);
        has_keyboard_layout |=
            manager_->util_.IsKeyboardLayout(active_input_method_id);
      }
    }
    if (!has_keyboard_layout)
      new_active_input_method_ids.push_back(GetAllowedFallBackKeyboardLayout());
  }
  return ReplaceEnabledInputMethods(new_active_input_method_ids);
}

const std::vector<std::string>&
InputMethodManagerImpl::StateImpl::GetAllowedInputMethods() {
  return allowed_keyboard_layout_input_method_ids;
}

bool InputMethodManagerImpl::StateImpl::IsInputMethodAllowed(
    const std::string& input_method_id) const {
  // Every input method is allowed if SetAllowedKeyboardLayoutInputMethods has
  // not been called.
  if (allowed_keyboard_layout_input_method_ids.empty())
    return true;

  // We only restrict keyboard layouts.
  if (!manager_->util_.IsKeyboardLayout(input_method_id) &&
      !extension_ime_util::IsArcIME(input_method_id)) {
    return true;
  }

  return base::ContainsValue(allowed_keyboard_layout_input_method_ids,
                             input_method_id) ||
         base::ContainsValue(
             allowed_keyboard_layout_input_method_ids,
             manager_->util_.MigrateInputMethod(input_method_id));
}

std::string
InputMethodManagerImpl::StateImpl::GetAllowedFallBackKeyboardLayout() const {
  for (const std::string& hardware_id :
       manager_->util_.GetHardwareInputMethodIds()) {
    if (IsInputMethodAllowed(hardware_id))
      return hardware_id;
  }
  return allowed_keyboard_layout_input_method_ids[0];
}

void InputMethodManagerImpl::StateImpl::ChangeInputMethod(
    const std::string& input_method_id,
    bool show_message) {
  if (manager_->ui_session_ == STATE_TERMINATING)
    return;

  bool notify_menu = false;

  // Always lookup input method, even if it is the same as
  // |current_input_method| because If it is no longer in
  // |active_input_method_ids|, pick the first one in
  // |active_input_method_ids|.
  const InputMethodDescriptor* descriptor =
      manager_->LookupInputMethod(input_method_id, this);
  if (!descriptor) {
    descriptor = manager_->LookupInputMethod(
        manager_->util_.MigrateInputMethod(input_method_id), this);
    if (!descriptor) {
      LOG(ERROR) << "Can't find InputMethodDescriptor for \"" << input_method_id
                 << "\"";
      return;
    }
  }

  // For 3rd party IME, when the user just logged in, SetEnabledExtensionImes
  // happens after activating the 3rd party IME.
  // So here to record the 3rd party IME to be activated, and activate it
  // when SetEnabledExtensionImes happens later.
  if (MethodAwaitsExtensionLoad(input_method_id))
    pending_input_method_id = input_method_id;

  if (descriptor->id() != current_input_method.id()) {
    last_used_input_method = current_input_method;
    current_input_method = *descriptor;
    notify_menu = true;
  }

  // Always change input method even if it is the same.
  // TODO(komatsu): Revisit if this is neccessary.
  if (IsActive())
    manager_->ChangeInputMethodInternal(*descriptor, profile, show_message,
                                        notify_menu);
  manager_->RecordInputMethodUsage(current_input_method.id());
}

void InputMethodManagerImpl::StateImpl::ChangeInputMethodToJpKeyboard() {
  ChangeInputMethod(
      extension_ime_util::GetInputMethodIDByEngineID("xkb:jp::jpn"), true);
}

void InputMethodManagerImpl::StateImpl::ChangeInputMethodToJpIme() {
  ChangeInputMethod(
      extension_ime_util::GetInputMethodIDByEngineID("nacl_mozc_jp"), true);
}

void InputMethodManagerImpl::StateImpl::ToggleInputMethodForJpIme() {
  std::string jp_ime_id =
      extension_ime_util::GetInputMethodIDByEngineID("nacl_mozc_jp");
  ChangeInputMethod(
      GetCurrentInputMethod().id() == jp_ime_id
          ? extension_ime_util::GetInputMethodIDByEngineID("xkb:jp::jpn")
          : jp_ime_id,
      true);
}

bool InputMethodManagerImpl::StateImpl::MethodAwaitsExtensionLoad(
    const std::string& input_method_id) const {
  // For 3rd party IME, when the user just logged in, SetEnabledExtensionImes
  // happens after activating the 3rd party IME.
  // So here to record the 3rd party IME to be activated, and activate it
  // when SetEnabledExtensionImes happens later.
  return !InputMethodIsActivated(input_method_id) &&
         extension_ime_util::IsExtensionIME(input_method_id);
}

void InputMethodManagerImpl::StateImpl::AddInputMethodExtension(
    const std::string& extension_id,
    const InputMethodDescriptors& descriptors,
    ui::IMEEngineHandlerInterface* engine) {
  if (manager_->ui_session_ == STATE_TERMINATING)
    return;

  DCHECK(engine);

  manager_->engine_map_[profile][extension_id] = engine;
  VLOG(1) << "Add an engine for \"" << extension_id << "\"";

  bool contain = false;
  for (size_t i = 0; i < descriptors.size(); i++) {
    const InputMethodDescriptor& descriptor = descriptors[i];
    const std::string& id = descriptor.id();
    extra_input_methods[id] = descriptor;
    if (base::ContainsValue(enabled_extension_imes, id)) {
      if (!base::ContainsValue(active_input_method_ids, id)) {
        active_input_method_ids.push_back(id);
      } else {
        DVLOG(1) << "AddInputMethodExtension: already added: " << id << ", "
                 << descriptor.name();
      }
      contain = true;
    }
  }

  if (IsActive()) {
    if (extension_id == extension_ime_util::GetExtensionIDFromInputMethodID(
                            current_input_method.id())) {
      ui::IMEBridge::Get()->SetCurrentEngineHandler(engine);
      engine->Enable(extension_ime_util::GetComponentIDByInputMethodID(
          current_input_method.id()));
    }

    // Ensure that the input method daemon is running.
    if (contain)
      manager_->MaybeInitializeCandidateWindowController();
  }

  manager_->NotifyImeMenuListChanged();
  manager_->NotifyInputMethodExtensionAdded(extension_id);
}

void InputMethodManagerImpl::StateImpl::RemoveInputMethodExtension(
    const std::string& extension_id) {
  // Remove the active input methods with |extension_id|.
  std::vector<std::string> new_active_input_method_ids;
  for (size_t i = 0; i < active_input_method_ids.size(); ++i) {
    if (extension_id != extension_ime_util::GetExtensionIDFromInputMethodID(
                            active_input_method_ids[i]))
      new_active_input_method_ids.push_back(active_input_method_ids[i]);
  }
  active_input_method_ids.swap(new_active_input_method_ids);

  // Remove the extra input methods with |extension_id|.
  std::map<std::string, InputMethodDescriptor> new_extra_input_methods;
  for (std::map<std::string, InputMethodDescriptor>::iterator i =
           extra_input_methods.begin();
       i != extra_input_methods.end();
       ++i) {
    if (extension_id !=
        extension_ime_util::GetExtensionIDFromInputMethodID(i->first))
      new_extra_input_methods[i->first] = i->second;
  }
  extra_input_methods.swap(new_extra_input_methods);

  if (IsActive()) {
    if (ui::IMEBridge::Get()->GetCurrentEngineHandler() ==
        manager_->engine_map_[profile][extension_id]) {
      ui::IMEBridge::Get()->SetCurrentEngineHandler(NULL);
    }
    manager_->engine_map_[profile].erase(extension_id);
  }

  // If |current_input_method| is no longer in |active_input_method_ids|,
  // switch to the first one in |active_input_method_ids|.
  ChangeInputMethod(current_input_method.id(), false);
  manager_->NotifyInputMethodExtensionRemoved(extension_id);
}

void InputMethodManagerImpl::StateImpl::GetInputMethodExtensions(
    InputMethodDescriptors* result) {
  // Build the extension input method descriptors from the extra input
  // methods cache |extra_input_methods|.
  std::map<std::string, InputMethodDescriptor>::iterator iter;
  for (iter = extra_input_methods.begin(); iter != extra_input_methods.end();
       ++iter) {
    if (extension_ime_util::IsExtensionIME(iter->first) ||
        extension_ime_util::IsArcIME(iter->first)) {
      result->push_back(iter->second);
    }
  }
}

void InputMethodManagerImpl::StateImpl::SetEnabledExtensionImes(
    std::vector<std::string>* ids) {
  enabled_extension_imes.clear();
  enabled_extension_imes.insert(
      enabled_extension_imes.end(), ids->begin(), ids->end());
  bool active_imes_changed = false;
  bool switch_to_pending = false;

  for (std::map<std::string, InputMethodDescriptor>::iterator extra_iter =
           extra_input_methods.begin();
       extra_iter != extra_input_methods.end();
       ++extra_iter) {
    if (extension_ime_util::IsComponentExtensionIME(extra_iter->first))
      continue;  // Do not filter component extension.

    if (pending_input_method_id == extra_iter->first)
      switch_to_pending = true;

    std::vector<std::string>::iterator active_iter =
        std::find(active_input_method_ids.begin(),
                  active_input_method_ids.end(),
                  extra_iter->first);

    bool active = active_iter != active_input_method_ids.end();
    bool enabled =
        base::ContainsValue(enabled_extension_imes, extra_iter->first);

    if (active && !enabled)
      active_input_method_ids.erase(active_iter);

    if (!active && enabled)
      active_input_method_ids.push_back(extra_iter->first);

    if (active == !enabled)
      active_imes_changed = true;
  }

  if (IsActive() && active_imes_changed) {
    manager_->MaybeInitializeCandidateWindowController();

    if (switch_to_pending) {
      ChangeInputMethod(pending_input_method_id, false);
      pending_input_method_id.clear();
    } else {
      // If |current_input_method| is no longer in |active_input_method_ids_|,
      // switch to the first one in |active_input_method_ids_|.
      ChangeInputMethod(current_input_method.id(), false);
    }
  }
}

void InputMethodManagerImpl::StateImpl::SetInputMethodLoginDefaultFromVPD(
    const std::string& locale,
    const std::string& oem_layout) {
  std::string layout;
  if (!oem_layout.empty()) {
    // If the OEM layout information is provided, use it.
    layout = oem_layout;
  } else {
    // Otherwise, determine the hardware keyboard from the locale.
    std::vector<std::string> input_method_ids;
    if (manager_->util_.GetInputMethodIdsFromLanguageCode(
            locale,
            chromeos::input_method::kKeyboardLayoutsOnly,
            &input_method_ids)) {
      // The output list |input_method_ids| is sorted by popularity, hence
      // input_method_ids[0] now contains the most popular keyboard layout
      // for the given locale.
      DCHECK_GE(input_method_ids.size(), 1U);
      layout = input_method_ids[0];
    }
  }

  if (layout.empty())
    return;

  std::vector<std::string> layouts = base::SplitString(
      layout, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
  manager_->MigrateInputMethods(&layouts);

  PrefService* prefs = g_browser_process->local_state();
  prefs->SetString(prefs::kHardwareKeyboardLayout,
                   base::JoinString(layouts, ","));

  // This asks the file thread to save the prefs (i.e. doesn't block).
  // The latest values of Local State reside in memory so we can safely
  // get the value of kHardwareKeyboardLayout even if the data is not
  // yet saved to disk.
  prefs->CommitPendingWrite();

  manager_->util_.UpdateHardwareLayoutCache();

  EnableLoginLayouts(locale, layouts);
  manager_->LoadNecessaryComponentExtensions(this);
}

void InputMethodManagerImpl::StateImpl::SetInputMethodLoginDefault() {
  // Set up keyboards. For example, when |locale| is "en-US", enable US qwerty
  // and US dvorak keyboard layouts.
  if (g_browser_process && g_browser_process->local_state()) {
    const std::string locale = g_browser_process->GetApplicationLocale();
    std::vector<std::string> input_methods_to_be_enabled;
    if (!GetAllowedInputMethods().empty()) {
      // Prefer policy-set input methods.
      input_methods_to_be_enabled = GetAllowedInputMethods();
    } else {
      // If the preferred keyboard for the login screen has been saved, use it.
      PrefService* prefs = g_browser_process->local_state();
      std::string initial_input_method_id =
          prefs->GetString(chromeos::language_prefs::kPreferredKeyboardLayout);
      if (initial_input_method_id.empty()) {
        // If kPreferredKeyboardLayout is not specified, use the hardware
        // layout.
        input_methods_to_be_enabled =
            manager_->util_.GetHardwareLoginInputMethodIds();
      } else {
        input_methods_to_be_enabled.push_back(initial_input_method_id);
      }
    }
    EnableLoginLayouts(locale, input_methods_to_be_enabled);
    manager_->LoadNecessaryComponentExtensions(this);
  }
}

bool InputMethodManagerImpl::StateImpl::CanCycleInputMethod() const {
  // Sanity checks.
  if (active_input_method_ids.empty()) {
    DVLOG(1) << "active input method is empty";
    return false;
  }

  if (current_input_method.id().empty()) {
    DVLOG(1) << "current_input_method is unknown";
    return false;
  }

  return active_input_method_ids.size() > 1;
}

void InputMethodManagerImpl::StateImpl::SwitchToNextInputMethod() {
  if (!CanCycleInputMethod())
    return;

  // Find the next input method and switch to it.
  SwitchToNextInputMethodInternal(active_input_method_ids,
                                  current_input_method.id());
}

void InputMethodManagerImpl::StateImpl::SwitchToLastUsedInputMethod() {
  if (!CanCycleInputMethod())
    return;

  if (last_used_input_method.id().empty() ||
      last_used_input_method.id() == current_input_method.id()) {
    SwitchToNextInputMethod();
    return;
  }

  std::vector<std::string>::const_iterator iter =
      std::find(active_input_method_ids.begin(), active_input_method_ids.end(),
                last_used_input_method.id());
  if (iter == active_input_method_ids.end()) {
    // last_used_input_method is not supported.
    SwitchToNextInputMethod();
    return;
  }
  ChangeInputMethod(*iter, true);
}

void InputMethodManagerImpl::StateImpl::SwitchToNextInputMethodInternal(
    const std::vector<std::string>& input_method_ids,
    const std::string& current_input_methodid) {
  std::vector<std::string>::const_iterator iter = std::find(
      input_method_ids.begin(), input_method_ids.end(), current_input_methodid);
  if (iter != input_method_ids.end())
    ++iter;
  if (iter == input_method_ids.end())
    iter = input_method_ids.begin();
  ChangeInputMethod(*iter, true);
}

InputMethodDescriptor InputMethodManagerImpl::StateImpl::GetCurrentInputMethod()
    const {
  if (current_input_method.id().empty())
    return InputMethodUtil::GetFallbackInputMethodDescriptor();

  return current_input_method;
}

bool InputMethodManagerImpl::StateImpl::InputMethodIsActivated(
    const std::string& input_method_id) const {
  return base::ContainsValue(active_input_method_ids, input_method_id);
}

void InputMethodManagerImpl::StateImpl::EnableInputView() {
  input_view_url = current_input_method.input_view_url();
}

void InputMethodManagerImpl::StateImpl::DisableInputView() {
  input_view_url = GURL();
}

const GURL& InputMethodManagerImpl::StateImpl::GetInputViewUrl() const {
  return input_view_url;
}

// ------------------------ InputMethodManagerImpl
bool InputMethodManagerImpl::IsLoginKeyboard(
    const std::string& layout) const {
  return util_.IsLoginKeyboard(layout);
}

bool InputMethodManagerImpl::MigrateInputMethods(
    std::vector<std::string>* input_method_ids) {
  return util_.MigrateInputMethods(input_method_ids);
}

// Starts or stops the system input method framework as needed.
void InputMethodManagerImpl::ReconfigureIMFramework(
    InputMethodManagerImpl::StateImpl* state) {
  LoadNecessaryComponentExtensions(state);

  // Initialize candidate window controller and widgets such as
  // candidate window, infolist and mode indicator.  Note, mode
  // indicator is used by only keyboard layout input methods.
  if (state_.get() == state)
    MaybeInitializeCandidateWindowController();
}

void InputMethodManagerImpl::SetState(
    scoped_refptr<InputMethodManager::State> state) {
  DCHECK(state.get());
  InputMethodManagerImpl::StateImpl* new_impl_state =
      static_cast<InputMethodManagerImpl::StateImpl*>(state.get());

  state_ = new_impl_state;

  if (state_.get() && state_->active_input_method_ids.size()) {
    // Initialize candidate window controller and widgets such as
    // candidate window, infolist and mode indicator.  Note, mode
    // indicator is used by only keyboard layout input methods.
    MaybeInitializeCandidateWindowController();

    // Always call ChangeInputMethodInternal even when the input method id
    // remain unchanged, because onActivate event needs to be sent to IME
    // extension to update the current screen type correctly.
    ChangeInputMethodInternal(state_->current_input_method, state_->profile,
                              false /* show_message */, true /* notify_menu */);
  }
}

scoped_refptr<InputMethodManager::State>
InputMethodManagerImpl::GetActiveIMEState() {
  return scoped_refptr<InputMethodManager::State>(state_.get());
}

InputMethodManagerImpl::InputMethodManagerImpl(
    std::unique_ptr<InputMethodDelegate> delegate,
    bool enable_extension_loading)
    : delegate_(std::move(delegate)),
      ui_session_(STATE_LOGIN_SCREEN),
      state_(NULL),
      util_(delegate_.get()),
      component_extension_ime_manager_(new ComponentExtensionIMEManager()),
      enable_extension_loading_(enable_extension_loading),
      is_ime_menu_activated_(false),
      features_enabled_state_(InputMethodManager::FEATURE_ALL) {
  if (IsRunningAsSystemCompositor()) {
    keyboard_ = std::make_unique<ImeKeyboardMus>(
        g_browser_process->platform_part()->GetInputDeviceControllerClient());
  } else {
    keyboard_.reset(new FakeImeKeyboard());
  }

  // Initializes the system IME list.
  std::unique_ptr<ComponentExtensionIMEManagerDelegate> comp_delegate(
      new ComponentExtensionIMEManagerImpl());
  component_extension_ime_manager_->Initialize(std::move(comp_delegate));
  const InputMethodDescriptors& descriptors =
      component_extension_ime_manager_->GetAllIMEAsInputMethodDescriptor();
  util_.ResetInputMethods(descriptors);
  chromeos::UserAddingScreen::Get()->AddObserver(this);
}

InputMethodManagerImpl::~InputMethodManagerImpl() {
  if (candidate_window_controller_.get())
    candidate_window_controller_->RemoveObserver(this);
  chromeos::UserAddingScreen::Get()->RemoveObserver(this);
}

void InputMethodManagerImpl::RecordInputMethodUsage(
    const std::string& input_method_id) {
  UMA_HISTOGRAM_ENUMERATION("InputMethod.Category",
                            GetInputMethodCategory(input_method_id),
                            INPUT_METHOD_CATEGORY_MAX);
  base::UmaHistogramSparse("InputMethod.ID2",
                           static_cast<int32_t>(base::Hash(input_method_id)));
}

void InputMethodManagerImpl::AddObserver(
    InputMethodManager::Observer* observer) {
  observers_.AddObserver(observer);
  observer->OnExtraInputEnabledStateChange(
      base::FeatureList::IsEnabled(features::kEHVInputOnImeMenu),
      features_enabled_state_ & InputMethodManager::FEATURE_EMOJI,
      features_enabled_state_ & InputMethodManager::FEATURE_HANDWRITING,
      features_enabled_state_ & InputMethodManager::FEATURE_VOICE);
}

void InputMethodManagerImpl::AddCandidateWindowObserver(
    InputMethodManager::CandidateWindowObserver* observer) {
  candidate_window_observers_.AddObserver(observer);
}

void InputMethodManagerImpl::AddImeMenuObserver(
    InputMethodManager::ImeMenuObserver* observer) {
  ime_menu_observers_.AddObserver(observer);
}

void InputMethodManagerImpl::RemoveObserver(
    InputMethodManager::Observer* observer) {
  observers_.RemoveObserver(observer);
}

void InputMethodManagerImpl::RemoveCandidateWindowObserver(
    InputMethodManager::CandidateWindowObserver* observer) {
  candidate_window_observers_.RemoveObserver(observer);
}

void InputMethodManagerImpl::RemoveImeMenuObserver(
    InputMethodManager::ImeMenuObserver* observer) {
  ime_menu_observers_.RemoveObserver(observer);
}

InputMethodManager::UISessionState InputMethodManagerImpl::GetUISessionState() {
  return ui_session_;
}

void InputMethodManagerImpl::SetUISessionState(UISessionState new_ui_session) {
  ui_session_ = new_ui_session;
  if (ui_session_ == STATE_TERMINATING && candidate_window_controller_.get())
    candidate_window_controller_.reset();
}

void InputMethodManagerImpl::OnUserAddingStarted() {
  if (ui_session_ == STATE_BROWSER_SCREEN)
    SetUISessionState(STATE_SECONDARY_LOGIN_SCREEN);
}

void InputMethodManagerImpl::OnUserAddingFinished() {
  if (ui_session_ == STATE_SECONDARY_LOGIN_SCREEN)
    SetUISessionState(STATE_BROWSER_SCREEN);
}

std::unique_ptr<InputMethodDescriptors>
InputMethodManagerImpl::GetSupportedInputMethods() const {
  return std::unique_ptr<InputMethodDescriptors>(new InputMethodDescriptors);
}

const InputMethodDescriptor* InputMethodManagerImpl::LookupInputMethod(
    const std::string& input_method_id,
    InputMethodManagerImpl::StateImpl* state) {
  DCHECK(state);

  std::string input_method_id_to_switch = input_method_id;

  // Sanity check
  if (!state->InputMethodIsActivated(input_method_id)) {
    std::unique_ptr<InputMethodDescriptors> input_methods(
        state->GetActiveInputMethods());
    DCHECK(!input_methods->empty());
    input_method_id_to_switch = input_methods->at(0).id();
    if (!input_method_id.empty()) {
      DVLOG(1) << "Can't change the current input method to "
               << input_method_id << " since the engine is not enabled. "
               << "Switch to " << input_method_id_to_switch << " instead.";
    }
  }

  const InputMethodDescriptor* descriptor = NULL;
  if (extension_ime_util::IsExtensionIME(input_method_id_to_switch) ||
      extension_ime_util::IsArcIME(input_method_id_to_switch)) {
    DCHECK(state->extra_input_methods.find(input_method_id_to_switch) !=
           state->extra_input_methods.end());
    descriptor = &(state->extra_input_methods[input_method_id_to_switch]);
  } else {
    descriptor =
        util_.GetInputMethodDescriptorFromId(input_method_id_to_switch);
    if (!descriptor)
      LOG(ERROR) << "Unknown input method id: " << input_method_id_to_switch;
  }
  DCHECK(descriptor);
  return descriptor;
}

void InputMethodManagerImpl::ChangeInputMethodInternal(
    const InputMethodDescriptor& descriptor,
    Profile* profile,
    bool show_message,
    bool notify_menu) {
  // No need to switch input method when terminating.
  if (ui_session_ == STATE_TERMINATING) {
    VLOG(1) << "No need to switch input method when terminating.";
    return;
  }

  if (candidate_window_controller_.get())
    candidate_window_controller_->Hide();

  if (notify_menu) {
    // Clear property list.  Property list would be updated by
    // extension IMEs via IMEEngineHandlerInterface::(Set|Update)MenuItems.
    // If the current input method is a keyboard layout, empty
    // properties are sufficient.
    const ui::ime::InputMethodMenuItemList empty_menu_item_list;
    ui::ime::InputMethodMenuManager* input_method_menu_manager =
        ui::ime::InputMethodMenuManager::GetInstance();
    input_method_menu_manager->SetCurrentInputMethodMenuItemList(
            empty_menu_item_list);
  }

  // Disable the current engine handler.
  ui::IMEEngineHandlerInterface* engine =
      ui::IMEBridge::Get()->GetCurrentEngineHandler();
  if (engine)
    engine->Disable();

  // Configure the next engine handler.
  // This must be after |current_input_method| has been set to new input
  // method, because engine's Enable() method needs to access it.
  const std::string& extension_id =
      extension_ime_util::GetExtensionIDFromInputMethodID(descriptor.id());
  const std::string& component_id =
      extension_ime_util::GetComponentIDByInputMethodID(descriptor.id());
  if (engine_map_.find(profile) == engine_map_.end() ||
      engine_map_[profile].find(extension_id) == engine_map_[profile].end()) {
    LOG_IF(ERROR, base::SysInfo::IsRunningOnChromeOS())
        << "IMEEngine for \"" << extension_id << "\" is not registered";
  }
  engine = engine_map_[profile][extension_id];

  ui::IMEBridge::Get()->SetCurrentEngineHandler(engine);

  if (engine) {
    engine->Enable(component_id);
  } else {
    // If no engine to enable, cancel the virtual keyboard url override so that
    // it can use the fallback system virtual keyboard UI.
    state_->DisableInputView();
    ReloadKeyboard();
  }

  // Change the keyboard layout to a preferred layout for the input method.
  if (!keyboard_->SetCurrentKeyboardLayoutByName(
          descriptor.GetPreferredKeyboardLayout())) {
    LOG(ERROR) << "Failed to change keyboard layout to "
               << descriptor.GetPreferredKeyboardLayout();
  }

  // Update input method indicators (e.g. "US", "DV") in Chrome windows.
  for (auto& observer : observers_)
    observer.InputMethodChanged(this, profile, show_message);
  // Update the current input method in IME menu.
  NotifyImeMenuListChanged();
}

void InputMethodManagerImpl::LoadNecessaryComponentExtensions(
    InputMethodManagerImpl::StateImpl* state) {
  // Load component extensions but also update |active_input_method_ids| as
  // some component extension IMEs may have been removed from the Chrome OS
  // image. If specified component extension IME no longer exists, falling back
  // to an existing IME.
  DCHECK(state);
  std::vector<std::string> unfiltered_input_method_ids;
  unfiltered_input_method_ids.swap(state->active_input_method_ids);
  for (size_t i = 0; i < unfiltered_input_method_ids.size(); ++i) {
    if (!extension_ime_util::IsComponentExtensionIME(
        unfiltered_input_method_ids[i])) {
      // Legacy IMEs or xkb layouts are alwayes active.
      state->active_input_method_ids.push_back(unfiltered_input_method_ids[i]);
    } else if (component_extension_ime_manager_->IsWhitelisted(
        unfiltered_input_method_ids[i])) {
      if (enable_extension_loading_) {
        component_extension_ime_manager_->LoadComponentExtensionIME(
            state->profile, unfiltered_input_method_ids[i]);
      }

      state->active_input_method_ids.push_back(unfiltered_input_method_ids[i]);
    }
  }
}

void InputMethodManagerImpl::ActivateInputMethodMenuItem(
    const std::string& key) {
  DCHECK(!key.empty());

  if (ui::ime::InputMethodMenuManager::GetInstance()->
      HasInputMethodMenuItemForKey(key)) {
    ui::IMEEngineHandlerInterface* engine =
        ui::IMEBridge::Get()->GetCurrentEngineHandler();
    if (engine)
      engine->PropertyActivate(key);
    return;
  }

  DVLOG(1) << "ActivateInputMethodMenuItem: unknown key: " << key;
}

bool InputMethodManagerImpl::IsISOLevel5ShiftUsedByCurrentInputMethod() const {
  return keyboard_->IsISOLevel5ShiftAvailable();
}

bool InputMethodManagerImpl::IsAltGrUsedByCurrentInputMethod() const {
  return keyboard_->IsAltGrAvailable();
}

ImeKeyboard* InputMethodManagerImpl::GetImeKeyboard() {
  return keyboard_.get();
}

InputMethodUtil* InputMethodManagerImpl::GetInputMethodUtil() {
  return &util_;
}

ComponentExtensionIMEManager*
    InputMethodManagerImpl::GetComponentExtensionIMEManager() {
  return component_extension_ime_manager_.get();
}

scoped_refptr<InputMethodManager::State> InputMethodManagerImpl::CreateNewState(
    Profile* profile) {
  StateImpl* new_state = new StateImpl(this, profile);

  // Active IM should be set to owner/user's default.
  PrefService* prefs = g_browser_process->local_state();
  PrefService* user_prefs = profile ? profile->GetPrefs() : nullptr;
  std::string initial_input_method_id;
  if (user_prefs) {
    initial_input_method_id =
        user_prefs->GetString(prefs::kLanguageCurrentInputMethod);
  }
  if (initial_input_method_id.empty()) {
    initial_input_method_id =
        prefs->GetString(chromeos::language_prefs::kPreferredKeyboardLayout);
  }

  const InputMethodDescriptor* descriptor =
      GetInputMethodUtil()->GetInputMethodDescriptorFromId(
          initial_input_method_id.empty()
              ? GetInputMethodUtil()->GetFallbackInputMethodDescriptor().id()
              : initial_input_method_id);
  if (descriptor) {
    new_state->active_input_method_ids.push_back(descriptor->id());
    new_state->current_input_method = *descriptor;
  }
  return scoped_refptr<InputMethodManager::State>(new_state);
}

void InputMethodManagerImpl::SetCandidateWindowControllerForTesting(
    CandidateWindowController* candidate_window_controller) {
  candidate_window_controller_.reset(candidate_window_controller);
  candidate_window_controller_->AddObserver(this);
}

void InputMethodManagerImpl::SetImeKeyboardForTesting(ImeKeyboard* keyboard) {
  keyboard_.reset(keyboard);
}

void InputMethodManagerImpl::InitializeComponentExtensionForTesting(
    std::unique_ptr<ComponentExtensionIMEManagerDelegate> delegate) {
  component_extension_ime_manager_->Initialize(std::move(delegate));
  util_.ResetInputMethods(
      component_extension_ime_manager_->GetAllIMEAsInputMethodDescriptor());
}

void InputMethodManagerImpl::CandidateClicked(int index) {
  ui::IMEEngineHandlerInterface* engine =
      ui::IMEBridge::Get()->GetCurrentEngineHandler();
  if (engine)
    engine->CandidateClicked(index);
}

void InputMethodManagerImpl::CandidateWindowOpened() {
  for (auto& observer : candidate_window_observers_)
    observer.CandidateWindowOpened(this);
}

void InputMethodManagerImpl::CandidateWindowClosed() {
  for (auto& observer : candidate_window_observers_)
    observer.CandidateWindowClosed(this);
}

void InputMethodManagerImpl::ImeMenuActivationChanged(bool is_active) {
  // Saves the state that whether the expanded IME menu has been activated by
  // users. This method is only called when the preference is changing.
  state_->menu_activated = is_active;
  MaybeNotifyImeMenuActivationChanged();
}

void InputMethodManagerImpl::NotifyInputMethodExtensionAdded(
    const std::string& extension_id) {
  for (auto& observer : observers_)
    observer.OnInputMethodExtensionAdded(extension_id);
}

void InputMethodManagerImpl::NotifyInputMethodExtensionRemoved(
    const std::string& extension_id) {
  for (auto& observer : observers_)
    observer.OnInputMethodExtensionRemoved(extension_id);
}

void InputMethodManagerImpl::NotifyImeMenuListChanged() {
  for (auto& observer : ime_menu_observers_)
    observer.ImeMenuListChanged();
}

void InputMethodManagerImpl::MaybeInitializeCandidateWindowController() {
  if (candidate_window_controller_.get())
    return;

  candidate_window_controller_.reset(
      CandidateWindowController::CreateCandidateWindowController());
  candidate_window_controller_->AddObserver(this);
}

void InputMethodManagerImpl::NotifyImeMenuItemsChanged(
    const std::string& engine_id,
    const std::vector<InputMethodManager::MenuItem>& items) {
  for (auto& observer : ime_menu_observers_)
    observer.ImeMenuItemsChanged(engine_id, items);
}

void InputMethodManagerImpl::MaybeNotifyImeMenuActivationChanged() {
  if (is_ime_menu_activated_ == state_->menu_activated)
    return;

  is_ime_menu_activated_ = state_->menu_activated;
  for (auto& observer : ime_menu_observers_)
    observer.ImeMenuActivationChanged(is_ime_menu_activated_);
  UMA_HISTOGRAM_BOOLEAN("InputMethod.ImeMenu.ActivationChanged",
                        is_ime_menu_activated_);
}

void InputMethodManagerImpl::OverrideKeyboardKeyset(mojom::ImeKeyset keyset) {
  GURL url = state_->GetInputViewUrl();

  // If fails to find ref or tag "id" in the ref, it means the current IME is
  // not system IME, and we don't support show emoji, handwriting or voice
  // input for such IME extension.
  if (!url.has_ref())
    return;
  std::string overridden_ref = url.ref();

  auto i = overridden_ref.find("id=");
  if (i == std::string::npos)
    return;

  if (keyset == mojom::ImeKeyset::kNone) {
    // Resets the url as the input method default url and notify the hash
    // changed to VK.
    state_->input_view_url = state_->current_input_method.input_view_url();
    ReloadKeyboard();
    return;
  }

  // For system IME extension, the input view url is overridden as:
  // chrome-extension://${extension_id}/inputview.html#id=us.compact.qwerty
  // &language=en-US&passwordLayout=us.compact.qwerty&name=keyboard_us
  // Fow emoji, handwriting and voice input, we append the keyset to the end of
  // id like: id=${keyset}.emoji/hwt/voice.
  auto j = overridden_ref.find("&", i + 1);
  if (j == std::string::npos) {
    overridden_ref += "." + KeysetToString(keyset);
  } else {
    overridden_ref.replace(j, 0, "." + KeysetToString(keyset));
  }

  GURL::Replacements replacements;
  replacements.SetRefStr(overridden_ref);
  state_->input_view_url = url.ReplaceComponents(replacements);

  ReloadKeyboard();
}

void InputMethodManagerImpl::SetImeMenuFeatureEnabled(ImeMenuFeature feature,
                                                      bool enabled) {
  const uint32_t original_state = features_enabled_state_;
  if (enabled)
    features_enabled_state_ |= feature;
  else
    features_enabled_state_ &= ~feature;
  if (original_state != features_enabled_state_)
    NotifyObserversImeExtraInputStateChange();
}

bool InputMethodManagerImpl::GetImeMenuFeatureEnabled(
    ImeMenuFeature feature) const {
  return features_enabled_state_ & feature;
}

void InputMethodManagerImpl::NotifyObserversImeExtraInputStateChange() {
  for (auto& observer : observers_) {
    const bool is_ehv_enabled =
        base::FeatureList::IsEnabled(features::kEHVInputOnImeMenu);
    const bool is_emoji_enabled =
        (features_enabled_state_ & InputMethodManager::FEATURE_EMOJI);
    const bool is_handwriting_enabled =
        (features_enabled_state_ & InputMethodManager::FEATURE_HANDWRITING);
    const bool is_voice_enabled =
        (features_enabled_state_ & InputMethodManager::FEATURE_VOICE);
    observer.OnExtraInputEnabledStateChange(is_ehv_enabled, is_emoji_enabled,
                                            is_handwriting_enabled,
                                            is_voice_enabled);
  }
}

ui::InputMethodKeyboardController*
InputMethodManagerImpl::GetInputMethodKeyboardController() {
  // TODO(stevenjb/shuchen): Fix this for Mash. https://crbug.com/756059
  if (features::IsMultiProcessMash())
    return nullptr;
  // Callers expect a nullptr when the keyboard is disabled. See
  // https://crbug.com/850020.
  if (!keyboard::KeyboardController::HasInstance() ||
      !keyboard::KeyboardController::Get()->IsEnabled()) {
    return nullptr;
  }
  return keyboard::KeyboardController::Get()
      ->input_method_keyboard_controller();
}

void InputMethodManagerImpl::ReloadKeyboard() {
  auto* keyboard_client = ChromeKeyboardControllerClient::Get();
  if (keyboard_client->is_keyboard_enabled())
    keyboard_client->ReloadKeyboardIfNeeded();
}

}  // namespace input_method
}  // namespace chromeos
