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 } | 107 } |
Yuki
2014/08/05 07:57:18
This line can be on the same line above.
: ext
Shu Chen
2014/08/05 14:04:31
Done.
| |
115 | 108 |
116 virtual ~ImeObserver() {} | 109 virtual ~ImeObserver() {} |
117 | 110 |
118 virtual void OnActivate(const std::string& engine_id) OVERRIDE { | 111 virtual void OnActivate(const std::string& engine_id) OVERRIDE { |
119 if (profile_ == NULL || extension_id_.empty()) | 112 if (extension_id_.empty()) |
120 return; | 113 return; |
121 | 114 |
122 scoped_ptr<base::ListValue> args(input_ime::OnActivate::Create(engine_id)); | 115 scoped_ptr<base::ListValue> args(input_ime::OnActivate::Create(engine_id)); |
123 | 116 |
124 DispatchEventToExtension(profile_, extension_id_, | 117 DispatchEventToExtension(extension_id_, |
125 input_ime::OnActivate::kEventName, args.Pass()); | 118 input_ime::OnActivate::kEventName, args.Pass()); |
126 } | 119 } |
127 | 120 |
128 virtual void OnDeactivated(const std::string& engine_id) OVERRIDE { | 121 virtual void OnDeactivated(const std::string& engine_id) OVERRIDE { |
129 if (profile_ == NULL || extension_id_.empty()) | 122 if (extension_id_.empty()) |
130 return; | 123 return; |
131 | 124 |
132 scoped_ptr<base::ListValue> args( | 125 scoped_ptr<base::ListValue> args( |
133 input_ime::OnDeactivated::Create(engine_id)); | 126 input_ime::OnDeactivated::Create(engine_id)); |
134 | 127 |
135 DispatchEventToExtension(profile_, extension_id_, | 128 DispatchEventToExtension(extension_id_, |
136 input_ime::OnDeactivated::kEventName, args.Pass()); | 129 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(extension_id_, |
169 input_ime::OnFocus::kEventName, args.Pass()); | 162 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(extension_id_, |
179 input_ime::OnBlur::kEventName, args.Pass()); | 172 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& engine_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 } |
(...skipping 12 matching lines...) Expand all Loading... | |
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(engine_id, key_data_value)); |
236 | 228 |
237 DispatchEventToExtension(profile_, extension_id_, | 229 DispatchEventToExtension(extension_id_, |
238 input_ime::OnKeyEvent::kEventName, args.Pass()); | 230 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& engine_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( |
267 input_ime::OnCandidateClicked::Create(engine_id, | 259 input_ime::OnCandidateClicked::Create(engine_id, |
268 candidate_id, | 260 candidate_id, |
269 button_enum)); | 261 button_enum)); |
270 | 262 |
271 DispatchEventToExtension(profile_, | 263 DispatchEventToExtension(extension_id_, |
272 extension_id_, | |
273 input_ime::OnCandidateClicked::kEventName, | 264 input_ime::OnCandidateClicked::kEventName, |
274 args.Pass()); | 265 args.Pass()); |
275 } | 266 } |
276 | 267 |
277 virtual void OnMenuItemActivated(const std::string& engine_id, | 268 virtual void OnMenuItemActivated(const std::string& engine_id, |
278 const std::string& menu_id) OVERRIDE { | 269 const std::string& menu_id) OVERRIDE { |
279 if (profile_ == NULL || extension_id_.empty()) | 270 if (extension_id_.empty()) |
280 return; | 271 return; |
281 | 272 |
282 scoped_ptr<base::ListValue> args( | 273 scoped_ptr<base::ListValue> args( |
283 input_ime::OnMenuItemActivated::Create(engine_id, menu_id)); | 274 input_ime::OnMenuItemActivated::Create(engine_id, menu_id)); |
284 | 275 |
285 DispatchEventToExtension(profile_, | 276 DispatchEventToExtension(extension_id_, |
286 extension_id_, | |
287 input_ime::OnMenuItemActivated::kEventName, | 277 input_ime::OnMenuItemActivated::kEventName, |
288 args.Pass()); | 278 args.Pass()); |
289 } | 279 } |
290 | 280 |
291 virtual void OnSurroundingTextChanged(const std::string& engine_id, | 281 virtual void OnSurroundingTextChanged(const std::string& engine_id, |
292 const std::string& text, | 282 const std::string& text, |
293 int cursor_pos, | 283 int cursor_pos, |
294 int anchor_pos) OVERRIDE { | 284 int anchor_pos) OVERRIDE { |
295 if (profile_ == NULL || extension_id_.empty()) | 285 if (extension_id_.empty()) |
296 return; | 286 return; |
297 | 287 |
298 input_ime::OnSurroundingTextChanged::SurroundingInfo info; | 288 input_ime::OnSurroundingTextChanged::SurroundingInfo info; |
299 info.text = text; | 289 info.text = text; |
300 info.focus = cursor_pos; | 290 info.focus = cursor_pos; |
301 info.anchor = anchor_pos; | 291 info.anchor = anchor_pos; |
302 scoped_ptr<base::ListValue> args( | 292 scoped_ptr<base::ListValue> args( |
303 input_ime::OnSurroundingTextChanged::Create(engine_id, info)); | 293 input_ime::OnSurroundingTextChanged::Create(engine_id, info)); |
304 | 294 |
305 DispatchEventToExtension(profile_, | 295 DispatchEventToExtension(extension_id_, |
306 extension_id_, | |
307 input_ime::OnSurroundingTextChanged::kEventName, | 296 input_ime::OnSurroundingTextChanged::kEventName, |
308 args.Pass()); | 297 args.Pass()); |
309 } | 298 } |
310 | 299 |
311 virtual void OnReset(const std::string& engine_id) OVERRIDE { | 300 virtual void OnReset(const std::string& engine_id) OVERRIDE { |
312 if (profile_ == NULL || extension_id_.empty()) | 301 if (extension_id_.empty()) |
313 return; | 302 return; |
314 | 303 |
315 scoped_ptr<base::ListValue> args(input_ime::OnReset::Create(engine_id)); | 304 scoped_ptr<base::ListValue> args(input_ime::OnReset::Create(engine_id)); |
316 | 305 |
317 DispatchEventToExtension(profile_, | 306 DispatchEventToExtension(extension_id_, |
318 extension_id_, | |
319 input_ime::OnReset::kEventName, | 307 input_ime::OnReset::kEventName, |
320 args.Pass()); | 308 args.Pass()); |
321 } | 309 } |
322 | 310 |
323 private: | 311 private: |
324 // Returns true if the extension is ready to accept key event, otherwise | 312 // Returns true if the extension is ready to accept key event, otherwise |
325 // returns false. | 313 // returns false. |
326 bool ShouldForwardKeyEvent() const { | 314 bool ShouldForwardKeyEvent() const { |
327 // Need to check the background page first since the | 315 // Need to check the background page first since the |
328 // ExtensionHasEventListner returns true if the extension does not have a | 316 // ExtensionHasEventListner returns true if the extension does not have a |
329 // background page. See crbug.com/394682. | 317 // background page. See crbug.com/394682. |
330 return has_background_ && extensions::EventRouter::Get(profile_) | 318 return extensions::EventRouter::Get(ProfileManager::GetActiveUserProfile()) |
331 ->ExtensionHasEventListener(extension_id_, | 319 ->ExtensionHasEventListener(extension_id_, |
332 input_ime::OnKeyEvent::kEventName); | 320 input_ime::OnKeyEvent::kEventName); |
333 } | 321 } |
334 | 322 |
335 Profile* profile_; | |
336 std::string extension_id_; | 323 std::string extension_id_; |
337 bool has_background_; | |
338 | 324 |
339 DISALLOW_COPY_AND_ASSIGN(ImeObserver); | 325 DISALLOW_COPY_AND_ASSIGN(ImeObserver); |
340 }; | 326 }; |
341 | 327 |
342 } // namespace chromeos | 328 } // namespace chromeos |
343 | 329 |
344 namespace extensions { | 330 namespace extensions { |
345 | 331 |
346 InputImeEventRouter* | 332 InputImeEventRouter* |
347 InputImeEventRouter::GetInstance() { | 333 InputImeEventRouter::GetInstance() { |
348 return Singleton<InputImeEventRouter>::get(); | 334 return Singleton<InputImeEventRouter>::get(); |
349 } | 335 } |
350 | 336 |
351 bool InputImeEventRouter::RegisterIme( | 337 bool InputImeEventRouter::RegisterImeExtension( |
352 const std::string& extension_id, | 338 const std::string& extension_id, |
353 const extensions::InputComponentInfo& component) { | 339 const std::vector<extensions::InputComponentInfo>& input_components) { |
354 #if defined(USE_X11) | 340 #if defined(USE_X11) |
355 VLOG(1) << "RegisterIme: " << extension_id << " id: " << component.id; | 341 VLOG(1) << "RegisterImeExtension: " << extension_id; |
356 | 342 |
357 Profile* profile = ProfileManager::GetActiveUserProfile(); | 343 if (engine_map_[extension_id]) |
358 // Avoid potential mem leaks due to duplicated component IDs. | 344 return false; |
359 if (!profile_engine_map_[profile][extension_id][component.id]) { | |
360 std::vector<std::string> layouts; | |
361 layouts.assign(component.layouts.begin(), component.layouts.end()); | |
362 | 345 |
363 std::vector<std::string> languages; | 346 chromeos::input_method::InputMethodManager* manager = |
364 languages.assign(component.languages.begin(), component.languages.end()); | 347 chromeos::input_method::InputMethodManager::Get(); |
348 chromeos::ComponentExtensionIMEManager* comp_ext_ime_manager = | |
349 manager->GetComponentExtensionIMEManager(); | |
365 | 350 |
366 // Ideally Observer should be per (extension_id + Profile), and multiple | 351 chromeos::input_method::InputMethodDescriptors descriptors; |
367 // InputMethodEngine can share one Observer. But it would become tricky | 352 // Only creates descriptors for 3rd party IME extension, because the |
368 // to maintain an internal map for observers which does nearly nothing | 353 // descriptors for component IME extensions are managed by InputMethodUtil. |
369 // but just make sure they can properly deleted. | 354 if (!comp_ext_ime_manager->IsWhitelistedExtension(extension_id)) { |
370 // Making Obesrver per InputMethodEngine can make things cleaner. | 355 for (std::vector<extensions::InputComponentInfo>::const_iterator it = |
371 scoped_ptr<chromeos::InputMethodEngineInterface::Observer> observer( | 356 input_components.begin(); it != input_components.end(); ++it) { |
372 new chromeos::ImeObserver(profile, extension_id)); | 357 const extensions::InputComponentInfo& component = *it; |
373 chromeos::InputMethodEngine* engine = new chromeos::InputMethodEngine(); | 358 DCHECK(component.type == extensions::INPUT_COMPONENT_TYPE_IME); |
374 engine->Initialize(observer.Pass(), | 359 |
375 component.name.c_str(), | 360 std::vector<std::string> layouts; |
376 extension_id.c_str(), | 361 layouts.assign(component.layouts.begin(), component.layouts.end()); |
377 component.id.c_str(), | 362 std::vector<std::string> languages; |
378 languages, | 363 languages.assign(component.languages.begin(), component.languages.end()); |
379 layouts, | 364 |
380 component.options_page_url, | 365 std::string input_method_id = |
Yuki
2014/08/05 07:57:18
Use a const reference.
Shu Chen
2014/08/05 14:04:31
Done.
| |
381 component.input_view_url); | 366 chromeos::extension_ime_util::GetInputMethodID( |
382 profile_engine_map_[profile][extension_id][component.id] = engine; | 367 extension_id, component.id); |
368 descriptors.push_back(chromeos::input_method::InputMethodDescriptor( | |
369 input_method_id, | |
370 component.name, | |
371 std::string(), // TODO(uekawa): Set short name. | |
372 layouts, | |
373 languages, | |
374 false, // 3rd party IMEs are always not for login. | |
375 component.options_page_url, | |
376 component.input_view_url)); | |
377 } | |
383 } | 378 } |
384 | 379 |
380 scoped_ptr<chromeos::InputMethodEngineInterface::Observer> observer( | |
381 new chromeos::ImeObserver(extension_id)); | |
382 chromeos::InputMethodEngine* engine = new chromeos::InputMethodEngine(); | |
383 engine->Initialize(observer.Pass(), extension_id.c_str()); | |
384 engine_map_[extension_id] = engine; | |
385 manager->AddInputMethodExtension(extension_id, descriptors, engine); | |
386 | |
385 return true; | 387 return true; |
386 #else | 388 #else |
387 // TODO(spang): IME support under ozone. | 389 // TODO(spang): IME support under ozone. |
388 NOTIMPLEMENTED(); | 390 NOTIMPLEMENTED(); |
389 return false; | 391 return false; |
390 #endif | 392 #endif |
391 } | 393 } |
392 | 394 |
393 void InputImeEventRouter::UnregisterAllImes(const std::string& extension_id) { | 395 void InputImeEventRouter::UnregisterAllImes(const std::string& extension_id) { |
394 Profile* profile = ProfileManager::GetActiveUserProfile(); | 396 if (engine_map_.find(extension_id) != engine_map_.end()) { |
Yuki
2014/08/05 07:57:18
Could you optimize the code a little more?
find()
Shu Chen
2014/08/05 14:04:31
Done.
| |
395 ProfileEngineMap::iterator extension_map = | 397 chromeos::input_method::InputMethodManager::Get() |
396 profile_engine_map_.find(profile); | 398 ->RemoveInputMethodExtension(extension_id); |
397 if (extension_map == profile_engine_map_.end()) | 399 delete engine_map_[extension_id]; |
398 return; | 400 engine_map_.erase(extension_id); |
399 ExtensionMap::iterator engine_map = extension_map->second.find(extension_id); | 401 } |
400 if (engine_map == extension_map->second.end()) | |
401 return; | |
402 STLDeleteContainerPairSecondPointers(engine_map->second.begin(), | |
403 engine_map->second.end()); | |
404 extension_map->second.erase(extension_id); | |
405 profile_engine_map_.erase(profile); | |
406 } | 402 } |
407 | 403 |
408 InputMethodEngineInterface* InputImeEventRouter::GetEngine( | 404 InputMethodEngineInterface* InputImeEventRouter::GetEngine( |
409 const std::string& extension_id, const std::string& engine_id) { | 405 const std::string& extension_id, const std::string& engine_id) { |
410 // IME can only work on active user profile. | 406 if (engine_map_.find(extension_id) == engine_map_.end()) |
411 Profile* profile = ProfileManager::GetActiveUserProfile(); | 407 return NULL; |
412 | 408 |
413 ProfileEngineMap::const_iterator extension_map = | 409 if (engine_map_[extension_id]->GetActiveEngineId() == engine_id) |
414 profile_engine_map_.find(profile); | 410 return engine_map_[extension_id]; |
415 if (extension_map == profile_engine_map_.end()) | 411 |
416 return NULL; | 412 return NULL; |
417 ExtensionMap::const_iterator engine_map = | |
418 extension_map->second.find(extension_id); | |
419 if (engine_map == extension_map->second.end()) | |
420 return NULL; | |
421 EngineMap::const_iterator engine = engine_map->second.find(engine_id); | |
422 if (engine == engine_map->second.end()) | |
423 return NULL; | |
424 return engine->second; | |
425 } | 413 } |
426 | 414 |
427 InputMethodEngineInterface* InputImeEventRouter::GetActiveEngine( | 415 InputMethodEngineInterface* InputImeEventRouter::GetActiveEngine( |
428 const std::string& extension_id) { | 416 const std::string& extension_id) { |
429 // IME can only work on active user profile. | 417 if (engine_map_.find(extension_id) == engine_map_.end()) |
430 Profile* profile = ProfileManager::GetActiveUserProfile(); | |
431 | |
432 ProfileEngineMap::const_iterator extension_map = | |
433 profile_engine_map_.find(profile); | |
434 if (extension_map == profile_engine_map_.end()) | |
435 return NULL; | |
436 ExtensionMap::const_iterator engine_map = | |
437 extension_map->second.find(extension_id); | |
438 if (engine_map == extension_map->second.end()) | |
439 return NULL; | 418 return NULL; |
440 | 419 |
441 for (EngineMap::const_iterator i = engine_map->second.begin(); | 420 if (engine_map_[extension_id]->IsActive()) |
442 i != engine_map->second.end(); | 421 return engine_map_[extension_id]; |
443 ++i) { | 422 |
444 if (i->second->IsActive()) | |
445 return i->second; | |
446 } | |
447 return NULL; | 423 return NULL; |
448 } | 424 } |
449 | 425 |
450 void InputImeEventRouter::OnKeyEventHandled( | 426 void InputImeEventRouter::OnKeyEventHandled( |
451 const std::string& extension_id, | 427 const std::string& extension_id, |
452 const std::string& request_id, | 428 const std::string& request_id, |
453 bool handled) { | 429 bool handled) { |
454 RequestMap::iterator request = request_map_.find(request_id); | 430 RequestMap::iterator request = request_map_.find(request_id); |
455 if (request == request_map_.end()) { | 431 if (request == request_map_.end()) { |
456 LOG(ERROR) << "Request ID not found: " << request_id; | 432 LOG(ERROR) << "Request ID not found: " << request_id; |
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
820 InputImeEventRouter::GetInstance()->OnKeyEventHandled( | 796 InputImeEventRouter::GetInstance()->OnKeyEventHandled( |
821 extension_id(), params->request_id, params->response); | 797 extension_id(), params->request_id, params->response); |
822 return true; | 798 return true; |
823 } | 799 } |
824 | 800 |
825 InputImeAPI::InputImeAPI(content::BrowserContext* context) | 801 InputImeAPI::InputImeAPI(content::BrowserContext* context) |
826 : browser_context_(context), extension_registry_observer_(this) { | 802 : browser_context_(context), extension_registry_observer_(this) { |
827 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); | 803 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); |
828 | 804 |
829 EventRouter* event_router = EventRouter::Get(browser_context_); | 805 EventRouter* event_router = EventRouter::Get(browser_context_); |
830 event_router->RegisterObserver(this, input_ime::OnActivate::kEventName); | |
831 event_router->RegisterObserver(this, input_ime::OnFocus::kEventName); | 806 event_router->RegisterObserver(this, input_ime::OnFocus::kEventName); |
832 } | 807 } |
833 | 808 |
834 InputImeAPI::~InputImeAPI() { | 809 InputImeAPI::~InputImeAPI() { |
835 EventRouter::Get(browser_context_)->UnregisterObserver(this); | 810 EventRouter::Get(browser_context_)->UnregisterObserver(this); |
836 } | 811 } |
837 | 812 |
838 static base::LazyInstance<BrowserContextKeyedAPIFactory<InputImeAPI> > | 813 static base::LazyInstance<BrowserContextKeyedAPIFactory<InputImeAPI> > |
839 g_factory = LAZY_INSTANCE_INITIALIZER; | 814 g_factory = LAZY_INSTANCE_INITIALIZER; |
840 | 815 |
841 // static | 816 // static |
842 BrowserContextKeyedAPIFactory<InputImeAPI>* InputImeAPI::GetFactoryInstance() { | 817 BrowserContextKeyedAPIFactory<InputImeAPI>* InputImeAPI::GetFactoryInstance() { |
843 return g_factory.Pointer(); | 818 return g_factory.Pointer(); |
844 } | 819 } |
845 | 820 |
846 void InputImeAPI::OnExtensionLoaded(content::BrowserContext* browser_context, | 821 void InputImeAPI::OnExtensionLoaded(content::BrowserContext* browser_context, |
847 const Extension* extension) { | 822 const Extension* extension) { |
848 const std::vector<InputComponentInfo>* input_components = | 823 const std::vector<InputComponentInfo>* input_components = |
849 extensions::InputComponents::GetInputComponents(extension); | 824 extensions::InputComponents::GetInputComponents(extension); |
850 if (!input_components) | 825 if (input_components) |
851 return; | 826 input_ime_event_router()->RegisterImeExtension( |
852 for (std::vector<extensions::InputComponentInfo>::const_iterator component = | 827 extension->id(), *input_components); |
853 input_components->begin(); | |
854 component != input_components->end(); | |
855 ++component) { | |
856 if (component->type == extensions::INPUT_COMPONENT_TYPE_IME) { | |
857 // Don't pass profile_ to register ime, instead always use | |
858 // GetActiveUserProfile. It is because: | |
859 // The original profile for login screen is called signin profile. | |
860 // And the active profile is the incognito profile based on signin | |
861 // profile. 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 input_ime_event_router()->RegisterIme(extension->id(), *component); | |
865 } | |
866 } | |
867 } | 828 } |
868 | 829 |
869 void InputImeAPI::OnExtensionUnloaded(content::BrowserContext* browser_context, | 830 void InputImeAPI::OnExtensionUnloaded(content::BrowserContext* browser_context, |
870 const Extension* extension, | 831 const Extension* extension, |
871 UnloadedExtensionInfo::Reason reason) { | 832 UnloadedExtensionInfo::Reason reason) { |
872 const std::vector<InputComponentInfo>* input_components = | 833 const std::vector<InputComponentInfo>* input_components = |
873 extensions::InputComponents::GetInputComponents(extension); | 834 extensions::InputComponents::GetInputComponents(extension); |
874 if (!input_components) | 835 if (!input_components) |
875 return; | 836 return; |
876 if (input_components->size() > 0) | 837 if (input_components->size() > 0) |
877 input_ime_event_router()->UnregisterAllImes(extension->id()); | 838 input_ime_event_router()->UnregisterAllImes(extension->id()); |
878 } | 839 } |
879 | 840 |
880 void InputImeAPI::OnListenerAdded(const EventListenerInfo& details) { | 841 void InputImeAPI::OnListenerAdded(const EventListenerInfo& details) { |
881 InputMethodEngineInterface* engine = | 842 InputMethodEngineInterface* engine = |
882 input_ime_event_router()->GetActiveEngine(details.extension_id); | 843 input_ime_event_router()->GetActiveEngine(details.extension_id); |
844 // Notifies the IME extension for IME ready with onActivate/onFocus events. | |
883 if (engine) | 845 if (engine) |
884 engine->NotifyImeReady(); | 846 engine->Enable(engine->GetActiveEngineId()); |
885 } | 847 } |
886 | 848 |
887 InputImeEventRouter* InputImeAPI::input_ime_event_router() { | 849 InputImeEventRouter* InputImeAPI::input_ime_event_router() { |
888 return InputImeEventRouter::GetInstance(); | 850 return InputImeEventRouter::GetInstance(); |
889 } | 851 } |
890 | 852 |
891 } // namespace extensions | 853 } // namespace extensions |
OLD | NEW |