OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/input_method/input_method_manager_impl.h" | 5 #include "chrome/browser/chromeos/input_method/input_method_manager_impl.h" |
6 | 6 |
7 #include <algorithm> // std::find | 7 #include <algorithm> // std::find |
8 | 8 |
9 #include <sstream> | 9 #include <sstream> |
10 | 10 |
11 #include "ash/ime/input_method_menu_item.h" | 11 #include "ash/ime/input_method_menu_item.h" |
12 #include "ash/ime/input_method_menu_manager.h" | 12 #include "ash/ime/input_method_menu_manager.h" |
13 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
14 #include "base/bind.h" | 14 #include "base/bind.h" |
15 #include "base/location.h" | 15 #include "base/location.h" |
16 #include "base/memory/scoped_ptr.h" | 16 #include "base/memory/scoped_ptr.h" |
| 17 #include "base/metrics/histogram.h" |
| 18 #include "base/metrics/sparse_histogram.h" |
17 #include "base/prefs/pref_service.h" | 19 #include "base/prefs/pref_service.h" |
18 #include "base/strings/string_split.h" | 20 #include "base/strings/string_split.h" |
19 #include "base/strings/string_util.h" | 21 #include "base/strings/string_util.h" |
20 #include "base/strings/stringprintf.h" | 22 #include "base/strings/stringprintf.h" |
21 #include "base/sys_info.h" | 23 #include "base/sys_info.h" |
22 #include "chrome/browser/browser_process.h" | 24 #include "chrome/browser/browser_process.h" |
23 #include "chrome/browser/chromeos/input_method/candidate_window_controller.h" | 25 #include "chrome/browser/chromeos/input_method/candidate_window_controller.h" |
24 #include "chrome/browser/chromeos/input_method/component_extension_ime_manager_i
mpl.h" | 26 #include "chrome/browser/chromeos/input_method/component_extension_ime_manager_i
mpl.h" |
25 #include "chrome/browser/chromeos/input_method/input_method_engine.h" | 27 #include "chrome/browser/chromeos/input_method/input_method_engine.h" |
26 #include "chrome/browser/chromeos/language_preferences.h" | 28 #include "chrome/browser/chromeos/language_preferences.h" |
(...skipping 16 matching lines...) Expand all Loading... |
43 namespace input_method { | 45 namespace input_method { |
44 | 46 |
45 namespace { | 47 namespace { |
46 | 48 |
47 bool Contains(const std::vector<std::string>& container, | 49 bool Contains(const std::vector<std::string>& container, |
48 const std::string& value) { | 50 const std::string& value) { |
49 return std::find(container.begin(), container.end(), value) != | 51 return std::find(container.begin(), container.end(), value) != |
50 container.end(); | 52 container.end(); |
51 } | 53 } |
52 | 54 |
| 55 enum InputMethodCategory { |
| 56 INPUT_METHOD_CATEGORY_UNKNOWN = 0, |
| 57 INPUT_METHOD_CATEGORY_XKB, // XKB input methods |
| 58 INPUT_METHOD_CATEGORY_ZH, // Chinese input methods |
| 59 INPUT_METHOD_CATEGORY_JA, // Japanese input methods |
| 60 INPUT_METHOD_CATEGORY_KO, // Korean input methods |
| 61 INPUT_METHOD_CATEGORY_M17N, // Multilingualization input methods |
| 62 INPUT_METHOD_CATEGORY_T13N, // Transliteration input methods |
| 63 INPUT_METHOD_CATEGORY_MAX |
| 64 }; |
| 65 |
| 66 InputMethodCategory GetInputMethodCategory(const std::string& input_method_id, |
| 67 char* first_char = NULL) { |
| 68 const std::string component_id = |
| 69 extension_ime_util::GetComponentIDByInputMethodID(input_method_id); |
| 70 InputMethodCategory category = INPUT_METHOD_CATEGORY_UNKNOWN; |
| 71 char ch = 0; |
| 72 if (StartsWithASCII(component_id, "xkb:", true)) { |
| 73 ch = component_id[4]; |
| 74 category = INPUT_METHOD_CATEGORY_XKB; |
| 75 } else if (StartsWithASCII(component_id, "zh-", true)) { |
| 76 size_t pos = component_id.find("-t-i0-"); |
| 77 if (pos > 0) |
| 78 pos += 6; |
| 79 ch = component_id[pos]; |
| 80 category = INPUT_METHOD_CATEGORY_ZH; |
| 81 } else if (StartsWithASCII(component_id, "nacl_mozc_", true)) { |
| 82 ch = component_id[10]; |
| 83 category = INPUT_METHOD_CATEGORY_JA; |
| 84 } else if (StartsWithASCII(component_id, "hangul_", true)) { |
| 85 ch = component_id[7]; |
| 86 category = INPUT_METHOD_CATEGORY_KO; |
| 87 } else if (StartsWithASCII(component_id, "vkd_", true)) { |
| 88 ch = component_id[4]; |
| 89 category = INPUT_METHOD_CATEGORY_M17N; |
| 90 } else if (component_id.find("-t-i0-") > 0) { |
| 91 ch = component_id[0]; |
| 92 category = INPUT_METHOD_CATEGORY_T13N; |
| 93 } |
| 94 |
| 95 if (first_char) |
| 96 *first_char = ch; |
| 97 return category; |
| 98 } |
| 99 |
53 } // namespace | 100 } // namespace |
54 | 101 |
55 // ------------------------ InputMethodManagerImpl::StateImpl | 102 // ------------------------ InputMethodManagerImpl::StateImpl |
56 | 103 |
57 InputMethodManagerImpl::StateImpl::StateImpl(InputMethodManagerImpl* manager, | 104 InputMethodManagerImpl::StateImpl::StateImpl(InputMethodManagerImpl* manager, |
58 Profile* profile) | 105 Profile* profile) |
59 : profile(profile), manager_(manager) { | 106 : profile(profile), manager_(manager) { |
60 } | 107 } |
61 | 108 |
62 InputMethodManagerImpl::StateImpl::~StateImpl() { | 109 InputMethodManagerImpl::StateImpl::~StateImpl() { |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
322 new_active_input_method_ids_filtered.push_back(input_method_id); | 369 new_active_input_method_ids_filtered.push_back(input_method_id); |
323 } | 370 } |
324 active_input_method_ids.swap(new_active_input_method_ids_filtered); | 371 active_input_method_ids.swap(new_active_input_method_ids_filtered); |
325 manager_->MigrateInputMethods(&active_input_method_ids); | 372 manager_->MigrateInputMethods(&active_input_method_ids); |
326 | 373 |
327 manager_->ReconfigureIMFramework(this); | 374 manager_->ReconfigureIMFramework(this); |
328 | 375 |
329 // If |current_input_method| is no longer in |active_input_method_ids|, | 376 // If |current_input_method| is no longer in |active_input_method_ids|, |
330 // ChangeInputMethod() picks the first one in |active_input_method_ids|. | 377 // ChangeInputMethod() picks the first one in |active_input_method_ids|. |
331 ChangeInputMethod(current_input_method.id(), false); | 378 ChangeInputMethod(current_input_method.id(), false); |
| 379 |
| 380 // Record histogram for active input method count. |
| 381 UMA_HISTOGRAM_COUNTS("InputMethod.ActiveCount", |
| 382 active_input_method_ids.size()); |
| 383 |
332 return true; | 384 return true; |
333 } | 385 } |
334 | 386 |
335 void InputMethodManagerImpl::StateImpl::ChangeInputMethod( | 387 void InputMethodManagerImpl::StateImpl::ChangeInputMethod( |
336 const std::string& input_method_id, | 388 const std::string& input_method_id, |
337 bool show_message) { | 389 bool show_message) { |
338 if (manager_->ui_session_ == STATE_TERMINATING) | 390 if (manager_->ui_session_ == STATE_TERMINATING) |
339 return; | 391 return; |
340 | 392 |
341 bool notify_menu = false; | 393 bool notify_menu = false; |
(...skipping 13 matching lines...) Expand all Loading... |
355 if (descriptor->id() != current_input_method.id()) { | 407 if (descriptor->id() != current_input_method.id()) { |
356 previous_input_method = current_input_method; | 408 previous_input_method = current_input_method; |
357 current_input_method = *descriptor; | 409 current_input_method = *descriptor; |
358 notify_menu = true; | 410 notify_menu = true; |
359 } | 411 } |
360 | 412 |
361 // Always change input method even if it is the same. | 413 // Always change input method even if it is the same. |
362 // TODO(komatsu): Revisit if this is neccessary. | 414 // TODO(komatsu): Revisit if this is neccessary. |
363 if (IsActive()) | 415 if (IsActive()) |
364 manager_->ChangeInputMethodInternal(*descriptor, show_message, notify_menu); | 416 manager_->ChangeInputMethodInternal(*descriptor, show_message, notify_menu); |
| 417 manager_->RecordInputMethodUsage(current_input_method.id()); |
365 } | 418 } |
366 | 419 |
367 bool InputMethodManagerImpl::StateImpl::MethodAwaitsExtensionLoad( | 420 bool InputMethodManagerImpl::StateImpl::MethodAwaitsExtensionLoad( |
368 const std::string& input_method_id) const { | 421 const std::string& input_method_id) const { |
369 // For 3rd party IME, when the user just logged in, SetEnabledExtensionImes | 422 // For 3rd party IME, when the user just logged in, SetEnabledExtensionImes |
370 // happens after activating the 3rd party IME. | 423 // happens after activating the 3rd party IME. |
371 // So here to record the 3rd party IME to be activated, and activate it | 424 // So here to record the 3rd party IME to be activated, and activate it |
372 // when SetEnabledExtensionImes happens later. | 425 // when SetEnabledExtensionImes happens later. |
373 return !InputMethodIsActivated(input_method_id) && | 426 return !InputMethodIsActivated(input_method_id) && |
374 extension_ime_util::IsExtensionIME(input_method_id); | 427 extension_ime_util::IsExtensionIME(input_method_id); |
(...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
785 enable_extension_loading_(enable_extension_loading) { | 838 enable_extension_loading_(enable_extension_loading) { |
786 if (base::SysInfo::IsRunningOnChromeOS()) | 839 if (base::SysInfo::IsRunningOnChromeOS()) |
787 keyboard_.reset(ImeKeyboard::Create()); | 840 keyboard_.reset(ImeKeyboard::Create()); |
788 else | 841 else |
789 keyboard_.reset(new FakeImeKeyboard()); | 842 keyboard_.reset(new FakeImeKeyboard()); |
790 | 843 |
791 // Initializes the system IME list. | 844 // Initializes the system IME list. |
792 scoped_ptr<ComponentExtensionIMEManagerDelegate> comp_delegate( | 845 scoped_ptr<ComponentExtensionIMEManagerDelegate> comp_delegate( |
793 new ComponentExtensionIMEManagerImpl()); | 846 new ComponentExtensionIMEManagerImpl()); |
794 component_extension_ime_manager_->Initialize(comp_delegate.Pass()); | 847 component_extension_ime_manager_->Initialize(comp_delegate.Pass()); |
795 util_.ResetInputMethods( | 848 const InputMethodDescriptors& descriptors = |
796 component_extension_ime_manager_->GetAllIMEAsInputMethodDescriptor()); | 849 component_extension_ime_manager_->GetAllIMEAsInputMethodDescriptor(); |
| 850 util_.ResetInputMethods(descriptors); |
| 851 |
| 852 // Initializes the stat id map. |
| 853 std::map<int, std::vector<std::string> > buckets; |
| 854 for (InputMethodDescriptors::const_iterator it = descriptors.begin(); |
| 855 it != descriptors.end(); ++it) { |
| 856 char first_char; |
| 857 int cat_id = static_cast<int>( |
| 858 GetInputMethodCategory(it->id(), &first_char)); |
| 859 int key = cat_id * 1000 + first_char; |
| 860 buckets[key].push_back(it->id()); |
| 861 } |
| 862 for (std::map<int, std::vector<std::string>>::iterator i = |
| 863 buckets.begin(); i != buckets.end(); ++i) { |
| 864 std::sort(i->second.begin(), i->second.end()); |
| 865 for (size_t j = 0; j < i->second.size() && j < 100; ++j) { |
| 866 int key = i->first * 100 + j; |
| 867 stat_id_map_[i->second[j]] = key; |
| 868 } |
| 869 } |
797 } | 870 } |
798 | 871 |
799 InputMethodManagerImpl::~InputMethodManagerImpl() { | 872 InputMethodManagerImpl::~InputMethodManagerImpl() { |
800 if (candidate_window_controller_.get()) | 873 if (candidate_window_controller_.get()) |
801 candidate_window_controller_->RemoveObserver(this); | 874 candidate_window_controller_->RemoveObserver(this); |
802 } | 875 } |
803 | 876 |
| 877 void InputMethodManagerImpl::RecordInputMethodUsage( |
| 878 std::string input_method_id) { |
| 879 UMA_HISTOGRAM_ENUMERATION("InputMethod.Category", |
| 880 GetInputMethodCategory(input_method_id), |
| 881 INPUT_METHOD_CATEGORY_MAX); |
| 882 UMA_HISTOGRAM_SPARSE_SLOWLY("InputMethod.ID", |
| 883 stat_id_map_[input_method_id]); |
| 884 } |
| 885 |
804 void InputMethodManagerImpl::AddObserver( | 886 void InputMethodManagerImpl::AddObserver( |
805 InputMethodManager::Observer* observer) { | 887 InputMethodManager::Observer* observer) { |
806 observers_.AddObserver(observer); | 888 observers_.AddObserver(observer); |
807 } | 889 } |
808 | 890 |
809 void InputMethodManagerImpl::AddCandidateWindowObserver( | 891 void InputMethodManagerImpl::AddCandidateWindowObserver( |
810 InputMethodManager::CandidateWindowObserver* observer) { | 892 InputMethodManager::CandidateWindowObserver* observer) { |
811 candidate_window_observers_.AddObserver(observer); | 893 candidate_window_observers_.AddObserver(observer); |
812 } | 894 } |
813 | 895 |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1055 if (candidate_window_controller_.get()) | 1137 if (candidate_window_controller_.get()) |
1056 return; | 1138 return; |
1057 | 1139 |
1058 candidate_window_controller_.reset( | 1140 candidate_window_controller_.reset( |
1059 CandidateWindowController::CreateCandidateWindowController()); | 1141 CandidateWindowController::CreateCandidateWindowController()); |
1060 candidate_window_controller_->AddObserver(this); | 1142 candidate_window_controller_->AddObserver(this); |
1061 } | 1143 } |
1062 | 1144 |
1063 } // namespace input_method | 1145 } // namespace input_method |
1064 } // namespace chromeos | 1146 } // namespace chromeos |
OLD | NEW |