summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzork@chromium.org <zork@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-08 05:18:06 +0000
committerzork@chromium.org <zork@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-08 05:18:06 +0000
commitcd0b04c94c9d2dd922bcdd63b9325dfdacef3b85 (patch)
tree86cd0e0bad4e5a3ecbdf44da6cbc2836c154950c
parentb103b5975f6ac1b1b491510b8246091f160d9013 (diff)
downloadchromium_src-cd0b04c94c9d2dd922bcdd63b9325dfdacef3b85.zip
chromium_src-cd0b04c94c9d2dd922bcdd63b9325dfdacef3b85.tar.gz
chromium_src-cd0b04c94c9d2dd922bcdd63b9325dfdacef3b85.tar.bz2
Make OnKeyEvent asynchronous to match the design.
BUG=None TEST=None Review URL: http://codereview.chromium.org/7721006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@100107 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/chromeos/input_method/ibus_engine_controller.cc67
-rw-r--r--chrome/browser/chromeos/input_method/ibus_engine_controller.h8
-rw-r--r--chrome/browser/chromeos/input_method/input_method_engine.cc17
-rw-r--r--chrome/browser/chromeos/input_method/input_method_engine.h11
-rw-r--r--chrome/browser/extensions/extension_function_dispatcher.cc2
-rw-r--r--chrome/browser/extensions/extension_input_ime_api.cc59
-rw-r--r--chrome/browser/extensions/extension_input_ime_api.h19
-rw-r--r--chrome/common/extensions/api/extension_api.json11
-rw-r--r--chrome/renderer/resources/extension_process_bindings.js30
9 files changed, 205 insertions, 19 deletions
diff --git a/chrome/browser/chromeos/input_method/ibus_engine_controller.cc b/chrome/browser/chromeos/input_method/ibus_engine_controller.cc
index fa38801..7654bfd 100644
--- a/chrome/browser/chromeos/input_method/ibus_engine_controller.cc
+++ b/chrome/browser/chromeos/input_method/ibus_engine_controller.cc
@@ -32,7 +32,7 @@ namespace input_method {
(G_TYPE_CHECK_CLASS_TYPE((klass), IBUS_TYPE_CHROMEOS_ENGINE))
#define IBUS_CHROMEOS_ENGINE_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS((obj), IBUS_TYPE_CHROMEOS_ENGINE, \
- IBusChromeOSEngine))
+ IBusChromeOSEngineClass))
class IBusEngineControllerImpl;
struct IBusChromeOSEngine {
@@ -332,6 +332,15 @@ class IBusEngineControllerImpl : public IBusEngineController {
}
}
+ virtual void KeyEventDone(KeyEventHandle* key_data, bool handled) {
+ GDBusMethodInvocation* invocation =
+ reinterpret_cast<GDBusMethodInvocation*>(key_data);
+
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(b)", handled));
+ }
+
+
static void InitEngineClass(IBusChromeOSEngineClass *klass) {
GObjectClass *object_class = G_OBJECT_CLASS(klass);
IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS(klass);
@@ -340,7 +349,9 @@ class IBusEngineControllerImpl : public IBusEngineController {
object_class->constructor = EngineConstructor;
ibus_object_class->destroy = (IBusObjectDestroyFunc) OnDestroy;
- engine_class->process_key_event = OnProcessKeyEvent;
+ IBUS_SERVICE_CLASS(klass)->service_method_call = OnServiceMethodCall;
+
+ engine_class->process_key_event = NULL;
engine_class->reset = OnReset;
engine_class->enable = OnEnable;
engine_class->disable = OnDisable;
@@ -439,17 +450,51 @@ class IBusEngineControllerImpl : public IBusEngineController {
return true;
}
- static gboolean OnProcessKeyEvent(IBusEngine* ibus_engine, guint keyval,
- guint keycode, guint modifiers) {
+ static void OnServiceMethodCall(IBusService* service,
+ GDBusConnection* connection,
+ const gchar* sender,
+ const gchar* object_path,
+ const gchar* interface_name,
+ const gchar* method_name,
+ GVariant* parameters,
+ GDBusMethodInvocation* invocation) {
+ if (g_strcmp0(method_name, "ProcessKeyEvent") == 0) {
+ // Override the default ProcessKeyEvent handler so that we can send the
+ // response asynchronously.
+ IBusEngine *engine = IBUS_ENGINE(service);
+
+ guint keyval;
+ guint keycode;
+ guint state;
+ g_variant_get(parameters, "(uuu)", &keyval, &keycode, &state);
+
+ OnProcessKeyEvent(engine, keyval, keycode, state, invocation);
+ } else {
+ IBUS_SERVICE_CLASS(
+ ibus_chromeos_engine_parent_class)->service_method_call(
+ service,
+ connection,
+ sender,
+ object_path,
+ interface_name,
+ method_name,
+ parameters,
+ invocation);
+ }
+ }
+
+ static void OnProcessKeyEvent(IBusEngine* ibus_engine, guint keyval,
+ guint keycode, guint modifiers,
+ GDBusMethodInvocation* key_data) {
VLOG(1) << "OnProcessKeyEvent";
- // TODO: Use async version.
IBusChromeOSEngine* engine = IBUS_CHROMEOS_ENGINE(ibus_engine);
- engine->connection->observer_->OnKeyEvent(!(modifiers & IBUS_RELEASE_MASK),
- keyval, keycode,
- modifiers & IBUS_MOD1_MASK,
- modifiers & IBUS_CONTROL_MASK,
- modifiers & IBUS_SHIFT_MASK);
- return true;
+ engine->connection->observer_->OnKeyEvent(
+ !(modifiers & IBUS_RELEASE_MASK),
+ keyval, keycode,
+ modifiers & IBUS_MOD1_MASK,
+ modifiers & IBUS_CONTROL_MASK,
+ modifiers & IBUS_SHIFT_MASK,
+ reinterpret_cast<KeyEventHandle*>(key_data));
}
static void OnReset(IBusEngine* ibus_engine) {
diff --git a/chrome/browser/chromeos/input_method/ibus_engine_controller.h b/chrome/browser/chromeos/input_method/ibus_engine_controller.h
index a5763dc..b7f741b 100644
--- a/chrome/browser/chromeos/input_method/ibus_engine_controller.h
+++ b/chrome/browser/chromeos/input_method/ibus_engine_controller.h
@@ -14,6 +14,8 @@
namespace chromeos {
namespace input_method {
+struct KeyEventHandle;
+
// IBusEngineController is used to encapsulate an ibus engine.
class IBusEngineController {
public:
@@ -22,7 +24,8 @@ class IBusEngineController {
// Called when a key is pressed or released.
virtual void OnKeyEvent(bool key_press, unsigned int keyval,
unsigned int keycode, bool alt_key,
- bool ctrl_key, bool shift_key) = 0;
+ bool ctrl_key, bool shift_key,
+ KeyEventHandle* key_data) = 0;
// Called when the engine should reset its internal state.
virtual void OnReset() = 0;
@@ -114,6 +117,9 @@ class IBusEngineController {
// Set the posistion of the cursor in the candidate window.
virtual void SetCursorPosition(unsigned int position) = 0;
+
+ // Inform the engine that a key event has been processed.
+ virtual void KeyEventDone(KeyEventHandle* key_data, bool handled) = 0;
};
} // namespace input_method
diff --git a/chrome/browser/chromeos/input_method/input_method_engine.cc b/chrome/browser/chromeos/input_method/input_method_engine.cc
index f758409..e4b55be 100644
--- a/chrome/browser/chromeos/input_method/input_method_engine.cc
+++ b/chrome/browser/chromeos/input_method/input_method_engine.cc
@@ -90,6 +90,8 @@ class InputMethodEngineImpl
virtual bool IsActive() const {
return active_;
}
+ virtual void KeyEventDone(input_method::KeyEventHandle* key_data,
+ bool handled);
virtual void OnReset();
virtual void OnEnable();
@@ -97,8 +99,9 @@ class InputMethodEngineImpl
virtual void OnFocusIn();
virtual void OnFocusOut();
virtual void OnKeyEvent(bool key_press, unsigned int keyval,
- unsigned int keycode, bool alt_key,
- bool ctrl_key, bool shift_key);
+ unsigned int keycode, bool alt_key, bool ctrl_key,
+ bool shift_key,
+ input_method::KeyEventHandle* key_data);
virtual void OnPropertyActivate(const char* name, unsigned int state);
virtual void OnCandidateClicked(unsigned int index, unsigned int button,
unsigned int state);
@@ -359,6 +362,11 @@ void InputMethodEngineImpl::UpdateMenuItems(
// TODO(zork): Implement this function
}
+void InputMethodEngineImpl::KeyEventDone(input_method::KeyEventHandle* key_data,
+ bool handled) {
+ connection_->KeyEventDone(key_data, handled);
+}
+
void InputMethodEngineImpl::OnReset() {
// Ignored
}
@@ -393,7 +401,8 @@ void InputMethodEngineImpl::OnFocusOut() {
void InputMethodEngineImpl::OnKeyEvent(bool key_press, unsigned int keyval,
unsigned int keycode, bool alt_key,
- bool ctrl_key, bool shift_key) {
+ bool ctrl_key, bool shift_key,
+ input_method::KeyEventHandle* key_data) {
KeyboardEvent event;
event.type = key_press ? "keydown" : "keyup";
event.key = input_method::GetIBusKey(keyval);
@@ -401,7 +410,7 @@ void InputMethodEngineImpl::OnKeyEvent(bool key_press, unsigned int keyval,
event.alt_key = alt_key;
event.ctrl_key = ctrl_key;
event.shift_key = shift_key;
- observer_->OnKeyEvent(engine_id_, event);
+ observer_->OnKeyEvent(engine_id_, event, key_data);
}
void InputMethodEngineImpl::OnPropertyActivate(const char* name,
diff --git a/chrome/browser/chromeos/input_method/input_method_engine.h b/chrome/browser/chromeos/input_method/input_method_engine.h
index de9c871..3cf82dd 100644
--- a/chrome/browser/chromeos/input_method/input_method_engine.h
+++ b/chrome/browser/chromeos/input_method/input_method_engine.h
@@ -11,6 +11,10 @@
namespace chromeos {
+namespace input_method {
+struct KeyEventHandle;
+} // namespace input_method
+
extern const char* kExtensionImePrefix;
// InputMethodEngine is used to translate from the Chrome IME API to the native
@@ -87,7 +91,8 @@ class InputMethodEngine {
// Called when the user pressed a key with a text field focused.
virtual void OnKeyEvent(const std::string& engine_id,
- const KeyboardEvent& event) = 0;
+ const KeyboardEvent& event,
+ input_method::KeyEventHandle* key_data) = 0;
// Called when the user clicks on an item in the candidate list.
virtual void OnCandidateClicked(const std::string& engine_id,
@@ -172,6 +177,10 @@ class InputMethodEngine {
// Returns true if this IME is active, false if not.
virtual bool IsActive() const = 0;
+ // Inform the engine that a key event has been processed.
+ virtual void KeyEventDone(input_method::KeyEventHandle* key_data,
+ bool handled) = 0;
+
// Create an IME engine.
static InputMethodEngine* CreateEngine(
InputMethodEngine::Observer* observer,
diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc
index 79d6fa3..8e871ee 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.cc
+++ b/chrome/browser/extensions/extension_function_dispatcher.cc
@@ -315,6 +315,8 @@ void FactoryRegistry::ResetFunctions() {
RegisterFunction<SetCursorPositionFunction>();
RegisterFunction<SetMenuItemsFunction>();
RegisterFunction<UpdateMenuItemsFunction>();
+
+ RegisterFunction<InputEventHandled>();
#if defined(TOUCH_UI)
RegisterFunction<CandidateClickedInputUiFunction>();
RegisterFunction<CursorUpInputUiFunction>();
diff --git a/chrome/browser/extensions/extension_input_ime_api.cc b/chrome/browser/extensions/extension_input_ime_api.cc
index 662b5c2..13e59b5 100644
--- a/chrome/browser/extensions/extension_input_ime_api.cc
+++ b/chrome/browser/extensions/extension_input_ime_api.cc
@@ -5,6 +5,7 @@
#include "chrome/browser/extensions/extension_input_ime_api.h"
#include "base/json/json_writer.h"
+#include "base/string_number_conversions.h"
#include "base/values.h"
#include "chrome/browser/chromeos/input_method/input_method_engine.h"
#include "chrome/browser/extensions/extension_event_router.h"
@@ -115,12 +116,18 @@ class ImeObserver : public chromeos::InputMethodEngine::Observer {
}
virtual void OnKeyEvent(const std::string& engine_id,
- const InputMethodEngine::KeyboardEvent& event) {
+ const InputMethodEngine::KeyboardEvent& event,
+ chromeos::input_method::KeyEventHandle* key_data) {
if (profile_ == NULL || extension_id_.empty())
return;
+ std::string request_id =
+ ExtensionInputImeEventRouter::GetInstance()->AddRequest(engine_id,
+ key_data);
+
DictionaryValue* dict = new DictionaryValue();
dict->SetString("type", event.type);
+ dict->SetString("requestId", request_id);
dict->SetString("key", event.key);
dict->SetString("keyCode", event.key_code);
dict->SetBoolean("altKey", event.alt_key);
@@ -200,7 +207,8 @@ ExtensionInputImeEventRouter::GetInstance() {
return Singleton<ExtensionInputImeEventRouter>::get();
}
-ExtensionInputImeEventRouter::ExtensionInputImeEventRouter() {
+ExtensionInputImeEventRouter::ExtensionInputImeEventRouter()
+ : next_request_id_(1) {
}
ExtensionInputImeEventRouter::~ExtensionInputImeEventRouter() {
@@ -296,6 +304,40 @@ chromeos::InputMethodEngine* ExtensionInputImeEventRouter::GetActiveEngine(
return NULL;
}
+void ExtensionInputImeEventRouter::OnEventHandled(
+ const std::string& extension_id,
+ const std::string& request_id,
+ bool handled) {
+ RequestMap::iterator request = request_map_.find(request_id);
+ if (request == request_map_.end()) {
+ LOG(ERROR) << "Request ID not found: " << request_id;
+ return;
+ }
+
+ std::string engine_id = request->second.first;
+ chromeos::input_method::KeyEventHandle* key_data = request->second.second;
+ request_map_.erase(request);
+
+ chromeos::InputMethodEngine* engine = GetEngine(extension_id, engine_id);
+ if (!engine) {
+ LOG(ERROR) << "Engine does not exist: " << engine_id;
+ return;
+ }
+
+ engine->KeyEventDone(key_data, handled);
+}
+
+std::string ExtensionInputImeEventRouter::AddRequest(
+ const std::string& engine_id,
+ chromeos::input_method::KeyEventHandle* key_data) {
+ std::string request_id = base::IntToString(next_request_id_);
+ ++next_request_id_;
+
+ request_map_[request_id] = std::make_pair(engine_id, key_data);
+
+ return request_id;
+}
+
bool SetCompositionFunction::RunImpl() {
chromeos::InputMethodEngine* engine =
ExtensionInputImeEventRouter::GetInstance()->
@@ -631,4 +673,17 @@ bool UpdateMenuItemsFunction::RunImpl() {
// TODO
return true;
}
+
+bool InputEventHandled::RunImpl() {
+ std::string request_id_str;
+ EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &request_id_str));
+
+ bool handled = false;
+ EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(1, &handled));
+
+ ExtensionInputImeEventRouter::GetInstance()->OnEventHandled(
+ extension_id(), request_id_str, handled);
+
+ return true;
+}
#endif
diff --git a/chrome/browser/extensions/extension_input_ime_api.h b/chrome/browser/extensions/extension_input_ime_api.h
index 7a714d2..b1ebeaced 100644
--- a/chrome/browser/extensions/extension_input_ime_api.h
+++ b/chrome/browser/extensions/extension_input_ime_api.h
@@ -37,8 +37,18 @@ class ExtensionInputImeEventRouter {
chromeos::InputMethodEngine* GetActiveEngine(const std::string& extension_id);
+ // Called when a key event was handled.
+ void OnEventHandled(const std::string& extension_id,
+ const std::string& request_id,
+ bool handled);
+
+ std::string AddRequest(const std::string& engine_id,
+ chromeos::input_method::KeyEventHandle* key_data);
+
private:
friend struct DefaultSingletonTraits<ExtensionInputImeEventRouter>;
+ typedef std::map<std::string, std::pair<std::string,
+ chromeos::input_method::KeyEventHandle*> > RequestMap;
ExtensionInputImeEventRouter();
~ExtensionInputImeEventRouter();
@@ -48,6 +58,9 @@ class ExtensionInputImeEventRouter {
std::map<std::string, std::map<std::string, chromeos::ImeObserver*> >
observers_;
+ unsigned int next_request_id_;
+ RequestMap request_map_;
+
DISALLOW_COPY_AND_ASSIGN(ExtensionInputImeEventRouter);
};
@@ -111,4 +124,10 @@ class UpdateMenuItemsFunction : public AsyncExtensionFunction {
"experimental.input.updateMenuItems");
};
+class InputEventHandled : public AsyncExtensionFunction {
+ public:
+ virtual bool RunImpl();
+ DECLARE_EXTENSION_FUNCTION_NAME("experimental.input.eventHandled");
+};
+
#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_INPUT_IME_API_H_
diff --git a/chrome/common/extensions/api/extension_api.json b/chrome/common/extensions/api/extension_api.json
index 3c9d5ad..dbc5e60 100644
--- a/chrome/common/extensions/api/extension_api.json
+++ b/chrome/common/extensions/api/extension_api.json
@@ -2823,6 +2823,7 @@
"description": "See http://www.w3.org/TR/DOM-Level-3-Events/#events-KeyboardEvent",
"properties": {
"type": {"type": "string", "description": "One of keyup or keydown.", "enum": ["keyup", "keydown"]},
+ "requestId": {"type": "string", "description": "The ID of the request."},
"key": {"type": "string", "description": "Value of the key being pressed"},
"keyCode": {"type": "string", "description": "Value of the key being press, unmodified by control keys."},
"altKey": {"type": "boolean", "optional": true, "description": "Whether or not the ALT key is pressed."},
@@ -3325,6 +3326,16 @@
"minimum": 0
}
]
+ },
+ {
+ "name": "eventHandled",
+ "nodoc": true,
+ "type": "function",
+ "description": "Used internally to send a response for onKeyEvent.",
+ "parameters": [
+ {"type": "string", "name": "requestId"},
+ {"type": "boolean", "name": "response"}
+ ]
}
],
"events": [
diff --git a/chrome/renderer/resources/extension_process_bindings.js b/chrome/renderer/resources/extension_process_bindings.js
index c0c93ee..4dd5461 100644
--- a/chrome/renderer/resources/extension_process_bindings.js
+++ b/chrome/renderer/resources/extension_process_bindings.js
@@ -415,6 +415,35 @@ var chrome = chrome || {};
customBindings['ContentSetting'] = ContentSetting;
}
+ function setupInputEvents() {
+ chrome.experimental.input.onKeyEvent.dispatch =
+ function(engineID, keyData) {
+ var args = Array.prototype.slice.call(arguments);
+ if (this.validate_) {
+ var validationErrors = this.validate_(args);
+ if (validationErrors) {
+ chrome.experimental.input.eventHandled(requestId, false);
+ return validationErrors;
+ }
+ }
+ if (this.listeners_.length > 1) {
+ console.error("Too many listeners for 'onKeyEvent': " + e.stack);
+ chrome.experimental.input.eventHandled(requestId, false);
+ return;
+ }
+ for (var i = 0; i < this.listeners_.length; i++) {
+ try {
+ var requestId = keyData.requestId;
+ var result = this.listeners_[i].apply(null, args);
+ chrome.experimental.input.eventHandled(requestId, result);
+ } catch (e) {
+ console.error("Error in event handler for 'onKeyEvent': " + e.stack);
+ chrome.experimental.input.eventHandled(requestId, false);
+ }
+ }
+ };
+ }
+
// Page action events send (pageActionId, {tabId, tabUrl}).
function setupPageActionEvents(extensionId) {
var pageActions = GetCurrentPageActions(extensionId);
@@ -1021,6 +1050,7 @@ var chrome = chrome || {};
setupPageActionEvents(extensionId);
setupToolstripEvents(GetRenderViewId());
setupHiddenContextMenuEvent(extensionId);
+ setupInputEvents();
setupOmniboxEvents();
setupTtsEvents();
});