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/extensions/api/input_ime/input_ime_api.h" | 5 #include "chrome/browser/extensions/api/input_ime/input_ime_api.h" |
6 | 6 |
7 #include "base/strings/string_number_conversions.h" | 7 #include "base/strings/string_number_conversions.h" |
8 #include "base/values.h" | 8 #include "base/values.h" |
9 #include "chrome/browser/chromeos/login/lock/screen_locker.h" | 9 #include "chrome/browser/chromeos/login/lock/screen_locker.h" |
10 #include "chrome/browser/chromeos/login/ui/user_adding_screen.h" | 10 #include "chrome/browser/chromeos/login/ui/user_adding_screen.h" |
11 #include "chrome/browser/chromeos/login/users/user_manager.h" | 11 #include "chrome/browser/chromeos/login/users/user_manager.h" |
12 #include "chrome/browser/chromeos/profiles/profile_helper.h" | 12 #include "chrome/browser/chromeos/profiles/profile_helper.h" |
13 #include "chrome/browser/extensions/extension_service.h" | 13 #include "chrome/browser/extensions/extension_service.h" |
14 #include "chrome/browser/profiles/profile_manager.h" | 14 #include "chrome/browser/profiles/profile_manager.h" |
15 #include "chrome/common/extensions/api/input_ime.h" | 15 #include "chrome/common/extensions/api/input_ime.h" |
16 #include "chrome/common/extensions/api/input_ime/input_components_handler.h" | 16 #include "chrome/common/extensions/api/input_ime/input_components_handler.h" |
17 #include "chromeos/ime/component_extension_ime_manager.h" | |
18 #include "chromeos/ime/extension_ime_util.h" | |
19 #include "chromeos/ime/input_method_manager.h" | |
17 #include "extensions/browser/event_router.h" | 20 #include "extensions/browser/event_router.h" |
18 #include "extensions/browser/extension_function_registry.h" | 21 #include "extensions/browser/extension_function_registry.h" |
19 #include "extensions/browser/extension_registry.h" | 22 #include "extensions/browser/extension_registry.h" |
20 #include "extensions/browser/extension_system.h" | 23 #include "extensions/browser/extension_system.h" |
21 #include "extensions/common/manifest_handlers/background_info.h" | 24 #include "extensions/common/manifest_handlers/background_info.h" |
22 | 25 |
23 #if defined(USE_X11) | 26 #if defined(USE_X11) |
24 #include "chrome/browser/chromeos/input_method/input_method_engine.h" | 27 #include "chrome/browser/chromeos/input_method/input_method_engine.h" |
25 #endif | 28 #endif |
26 | 29 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
68 | 71 |
69 if (input.checked) | 72 if (input.checked) |
70 out->modified |= InputMethodEngineInterface::MENU_ITEM_MODIFIED_CHECKED; | 73 out->modified |= InputMethodEngineInterface::MENU_ITEM_MODIFIED_CHECKED; |
71 out->checked = input.checked ? *input.checked : false; | 74 out->checked = input.checked ? *input.checked : false; |
72 | 75 |
73 if (input.enabled) | 76 if (input.enabled) |
74 out->modified |= InputMethodEngineInterface::MENU_ITEM_MODIFIED_ENABLED; | 77 out->modified |= InputMethodEngineInterface::MENU_ITEM_MODIFIED_ENABLED; |
75 out->enabled = input.enabled ? *input.enabled : true; | 78 out->enabled = input.enabled ? *input.enabled : true; |
76 } | 79 } |
77 | 80 |
78 static void DispatchEventToExtension(Profile* profile, | 81 static void DispatchEventToExtension(const std::string& extension_id, |
79 const std::string& extension_id, | |
80 const std::string& event_name, | 82 const std::string& event_name, |
81 scoped_ptr<base::ListValue> args) { | 83 scoped_ptr<base::ListValue> args) { |
84 Profile* profile = ProfileManager::GetActiveUserProfile(); | |
82 scoped_ptr<extensions::Event> event(new extensions::Event( | 85 scoped_ptr<extensions::Event> event(new extensions::Event( |
83 event_name, args.Pass())); | 86 event_name, args.Pass())); |
84 event->restrict_to_browser_context = profile; | 87 event->restrict_to_browser_context = profile; |
85 extensions::EventRouter::Get(profile) | 88 extensions::EventRouter::Get(profile) |
86 ->DispatchEventToExtension(extension_id, event.Pass()); | 89 ->DispatchEventToExtension(extension_id, event.Pass()); |
87 } | 90 } |
88 | 91 |
89 void CallbackKeyEventHandle(chromeos::input_method::KeyEventHandle* key_data, | 92 void CallbackKeyEventHandle(chromeos::input_method::KeyEventHandle* key_data, |
90 bool handled) { | 93 bool handled) { |
91 base::Callback<void(bool consumed)>* callback = | 94 base::Callback<void(bool consumed)>* callback = |
92 reinterpret_cast<base::Callback<void(bool consumed)>*>(key_data); | 95 reinterpret_cast<base::Callback<void(bool consumed)>*>(key_data); |
93 callback->Run(handled); | 96 callback->Run(handled); |
94 delete callback; | 97 delete callback; |
95 } | 98 } |
96 | 99 |
97 } // namespace | 100 } // namespace |
98 | 101 |
99 namespace chromeos { | 102 namespace chromeos { |
100 class ImeObserver : public InputMethodEngineInterface::Observer { | 103 class ImeObserver : public InputMethodEngineInterface::Observer { |
101 public: | 104 public: |
102 ImeObserver(Profile* profile, const std::string& extension_id) | 105 explicit ImeObserver(const std::string& extension_id) |
103 : profile_(profile), extension_id_(extension_id), has_background_(false) { | 106 : extension_id_(extension_id) {} |
104 extensions::ExtensionSystem* extension_system = | |
105 extensions::ExtensionSystem::Get(profile_); | |
106 ExtensionService* extension_service = extension_system->extension_service(); | |
107 const extensions::Extension* extension = | |
108 extension_service->GetExtensionById(extension_id, false); | |
109 DCHECK(extension); | |
110 extensions::BackgroundInfo* info = static_cast<extensions::BackgroundInfo*>( | |
111 extension->GetManifestData("background")); | |
112 if (info) | |
113 has_background_ = info->has_background_page(); | |
114 } | |
115 | 107 |
116 virtual ~ImeObserver() {} | 108 virtual ~ImeObserver() {} |
117 | 109 |
118 virtual void OnActivate(const std::string& engine_id) OVERRIDE { | 110 virtual void OnActivate(const std::string& component_id) OVERRIDE { |
119 if (profile_ == NULL || extension_id_.empty()) | 111 if (extension_id_.empty()) |
120 return; | |
121 | |
122 scoped_ptr<base::ListValue> args(input_ime::OnActivate::Create(engine_id)); | |
123 | |
124 DispatchEventToExtension(profile_, extension_id_, | |
125 input_ime::OnActivate::kEventName, args.Pass()); | |
126 } | |
127 | |
128 virtual void OnDeactivated(const std::string& engine_id) OVERRIDE { | |
129 if (profile_ == NULL || extension_id_.empty()) | |
130 return; | 112 return; |
131 | 113 |
132 scoped_ptr<base::ListValue> args( | 114 scoped_ptr<base::ListValue> args( |
133 input_ime::OnDeactivated::Create(engine_id)); | 115 input_ime::OnActivate::Create(component_id)); |
134 | 116 |
135 DispatchEventToExtension(profile_, extension_id_, | 117 DispatchEventToExtension( |
136 input_ime::OnDeactivated::kEventName, args.Pass()); | 118 extension_id_, input_ime::OnActivate::kEventName, args.Pass()); |
119 } | |
120 | |
121 virtual void OnDeactivated(const std::string& component_id) OVERRIDE { | |
122 if (extension_id_.empty()) | |
123 return; | |
124 | |
125 scoped_ptr<base::ListValue> args( | |
126 input_ime::OnDeactivated::Create(component_id)); | |
127 | |
128 DispatchEventToExtension( | |
129 extension_id_, input_ime::OnDeactivated::kEventName, args.Pass()); | |
137 } | 130 } |
138 | 131 |
139 virtual void OnFocus( | 132 virtual void OnFocus( |
140 const InputMethodEngineInterface::InputContext& context) OVERRIDE { | 133 const InputMethodEngineInterface::InputContext& context) OVERRIDE { |
141 if (profile_ == NULL || extension_id_.empty()) | 134 if (extension_id_.empty()) |
142 return; | 135 return; |
143 | 136 |
144 input_ime::InputContext context_value; | 137 input_ime::InputContext context_value; |
145 context_value.context_id = context.id; | 138 context_value.context_id = context.id; |
146 context_value.type = input_ime::InputContext::ParseType(context.type); | 139 context_value.type = input_ime::InputContext::ParseType(context.type); |
147 | 140 |
148 scoped_ptr<base::ListValue> args(input_ime::OnFocus::Create(context_value)); | 141 scoped_ptr<base::ListValue> args(input_ime::OnFocus::Create(context_value)); |
149 | 142 |
150 // The component IME extensions need to know the current screen type (e.g. | 143 // The component IME extensions need to know the current screen type (e.g. |
151 // lock screen, login screen, etc.) so that its on-screen keyboard page | 144 // lock screen, login screen, etc.) so that its on-screen keyboard page |
152 // won't open new windows/pages. See crbug.com/395621. | 145 // won't open new windows/pages. See crbug.com/395621. |
153 base::DictionaryValue* val = NULL; | 146 base::DictionaryValue* val = NULL; |
154 if (args->GetDictionary(0, &val)) { | 147 if (args->GetDictionary(0, &val)) { |
155 std::string screen_type; | 148 std::string screen_type; |
156 if (!UserManager::Get()->IsUserLoggedIn()) { | 149 if (!UserManager::Get()->IsUserLoggedIn()) { |
157 screen_type = "login"; | 150 screen_type = "login"; |
158 } else if (chromeos::ScreenLocker::default_screen_locker() && | 151 } else if (chromeos::ScreenLocker::default_screen_locker() && |
159 chromeos::ScreenLocker::default_screen_locker()->locked()) { | 152 chromeos::ScreenLocker::default_screen_locker()->locked()) { |
160 screen_type = "lock"; | 153 screen_type = "lock"; |
161 } else if (UserAddingScreen::Get()->IsRunning()) { | 154 } else if (UserAddingScreen::Get()->IsRunning()) { |
162 screen_type = "secondary-login"; | 155 screen_type = "secondary-login"; |
163 } | 156 } |
164 if (!screen_type.empty()) | 157 if (!screen_type.empty()) |
165 val->SetStringWithoutPathExpansion("screen", screen_type); | 158 val->SetStringWithoutPathExpansion("screen", screen_type); |
166 } | 159 } |
167 | 160 |
168 DispatchEventToExtension(profile_, extension_id_, | 161 DispatchEventToExtension( |
169 input_ime::OnFocus::kEventName, args.Pass()); | 162 extension_id_, input_ime::OnFocus::kEventName, args.Pass()); |
170 } | 163 } |
171 | 164 |
172 virtual void OnBlur(int context_id) OVERRIDE { | 165 virtual void OnBlur(int context_id) OVERRIDE { |
173 if (profile_ == NULL || extension_id_.empty()) | 166 if (extension_id_.empty()) |
174 return; | 167 return; |
175 | 168 |
176 scoped_ptr<base::ListValue> args(input_ime::OnBlur::Create(context_id)); | 169 scoped_ptr<base::ListValue> args(input_ime::OnBlur::Create(context_id)); |
177 | 170 |
178 DispatchEventToExtension(profile_, extension_id_, | 171 DispatchEventToExtension( |
179 input_ime::OnBlur::kEventName, args.Pass()); | 172 extension_id_, input_ime::OnBlur::kEventName, args.Pass()); |
180 } | 173 } |
181 | 174 |
182 virtual void OnInputContextUpdate( | 175 virtual void OnInputContextUpdate( |
183 const InputMethodEngineInterface::InputContext& context) OVERRIDE { | 176 const InputMethodEngineInterface::InputContext& context) OVERRIDE { |
184 if (profile_ == NULL || extension_id_.empty()) | 177 if (extension_id_.empty()) |
185 return; | 178 return; |
186 | 179 |
187 input_ime::InputContext context_value; | 180 input_ime::InputContext context_value; |
188 context_value.context_id = context.id; | 181 context_value.context_id = context.id; |
189 context_value.type = input_ime::InputContext::ParseType(context.type); | 182 context_value.type = input_ime::InputContext::ParseType(context.type); |
190 | 183 |
191 scoped_ptr<base::ListValue> args( | 184 scoped_ptr<base::ListValue> args( |
192 input_ime::OnInputContextUpdate::Create(context_value)); | 185 input_ime::OnInputContextUpdate::Create(context_value)); |
193 | 186 |
194 DispatchEventToExtension(profile_, | 187 DispatchEventToExtension(extension_id_, |
195 extension_id_, | |
196 input_ime::OnInputContextUpdate::kEventName, | 188 input_ime::OnInputContextUpdate::kEventName, |
197 args.Pass()); | 189 args.Pass()); |
198 } | 190 } |
199 | 191 |
200 virtual void OnKeyEvent( | 192 virtual void OnKeyEvent( |
201 const std::string& engine_id, | 193 const std::string& component_id, |
202 const InputMethodEngineInterface::KeyboardEvent& event, | 194 const InputMethodEngineInterface::KeyboardEvent& event, |
203 chromeos::input_method::KeyEventHandle* key_data) OVERRIDE { | 195 chromeos::input_method::KeyEventHandle* key_data) OVERRIDE { |
204 if (profile_ == NULL || extension_id_.empty()) | 196 if (extension_id_.empty()) |
205 return; | 197 return; |
206 | 198 |
207 // If there is no listener for the event, no need to dispatch the event to | 199 // If there is no listener for the event, no need to dispatch the event to |
208 // extension. Instead, releases the key event for default system behavior. | 200 // extension. Instead, releases the key event for default system behavior. |
209 if (!ShouldForwardKeyEvent()) { | 201 if (!ShouldForwardKeyEvent()) { |
210 // Continue processing the key event so that the physical keyboard can | 202 // Continue processing the key event so that the physical keyboard can |
211 // still work. | 203 // still work. |
212 CallbackKeyEventHandle(key_data, false); | 204 CallbackKeyEventHandle(key_data, false); |
213 return; | 205 return; |
214 } | 206 } |
215 | 207 |
216 extensions::InputImeEventRouter* ime_event_router = | 208 extensions::InputImeEventRouter* ime_event_router = |
217 extensions::InputImeEventRouter::GetInstance(); | 209 extensions::InputImeEventRouter::GetInstance(); |
218 | 210 |
219 const std::string request_id = | 211 const std::string request_id = |
220 ime_event_router->AddRequest(engine_id, key_data); | 212 ime_event_router->AddRequest(component_id, key_data); |
221 | 213 |
222 input_ime::KeyboardEvent key_data_value; | 214 input_ime::KeyboardEvent key_data_value; |
223 key_data_value.type = input_ime::KeyboardEvent::ParseType(event.type); | 215 key_data_value.type = input_ime::KeyboardEvent::ParseType(event.type); |
224 key_data_value.request_id = request_id; | 216 key_data_value.request_id = request_id; |
225 if (!event.extension_id.empty()) | 217 if (!event.extension_id.empty()) |
226 key_data_value.extension_id.reset(new std::string(event.extension_id)); | 218 key_data_value.extension_id.reset(new std::string(event.extension_id)); |
227 key_data_value.key = event.key; | 219 key_data_value.key = event.key; |
228 key_data_value.code = event.code; | 220 key_data_value.code = event.code; |
229 key_data_value.alt_key.reset(new bool(event.alt_key)); | 221 key_data_value.alt_key.reset(new bool(event.alt_key)); |
230 key_data_value.ctrl_key.reset(new bool(event.ctrl_key)); | 222 key_data_value.ctrl_key.reset(new bool(event.ctrl_key)); |
231 key_data_value.shift_key.reset(new bool(event.shift_key)); | 223 key_data_value.shift_key.reset(new bool(event.shift_key)); |
232 key_data_value.caps_lock.reset(new bool(event.caps_lock)); | 224 key_data_value.caps_lock.reset(new bool(event.caps_lock)); |
233 | 225 |
234 scoped_ptr<base::ListValue> args( | 226 scoped_ptr<base::ListValue> args( |
235 input_ime::OnKeyEvent::Create(engine_id, key_data_value)); | 227 input_ime::OnKeyEvent::Create(component_id, key_data_value)); |
236 | 228 |
237 DispatchEventToExtension(profile_, extension_id_, | 229 DispatchEventToExtension( |
238 input_ime::OnKeyEvent::kEventName, args.Pass()); | 230 extension_id_, input_ime::OnKeyEvent::kEventName, args.Pass()); |
239 } | 231 } |
240 | 232 |
241 virtual void OnCandidateClicked( | 233 virtual void OnCandidateClicked( |
242 const std::string& engine_id, | 234 const std::string& component_id, |
243 int candidate_id, | 235 int candidate_id, |
244 InputMethodEngineInterface::MouseButtonEvent button) OVERRIDE { | 236 InputMethodEngineInterface::MouseButtonEvent button) OVERRIDE { |
245 if (profile_ == NULL || extension_id_.empty()) | 237 if (extension_id_.empty()) |
246 return; | 238 return; |
247 | 239 |
248 input_ime::OnCandidateClicked::Button button_enum = | 240 input_ime::OnCandidateClicked::Button button_enum = |
249 input_ime::OnCandidateClicked::BUTTON_NONE; | 241 input_ime::OnCandidateClicked::BUTTON_NONE; |
250 switch (button) { | 242 switch (button) { |
251 case InputMethodEngineInterface::MOUSE_BUTTON_MIDDLE: | 243 case InputMethodEngineInterface::MOUSE_BUTTON_MIDDLE: |
252 button_enum = input_ime::OnCandidateClicked::BUTTON_MIDDLE; | 244 button_enum = input_ime::OnCandidateClicked::BUTTON_MIDDLE; |
253 break; | 245 break; |
254 | 246 |
255 case InputMethodEngineInterface::MOUSE_BUTTON_RIGHT: | 247 case InputMethodEngineInterface::MOUSE_BUTTON_RIGHT: |
256 button_enum = input_ime::OnCandidateClicked::BUTTON_RIGHT; | 248 button_enum = input_ime::OnCandidateClicked::BUTTON_RIGHT; |
257 break; | 249 break; |
258 | 250 |
259 case InputMethodEngineInterface::MOUSE_BUTTON_LEFT: | 251 case InputMethodEngineInterface::MOUSE_BUTTON_LEFT: |
260 // Default to left. | 252 // Default to left. |
261 default: | 253 default: |
262 button_enum = input_ime::OnCandidateClicked::BUTTON_LEFT; | 254 button_enum = input_ime::OnCandidateClicked::BUTTON_LEFT; |
263 break; | 255 break; |
264 } | 256 } |
265 | 257 |
266 scoped_ptr<base::ListValue> args( | 258 scoped_ptr<base::ListValue> args(input_ime::OnCandidateClicked::Create( |
267 input_ime::OnCandidateClicked::Create(engine_id, | 259 component_id, candidate_id, button_enum)); |
268 candidate_id, | |
269 button_enum)); | |
270 | 260 |
271 DispatchEventToExtension(profile_, | 261 DispatchEventToExtension( |
272 extension_id_, | 262 extension_id_, input_ime::OnCandidateClicked::kEventName, args.Pass()); |
273 input_ime::OnCandidateClicked::kEventName, | |
274 args.Pass()); | |
275 } | 263 } |
276 | 264 |
277 virtual void OnMenuItemActivated(const std::string& engine_id, | 265 virtual void OnMenuItemActivated(const std::string& component_id, |
278 const std::string& menu_id) OVERRIDE { | 266 const std::string& menu_id) OVERRIDE { |
279 if (profile_ == NULL || extension_id_.empty()) | 267 if (extension_id_.empty()) |
280 return; | 268 return; |
281 | 269 |
282 scoped_ptr<base::ListValue> args( | 270 scoped_ptr<base::ListValue> args( |
283 input_ime::OnMenuItemActivated::Create(engine_id, menu_id)); | 271 input_ime::OnMenuItemActivated::Create(component_id, menu_id)); |
284 | 272 |
285 DispatchEventToExtension(profile_, | 273 DispatchEventToExtension( |
286 extension_id_, | 274 extension_id_, input_ime::OnMenuItemActivated::kEventName, args.Pass()); |
287 input_ime::OnMenuItemActivated::kEventName, | |
288 args.Pass()); | |
289 } | 275 } |
290 | 276 |
291 virtual void OnSurroundingTextChanged(const std::string& engine_id, | 277 virtual void OnSurroundingTextChanged(const std::string& component_id, |
292 const std::string& text, | 278 const std::string& text, |
293 int cursor_pos, | 279 int cursor_pos, |
294 int anchor_pos) OVERRIDE { | 280 int anchor_pos) OVERRIDE { |
295 if (profile_ == NULL || extension_id_.empty()) | 281 if (extension_id_.empty()) |
296 return; | 282 return; |
297 | 283 |
298 input_ime::OnSurroundingTextChanged::SurroundingInfo info; | 284 input_ime::OnSurroundingTextChanged::SurroundingInfo info; |
299 info.text = text; | 285 info.text = text; |
300 info.focus = cursor_pos; | 286 info.focus = cursor_pos; |
301 info.anchor = anchor_pos; | 287 info.anchor = anchor_pos; |
302 scoped_ptr<base::ListValue> args( | 288 scoped_ptr<base::ListValue> args( |
303 input_ime::OnSurroundingTextChanged::Create(engine_id, info)); | 289 input_ime::OnSurroundingTextChanged::Create(component_id, info)); |
304 | 290 |
305 DispatchEventToExtension(profile_, | 291 DispatchEventToExtension(extension_id_, |
306 extension_id_, | |
307 input_ime::OnSurroundingTextChanged::kEventName, | 292 input_ime::OnSurroundingTextChanged::kEventName, |
308 args.Pass()); | 293 args.Pass()); |
309 } | 294 } |
310 | 295 |
311 virtual void OnReset(const std::string& engine_id) OVERRIDE { | 296 virtual void OnReset(const std::string& component_id) OVERRIDE { |
312 if (profile_ == NULL || extension_id_.empty()) | 297 if (extension_id_.empty()) |
313 return; | 298 return; |
314 | 299 |
315 scoped_ptr<base::ListValue> args(input_ime::OnReset::Create(engine_id)); | 300 scoped_ptr<base::ListValue> args(input_ime::OnReset::Create(component_id)); |
316 | 301 |
317 DispatchEventToExtension(profile_, | 302 DispatchEventToExtension( |
318 extension_id_, | 303 extension_id_, input_ime::OnReset::kEventName, args.Pass()); |
319 input_ime::OnReset::kEventName, | |
320 args.Pass()); | |
321 } | 304 } |
322 | 305 |
323 private: | 306 private: |
324 // Returns true if the extension is ready to accept key event, otherwise | 307 // Returns true if the extension is ready to accept key event, otherwise |
325 // returns false. | 308 // returns false. |
326 bool ShouldForwardKeyEvent() const { | 309 bool ShouldForwardKeyEvent() const { |
327 // Need to check the background page first since the | 310 // Only forward key events to extension if there are non-lazy listeners |
328 // ExtensionHasEventListner returns true if the extension does not have a | 311 // for onKeyEvent. Because if something wrong with the lazy background |
329 // background page. See crbug.com/394682. | 312 // page which doesn't register listener for onKeyEvent, it will not handle |
330 return has_background_ && extensions::EventRouter::Get(profile_) | 313 // the key events, and therefore, all key events will be eaten. |
331 ->ExtensionHasEventListener(extension_id_, | 314 // This is for error-tolerance, and it means that onKeyEvent will never wake |
332 input_ime::OnKeyEvent::kEventName); | 315 // up lazy background page. |
316 const extensions::EventListenerMap::ListenerList& listener_list = | |
317 extensions::EventRouter::Get(ProfileManager::GetActiveUserProfile()) | |
318 ->listeners().GetEventListenersByName( | |
319 input_ime::OnKeyEvent::kEventName); | |
320 for (extensions::EventListenerMap::ListenerList::const_iterator it = | |
321 listener_list.begin(); | |
322 it != listener_list.end(); it++) { | |
Yuki
2014/08/06 04:42:24
s/it++/++it/ for iterators.
it++ may be slower tha
Shu Chen
2014/08/06 05:45:03
Done.
| |
323 if ((*it)->extension_id() == extension_id_ && !(*it)->IsLazy()) | |
324 return true; | |
325 } | |
326 return false; | |
333 } | 327 } |
334 | 328 |
335 Profile* profile_; | |
336 std::string extension_id_; | 329 std::string extension_id_; |
337 bool has_background_; | |
338 | 330 |
339 DISALLOW_COPY_AND_ASSIGN(ImeObserver); | 331 DISALLOW_COPY_AND_ASSIGN(ImeObserver); |
340 }; | 332 }; |
341 | 333 |
342 } // namespace chromeos | 334 } // namespace chromeos |
343 | 335 |
344 namespace extensions { | 336 namespace extensions { |
345 | 337 |
346 InputImeEventRouter* | 338 InputImeEventRouter* |
347 InputImeEventRouter::GetInstance() { | 339 InputImeEventRouter::GetInstance() { |
348 return Singleton<InputImeEventRouter>::get(); | 340 return Singleton<InputImeEventRouter>::get(); |
349 } | 341 } |
350 | 342 |
351 bool InputImeEventRouter::RegisterIme( | 343 bool InputImeEventRouter::RegisterImeExtension( |
352 Profile* profile, | |
353 const std::string& extension_id, | 344 const std::string& extension_id, |
354 const extensions::InputComponentInfo& component) { | 345 const std::vector<extensions::InputComponentInfo>& input_components) { |
355 #if defined(USE_X11) | 346 #if defined(USE_X11) |
356 VLOG(1) << "RegisterIme: " << extension_id << " id: " << component.id; | 347 VLOG(1) << "RegisterImeExtension: " << extension_id; |
357 | 348 |
358 // Avoid potential mem leaks due to duplicated component IDs. | 349 if (engine_map_[extension_id]) |
359 if (!profile_engine_map_[profile][extension_id][component.id]) { | 350 return false; |
360 std::vector<std::string> layouts; | |
361 layouts.assign(component.layouts.begin(), component.layouts.end()); | |
362 | 351 |
363 std::vector<std::string> languages; | 352 chromeos::input_method::InputMethodManager* manager = |
364 languages.assign(component.languages.begin(), component.languages.end()); | 353 chromeos::input_method::InputMethodManager::Get(); |
354 chromeos::ComponentExtensionIMEManager* comp_ext_ime_manager = | |
355 manager->GetComponentExtensionIMEManager(); | |
365 | 356 |
366 // Ideally Observer should be per (extension_id + Profile), and multiple | 357 chromeos::input_method::InputMethodDescriptors descriptors; |
367 // InputMethodEngine can share one Observer. But it would become tricky | 358 // Only creates descriptors for 3rd party IME extension, because the |
368 // to maintain an internal map for observers which does nearly nothing | 359 // descriptors for component IME extensions are managed by InputMethodUtil. |
369 // but just make sure they can properly deleted. | 360 if (!comp_ext_ime_manager->IsWhitelistedExtension(extension_id)) { |
370 // Making Obesrver per InputMethodEngine can make things cleaner. | 361 for (std::vector<extensions::InputComponentInfo>::const_iterator it = |
371 scoped_ptr<chromeos::InputMethodEngineInterface::Observer> observer( | 362 input_components.begin(); |
372 new chromeos::ImeObserver(profile, extension_id)); | 363 it != input_components.end(); |
373 chromeos::InputMethodEngine* engine = new chromeos::InputMethodEngine(); | 364 ++it) { |
374 engine->Initialize(profile, | 365 const extensions::InputComponentInfo& component = *it; |
375 observer.Pass(), | 366 DCHECK(component.type == extensions::INPUT_COMPONENT_TYPE_IME); |
376 component.name.c_str(), | 367 |
377 extension_id.c_str(), | 368 std::vector<std::string> layouts; |
378 component.id.c_str(), | 369 layouts.assign(component.layouts.begin(), component.layouts.end()); |
379 languages, | 370 std::vector<std::string> languages; |
380 layouts, | 371 languages.assign(component.languages.begin(), component.languages.end()); |
381 component.options_page_url, | 372 |
382 component.input_view_url); | 373 const std::string& input_method_id = |
383 profile_engine_map_[profile][extension_id][component.id] = engine; | 374 chromeos::extension_ime_util::GetInputMethodID(extension_id, |
375 component.id); | |
376 descriptors.push_back(chromeos::input_method::InputMethodDescriptor( | |
377 input_method_id, | |
378 component.name, | |
379 std::string(), // TODO(uekawa): Set short name. | |
380 layouts, | |
381 languages, | |
382 false, // 3rd party IMEs are always not for login. | |
383 component.options_page_url, | |
384 component.input_view_url)); | |
385 } | |
384 } | 386 } |
385 | 387 |
388 scoped_ptr<chromeos::InputMethodEngineInterface::Observer> observer( | |
389 new chromeos::ImeObserver(extension_id)); | |
390 chromeos::InputMethodEngine* engine = new chromeos::InputMethodEngine(); | |
391 engine->Initialize(observer.Pass(), extension_id.c_str()); | |
392 engine_map_[extension_id] = engine; | |
393 manager->AddInputMethodExtension(extension_id, descriptors, engine); | |
394 | |
386 return true; | 395 return true; |
387 #else | 396 #else |
388 // TODO(spang): IME support under ozone. | 397 // TODO(spang): IME support under ozone. |
389 NOTIMPLEMENTED(); | 398 NOTIMPLEMENTED(); |
390 return false; | 399 return false; |
391 #endif | 400 #endif |
392 } | 401 } |
393 | 402 |
394 void InputImeEventRouter::UnregisterAllImes(const std::string& extension_id) { | 403 void InputImeEventRouter::UnregisterAllImes(const std::string& extension_id) { |
395 Profile* profile = ProfileManager::GetActiveUserProfile(); | 404 std::map<std::string, InputMethodEngineInterface*>::iterator it = |
396 ProfileEngineMap::iterator extension_map = | 405 engine_map_.find(extension_id); |
397 profile_engine_map_.find(profile); | 406 if (it != engine_map_.end()) { |
398 if (extension_map == profile_engine_map_.end()) | 407 chromeos::input_method::InputMethodManager::Get() |
399 return; | 408 ->RemoveInputMethodExtension(extension_id); |
400 ExtensionMap::iterator engine_map = extension_map->second.find(extension_id); | 409 delete it->second; |
401 if (engine_map == extension_map->second.end()) | 410 engine_map_.erase(it); |
402 return; | 411 } |
403 STLDeleteContainerPairSecondPointers(engine_map->second.begin(), | |
404 engine_map->second.end()); | |
405 extension_map->second.erase(extension_id); | |
406 profile_engine_map_.erase(profile); | |
407 } | 412 } |
408 | 413 |
409 InputMethodEngineInterface* InputImeEventRouter::GetEngine( | 414 InputMethodEngineInterface* InputImeEventRouter::GetEngine( |
410 const std::string& extension_id, const std::string& engine_id) { | 415 const std::string& extension_id, |
411 // IME can only work on active user profile. | 416 const std::string& component_id) { |
412 Profile* profile = ProfileManager::GetActiveUserProfile(); | 417 std::map<std::string, InputMethodEngineInterface*>::iterator it = |
413 | 418 engine_map_.find(extension_id); |
414 ProfileEngineMap::const_iterator extension_map = | 419 if (it != engine_map_.end() && |
415 profile_engine_map_.find(profile); | 420 it->second->GetActiveComponentId() == component_id) |
416 if (extension_map == profile_engine_map_.end()) | 421 return it->second; |
417 return NULL; | 422 return NULL; |
418 ExtensionMap::const_iterator engine_map = | |
419 extension_map->second.find(extension_id); | |
420 if (engine_map == extension_map->second.end()) | |
421 return NULL; | |
422 EngineMap::const_iterator engine = engine_map->second.find(engine_id); | |
423 if (engine == engine_map->second.end()) | |
424 return NULL; | |
425 return engine->second; | |
426 } | 423 } |
427 | 424 |
428 InputMethodEngineInterface* InputImeEventRouter::GetActiveEngine( | 425 InputMethodEngineInterface* InputImeEventRouter::GetActiveEngine( |
429 const std::string& extension_id) { | 426 const std::string& extension_id) { |
430 // IME can only work on active user profile. | 427 std::map<std::string, InputMethodEngineInterface*>::iterator it = |
431 Profile* profile = ProfileManager::GetActiveUserProfile(); | 428 engine_map_.find(extension_id); |
432 | 429 if (it != engine_map_.end() && it->second->IsActive()) |
433 ProfileEngineMap::const_iterator extension_map = | 430 return it->second; |
434 profile_engine_map_.find(profile); | |
435 if (extension_map == profile_engine_map_.end()) | |
436 return NULL; | |
437 ExtensionMap::const_iterator engine_map = | |
438 extension_map->second.find(extension_id); | |
439 if (engine_map == extension_map->second.end()) | |
440 return NULL; | |
441 | |
442 for (EngineMap::const_iterator i = engine_map->second.begin(); | |
443 i != engine_map->second.end(); | |
444 ++i) { | |
445 if (i->second->IsActive()) | |
446 return i->second; | |
447 } | |
448 return NULL; | 431 return NULL; |
449 } | 432 } |
450 | 433 |
451 void InputImeEventRouter::OnKeyEventHandled( | 434 void InputImeEventRouter::OnKeyEventHandled( |
452 const std::string& extension_id, | 435 const std::string& extension_id, |
453 const std::string& request_id, | 436 const std::string& request_id, |
454 bool handled) { | 437 bool handled) { |
455 RequestMap::iterator request = request_map_.find(request_id); | 438 RequestMap::iterator request = request_map_.find(request_id); |
456 if (request == request_map_.end()) { | 439 if (request == request_map_.end()) { |
457 LOG(ERROR) << "Request ID not found: " << request_id; | 440 LOG(ERROR) << "Request ID not found: " << request_id; |
458 return; | 441 return; |
459 } | 442 } |
460 | 443 |
461 std::string engine_id = request->second.first; | 444 std::string component_id = request->second.first; |
462 chromeos::input_method::KeyEventHandle* key_data = request->second.second; | 445 chromeos::input_method::KeyEventHandle* key_data = request->second.second; |
463 request_map_.erase(request); | 446 request_map_.erase(request); |
464 | 447 |
465 CallbackKeyEventHandle(key_data, handled); | 448 CallbackKeyEventHandle(key_data, handled); |
466 } | 449 } |
467 | 450 |
468 std::string InputImeEventRouter::AddRequest( | 451 std::string InputImeEventRouter::AddRequest( |
469 const std::string& engine_id, | 452 const std::string& component_id, |
470 chromeos::input_method::KeyEventHandle* key_data) { | 453 chromeos::input_method::KeyEventHandle* key_data) { |
471 std::string request_id = base::IntToString(next_request_id_); | 454 std::string request_id = base::IntToString(next_request_id_); |
472 ++next_request_id_; | 455 ++next_request_id_; |
473 | 456 |
474 request_map_[request_id] = std::make_pair(engine_id, key_data); | 457 request_map_[request_id] = std::make_pair(component_id, key_data); |
475 | 458 |
476 return request_id; | 459 return request_id; |
477 } | 460 } |
478 | 461 |
479 InputImeEventRouter::InputImeEventRouter() | 462 InputImeEventRouter::InputImeEventRouter() |
480 : next_request_id_(1) { | 463 : next_request_id_(1) { |
481 } | 464 } |
482 | 465 |
483 InputImeEventRouter::~InputImeEventRouter() {} | 466 InputImeEventRouter::~InputImeEventRouter() {} |
484 | 467 |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
821 InputImeEventRouter::GetInstance()->OnKeyEventHandled( | 804 InputImeEventRouter::GetInstance()->OnKeyEventHandled( |
822 extension_id(), params->request_id, params->response); | 805 extension_id(), params->request_id, params->response); |
823 return true; | 806 return true; |
824 } | 807 } |
825 | 808 |
826 InputImeAPI::InputImeAPI(content::BrowserContext* context) | 809 InputImeAPI::InputImeAPI(content::BrowserContext* context) |
827 : browser_context_(context), extension_registry_observer_(this) { | 810 : browser_context_(context), extension_registry_observer_(this) { |
828 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); | 811 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); |
829 | 812 |
830 EventRouter* event_router = EventRouter::Get(browser_context_); | 813 EventRouter* event_router = EventRouter::Get(browser_context_); |
831 event_router->RegisterObserver(this, input_ime::OnActivate::kEventName); | |
832 event_router->RegisterObserver(this, input_ime::OnFocus::kEventName); | 814 event_router->RegisterObserver(this, input_ime::OnFocus::kEventName); |
833 } | 815 } |
834 | 816 |
835 InputImeAPI::~InputImeAPI() { | 817 InputImeAPI::~InputImeAPI() { |
836 EventRouter::Get(browser_context_)->UnregisterObserver(this); | 818 EventRouter::Get(browser_context_)->UnregisterObserver(this); |
837 } | 819 } |
838 | 820 |
839 static base::LazyInstance<BrowserContextKeyedAPIFactory<InputImeAPI> > | 821 static base::LazyInstance<BrowserContextKeyedAPIFactory<InputImeAPI> > |
840 g_factory = LAZY_INSTANCE_INITIALIZER; | 822 g_factory = LAZY_INSTANCE_INITIALIZER; |
841 | 823 |
842 // static | 824 // static |
843 BrowserContextKeyedAPIFactory<InputImeAPI>* InputImeAPI::GetFactoryInstance() { | 825 BrowserContextKeyedAPIFactory<InputImeAPI>* InputImeAPI::GetFactoryInstance() { |
844 return g_factory.Pointer(); | 826 return g_factory.Pointer(); |
845 } | 827 } |
846 | 828 |
847 void InputImeAPI::OnExtensionLoaded(content::BrowserContext* browser_context, | 829 void InputImeAPI::OnExtensionLoaded(content::BrowserContext* browser_context, |
848 const Extension* extension) { | 830 const Extension* extension) { |
849 const std::vector<InputComponentInfo>* input_components = | 831 const std::vector<InputComponentInfo>* input_components = |
850 extensions::InputComponents::GetInputComponents(extension); | 832 extensions::InputComponents::GetInputComponents(extension); |
851 if (!input_components) | 833 if (input_components) |
852 return; | 834 input_ime_event_router()->RegisterImeExtension(extension->id(), |
853 for (std::vector<extensions::InputComponentInfo>::const_iterator component = | 835 *input_components); |
854 input_components->begin(); | |
855 component != input_components->end(); | |
856 ++component) { | |
857 if (component->type == extensions::INPUT_COMPONENT_TYPE_IME) { | |
858 // If |browser_context| looks like signin profile, use the real signin | |
859 // profile. This is because IME extensions for signin profile are run | |
860 // in Off-The-Record profile, based on given static defaults. | |
861 // So if |profile_| is signin profile, we need to make sure | |
862 // the router/observer runs under its incognito profile, because the | |
863 // component extensions were installed under its incognito profile. | |
864 Profile* profile = Profile::FromBrowserContext(browser_context); | |
865 if (chromeos::ProfileHelper::IsSigninProfile(profile)) | |
866 profile = chromeos::ProfileHelper::GetSigninProfile(); | |
867 input_ime_event_router()->RegisterIme( | |
868 profile, extension->id(), *component); | |
869 } | |
870 } | |
871 } | 836 } |
872 | 837 |
873 void InputImeAPI::OnExtensionUnloaded(content::BrowserContext* browser_context, | 838 void InputImeAPI::OnExtensionUnloaded(content::BrowserContext* browser_context, |
874 const Extension* extension, | 839 const Extension* extension, |
875 UnloadedExtensionInfo::Reason reason) { | 840 UnloadedExtensionInfo::Reason reason) { |
876 const std::vector<InputComponentInfo>* input_components = | 841 const std::vector<InputComponentInfo>* input_components = |
877 extensions::InputComponents::GetInputComponents(extension); | 842 extensions::InputComponents::GetInputComponents(extension); |
878 if (!input_components) | 843 if (!input_components) |
879 return; | 844 return; |
880 if (input_components->size() > 0) | 845 if (input_components->size() > 0) |
881 input_ime_event_router()->UnregisterAllImes(extension->id()); | 846 input_ime_event_router()->UnregisterAllImes(extension->id()); |
882 } | 847 } |
883 | 848 |
884 void InputImeAPI::OnListenerAdded(const EventListenerInfo& details) { | 849 void InputImeAPI::OnListenerAdded(const EventListenerInfo& details) { |
885 InputMethodEngineInterface* engine = | 850 InputMethodEngineInterface* engine = |
886 input_ime_event_router()->GetActiveEngine(details.extension_id); | 851 input_ime_event_router()->GetActiveEngine(details.extension_id); |
852 // Notifies the IME extension for IME ready with onActivate/onFocus events. | |
887 if (engine) | 853 if (engine) |
888 engine->NotifyImeReady(); | 854 engine->Enable(engine->GetActiveComponentId()); |
889 } | 855 } |
890 | 856 |
891 InputImeEventRouter* InputImeAPI::input_ime_event_router() { | 857 InputImeEventRouter* InputImeAPI::input_ime_event_router() { |
892 return InputImeEventRouter::GetInstance(); | 858 return InputImeEventRouter::GetInstance(); |
893 } | 859 } |
894 | 860 |
895 } // namespace extensions | 861 } // namespace extensions |
OLD | NEW |