Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / chromeos / accessibility / spoken_feedback_event_rewriter.cc
blobba7dc7d30683cf982a0b1a3fd0e0bf6f99ca95c1
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"
7 #include <string>
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 {
23 return true;
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())
32 return false;
33 content::BrowserContext* context =
34 chromeos::AccessibilityManager::Get()->profile();
35 if (!context)
36 return false;
38 const extensions::Extension* extension =
39 extensions::ExtensionRegistry::Get(context)->enabled_extensions().GetByID(
40 extension_misc::kChromeVoxExtensionId);
41 if (!extension)
42 return false;
44 extensions::EventRouter* event_router = extensions::EventRouter::Get(context);
45 if (!event_router->ExtensionHasEventListener(
46 extension_misc::kChromeVoxExtensionId, "commands.onCommand"))
47 return false;
49 const extensions::CommandMap* commands =
50 extensions::CommandsInfo::GetNamedCommands(extension);
51 if (!commands)
52 return false;
54 int modifiers = key_event.flags() & kAllModifiers;
55 std::string command_name;
57 if (is_sequencing_) {
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())
77 return false;
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());
90 return true;
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;