OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/chromeos/input_method/browser_state_monitor.h" | |
6 | |
7 #include "ash/ash_switches.h" | |
8 #include "base/command_line.h" | |
9 #include "chrome/browser/browser_process.h" | |
10 #include "chrome/browser/chromeos/input_method/input_method_util.h" | |
11 #include "chrome/browser/chromeos/language_preferences.h" | |
12 #include "chrome/browser/prefs/pref_service.h" | |
13 #include "chrome/browser/profiles/profile_manager.h" | |
14 #include "chrome/common/chrome_notification_types.h" | |
15 #include "chrome/common/pref_names.h" | |
16 #include "content/public/browser/notification_service.h" | |
17 | |
18 namespace chromeos { | |
19 namespace input_method { | |
20 namespace { | |
21 | |
22 PrefService* GetPrefService() { | |
23 Profile* profile = ProfileManager::GetDefaultProfile(); | |
24 if (profile) | |
25 return profile->GetPrefs(); | |
26 return NULL; | |
27 } | |
28 | |
29 } // namespace | |
30 | |
31 BrowserStateMonitor::BrowserStateMonitor(InputMethodManager* manager) | |
32 : manager_(manager), | |
33 state_(InputMethodManager::STATE_LOGIN_SCREEN), | |
34 initialized_(false) { | |
35 // On R19, when Uber Tray is disabled, the IME status button will update the | |
36 // Preferences. | |
37 // TODO(yusukes): Remove all Preferences code from the button on R20. | |
38 if (CommandLine::ForCurrentProcess()->HasSwitch( | |
39 ash::switches::kDisableAshUberTray)) | |
40 return; | |
41 | |
42 notification_registrar_.Add(this, | |
43 chrome::NOTIFICATION_LOGIN_USER_CHANGED, | |
44 content::NotificationService::AllSources()); | |
45 notification_registrar_.Add(this, | |
46 chrome::NOTIFICATION_SESSION_STARTED, | |
47 content::NotificationService::AllSources()); | |
48 notification_registrar_.Add(this, | |
49 chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED, | |
50 content::NotificationService::AllSources()); | |
51 // We should not use APP_EXITING here since logout might be canceled by | |
52 // JavaScript after APP_EXITING is sent (crosbug.com/11055). | |
53 notification_registrar_.Add(this, | |
54 content::NOTIFICATION_APP_TERMINATING, | |
55 content::NotificationService::AllSources()); | |
56 | |
57 // TODO(yusukes): Tell the initial state to the manager. | |
58 manager_->AddPreLoginPreferenceObserver(this); | |
59 manager_->AddPostLoginPreferenceObserver(this); | |
60 } | |
61 | |
62 BrowserStateMonitor::~BrowserStateMonitor() { | |
63 manager_->RemovePostLoginPreferenceObserver(this); | |
64 manager_->RemovePreLoginPreferenceObserver(this); | |
65 } | |
66 | |
67 void BrowserStateMonitor::UpdateLocalState( | |
68 const std::string& current_input_method) { | |
69 if (!InputMethodUtil::IsKeyboardLayout(current_input_method)) { | |
70 LOG(ERROR) << "Only keyboard layouts are supported: " | |
71 << current_input_method; | |
72 return; | |
73 } | |
74 | |
75 if (!g_browser_process || !g_browser_process->local_state()) | |
76 return; | |
77 | |
78 g_browser_process->local_state()->SetString( | |
79 language_prefs::kPreferredKeyboardLayout, | |
80 current_input_method); | |
81 } | |
82 | |
83 void BrowserStateMonitor::UpdateUserPreferences( | |
84 const std::string& current_input_method) { | |
85 InitializePrefMembers(); | |
86 const std::string current_input_method_on_pref = | |
87 current_input_method_pref_.GetValue(); | |
88 if (current_input_method_on_pref == current_input_method) | |
89 return; | |
90 previous_input_method_pref_.SetValue(current_input_method_on_pref); | |
91 current_input_method_pref_.SetValue(current_input_method); | |
92 } | |
93 | |
94 void BrowserStateMonitor::PreferenceUpdateNeeded( | |
95 input_method::InputMethodManager* manager, | |
96 const input_method::InputMethodDescriptor& previous_input_method, | |
97 const input_method::InputMethodDescriptor& current_input_method) { | |
98 DCHECK_EQ(manager_, manager); | |
99 // Save the new input method id depending on the current browser state. | |
100 switch (state_) { | |
101 case InputMethodManager::STATE_LOGIN_SCREEN: | |
102 UpdateLocalState(current_input_method.id()); | |
Zachary Kuznia
2012/03/26 06:26:07
Does this handle the case where an IME is being us
Yusuke Sato
2012/03/26 06:42:43
Actually Aura version of Chrome OS never enables a
| |
103 return; | |
104 case InputMethodManager::STATE_BROWSER_SCREEN: | |
105 UpdateUserPreferences(current_input_method.id()); | |
106 return; | |
107 case InputMethodManager::STATE_LOGGING_IN: | |
108 // Do not update the prefs since Preferences::NotifyPrefChanged() will | |
109 // notify the current/previous input method IDs to the manager. | |
110 return; | |
111 case InputMethodManager::STATE_LOCK_SCREEN: | |
112 // We use a special set of input methods on the screen. Do not update. | |
113 return; | |
114 case InputMethodManager::STATE_TERMINATING: | |
115 return; | |
116 } | |
117 NOTREACHED(); | |
118 } | |
119 | |
120 void BrowserStateMonitor::Observe( | |
121 int type, | |
122 const content::NotificationSource& source, | |
123 const content::NotificationDetails& details) { | |
124 switch (type) { | |
125 case content::NOTIFICATION_APP_TERMINATING: { | |
126 SetState(InputMethodManager::STATE_TERMINATING); | |
127 break; | |
128 } | |
129 case chrome::NOTIFICATION_LOGIN_USER_CHANGED: { | |
130 // The user logged in, but the browser window for user session is not yet | |
131 // ready. An initial input method hasn't been set to the manager. | |
132 // Note that the notification is also sent when Chrome crashes/restarts. | |
133 SetState(InputMethodManager::STATE_LOGGING_IN); | |
134 break; | |
135 } | |
136 case chrome::NOTIFICATION_SESSION_STARTED: { | |
137 // The user logged in, and the browser window for user session is ready. | |
138 // An initial input method has already been set. | |
139 // We should NOT call InitializePrefMembers() here since the notification | |
140 // is sent in the PreProfileInit phase in case when Chrome crashes and | |
141 // restarts. | |
142 SetState(InputMethodManager::STATE_BROWSER_SCREEN); | |
143 break; | |
144 } | |
145 case chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED: { | |
146 const bool is_screen_locked = *content::Details<bool>(details).ptr(); | |
147 SetState(is_screen_locked ? InputMethodManager::STATE_LOCK_SCREEN : | |
148 InputMethodManager::STATE_BROWSER_SCREEN); | |
149 break; | |
150 } | |
151 case chrome::NOTIFICATION_PREF_CHANGED: { | |
152 break; // just ignore the notification. | |
153 } | |
154 default: { | |
155 NOTREACHED(); | |
156 break; | |
157 } | |
158 } | |
159 | |
160 // TODO(yusukes): On R20, we should handle Chrome crash/restart correctly. | |
161 // Currently, a wrong input method could be selected when Chrome crashes and | |
162 // restarts. | |
163 // | |
164 // Normal login sequence: | |
165 // 1. chrome::NOTIFICATION_LOGIN_USER_CHANGED is sent. | |
166 // 2. Preferences::NotifyPrefChanged() is called. preload_engines (which | |
167 // might change the current input method) and current/previous input method | |
168 // are sent to the manager. | |
169 // 3. chrome::NOTIFICATION_SESSION_STARTED is sent. | |
170 // | |
171 // Chrome crash/restart (after logging in) sequence: | |
172 // 1. chrome::NOTIFICATION_LOGIN_USER_CHANGED is sent. | |
173 // 2. chrome::NOTIFICATION_SESSION_STARTED is sent. | |
174 // 3. Preferences::NotifyPrefChanged() is called. preload_engines (which | |
175 // might change the current input method) and current/previous input method | |
176 // are sent to the manager. When preload_engines are sent to the manager, | |
177 // UpdateUserPreferences() might be accidentally called. | |
178 } | |
179 | |
180 void BrowserStateMonitor::SetState(InputMethodManager::State new_state) { | |
181 const InputMethodManager::State old_state = state_; | |
182 state_ = new_state; | |
183 if (old_state != state_) { | |
184 // TODO(yusukes): Tell the new state to the manager. | |
185 } | |
186 } | |
187 | |
188 void BrowserStateMonitor::InitializePrefMembers() { | |
189 if (initialized_) | |
190 return; | |
191 | |
192 initialized_ = true; | |
193 PrefService* pref_service = GetPrefService(); | |
194 DCHECK(pref_service); | |
195 DCHECK_EQ(InputMethodManager::STATE_BROWSER_SCREEN, state_); | |
196 previous_input_method_pref_.Init( | |
197 prefs::kLanguagePreviousInputMethod, pref_service, this); | |
198 current_input_method_pref_.Init( | |
199 prefs::kLanguageCurrentInputMethod, pref_service, this); | |
200 } | |
201 | |
202 } // namespace input_method | |
203 } // namespace chromeos | |
OLD | NEW |