Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: chrome/browser/extensions/api/input_ime/input_ime_api.cc

Issue 433163005: Refactoring for InputMethodEngine and InputMethodEventRouter. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fixed a bug. Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698