1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/accessibility/spoken_feedback_event_rewriter.h"
9 #include "base/values.h"
10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
12 #include "chrome/browser/profiles/profile_manager.h"
13 #include "chrome/common/extensions/api/commands/commands_handler.h"
14 #include "chrome/common/extensions/extension_constants.h"
15 #include "extensions/browser/event_router.h"
16 #include "extensions/browser/extension_registry.h"
17 #include "ui/events/event.h"
19 SpokenFeedbackEventRewriterDelegate::SpokenFeedbackEventRewriterDelegate()
20 : is_sequencing_(false) {}
22 bool SpokenFeedbackEventRewriterDelegate::IsSpokenFeedbackEnabled() const {
26 bool SpokenFeedbackEventRewriterDelegate::DispatchKeyEventToChromeVox(
27 const ui::KeyEvent
& key_event
) {
28 int kAllModifiers
= ui::EF_SHIFT_DOWN
| ui::EF_CONTROL_DOWN
|
29 ui::EF_ALT_DOWN
| ui::EF_COMMAND_DOWN
;
31 if (!chromeos::AccessibilityManager::Get())
33 content::BrowserContext
* context
=
34 chromeos::AccessibilityManager::Get()->profile();
38 const extensions::Extension
* extension
=
39 extensions::ExtensionRegistry::Get(context
)->enabled_extensions().GetByID(
40 extension_misc::kChromeVoxExtensionId
);
44 extensions::EventRouter
* event_router
= extensions::EventRouter::Get(context
);
45 if (!event_router
->ExtensionHasEventListener(
46 extension_misc::kChromeVoxExtensionId
, "commands.onCommand"))
49 const extensions::CommandMap
* commands
=
50 extensions::CommandsInfo::GetNamedCommands(extension
);
54 int modifiers
= key_event
.flags() & kAllModifiers
;
55 std::string command_name
;
58 is_sequencing_
= false;
59 modifiers
|= ui::EF_SHIFT_DOWN
| ui::EF_COMMAND_DOWN
;
60 // This command name doesn't exist; used simply to cause ChromeVox to reset
61 // its sequencing state in case command lookup fails.
62 command_name
= "sequenceCommand";
65 for (auto iter
: *commands
) {
66 int command_modifiers
=
67 iter
.second
.accelerator().modifiers() & kAllModifiers
;
68 if (iter
.second
.accelerator().key_code() == key_event
.key_code() &&
69 command_modifiers
== modifiers
) {
70 command_name
= iter
.second
.command_name();
71 if (!is_sequencing_
&& command_name
.substr(0, 14) == "sequencePrefix")
72 is_sequencing_
= true;
76 if (command_name
.empty())
79 scoped_ptr
<base::ListValue
> args(new base::ListValue());
80 args
->Append(new base::StringValue(command_name
));
82 scoped_ptr
<extensions::Event
> extension_event(
83 new extensions::Event(extensions::events::COMMANDS_ON_COMMAND
,
84 "commands.onCommand", args
.Pass()));
85 extension_event
->restrict_to_browser_context
= context
;
87 event_router
->DispatchEventToExtension(extension_misc::kChromeVoxExtensionId
,
88 extension_event
.Pass());
93 SpokenFeedbackEventRewriter::SpokenFeedbackEventRewriter() {
94 delegate_
.reset(new SpokenFeedbackEventRewriterDelegate());
97 SpokenFeedbackEventRewriter::~SpokenFeedbackEventRewriter() {
100 void SpokenFeedbackEventRewriter::SetDelegateForTest(
101 scoped_ptr
<SpokenFeedbackEventRewriterDelegate
> delegate
) {
102 delegate_
= delegate
.Pass();
105 ui::EventRewriteStatus
SpokenFeedbackEventRewriter::RewriteEvent(
106 const ui::Event
& event
,
107 scoped_ptr
<ui::Event
>* new_event
) {
108 if (!delegate_
->IsSpokenFeedbackEnabled())
109 return ui::EVENT_REWRITE_CONTINUE
;
111 if ((event
.type() != ui::ET_KEY_PRESSED
&&
112 event
.type() != ui::ET_KEY_RELEASED
))
113 return ui::EVENT_REWRITE_CONTINUE
;
115 const ui::KeyEvent key_event
= static_cast<const ui::KeyEvent
&>(event
);
116 if (event
.type() == ui::ET_KEY_RELEASED
) {
117 std::vector
<int>::iterator it
=
118 std::find(captured_key_codes_
.begin(), captured_key_codes_
.end(),
119 key_event
.key_code());
120 if (it
!= captured_key_codes_
.end()) {
121 captured_key_codes_
.erase(it
);
122 return ui::EVENT_REWRITE_DISCARD
;
124 return ui::EVENT_REWRITE_CONTINUE
;
127 if (delegate_
->DispatchKeyEventToChromeVox(key_event
)) {
128 captured_key_codes_
.push_back(key_event
.key_code());
129 return ui::EVENT_REWRITE_DISCARD
;
131 return ui::EVENT_REWRITE_CONTINUE
;
134 ui::EventRewriteStatus
SpokenFeedbackEventRewriter::NextDispatchEvent(
135 const ui::Event
& last_event
,
136 scoped_ptr
<ui::Event
>* new_event
) {
137 return ui::EVENT_REWRITE_CONTINUE
;