| // Copyright 2015 The Cobalt Authors. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "cobalt/input/input_device_manager_fuzzer.h" |
| |
| #include "base/basictypes.h" |
| #include "base/bind.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/rand_util.h" |
| #include "cobalt/base/tokens.h" |
| #include "cobalt/dom/keyboard_event.h" |
| #include "cobalt/dom/keycode.h" |
| |
| namespace cobalt { |
| namespace input { |
| |
| namespace { |
| |
| // Initialize the set of key events we are able to produce. |
| const int kKeyCodes[] = {dom::keycode::kUp, dom::keycode::kDown, |
| dom::keycode::kLeft, dom::keycode::kRight, |
| dom::keycode::kReturn, dom::keycode::kEscape}; |
| |
| } // namespace |
| |
| InputDeviceManagerFuzzer::KeyInfo::KeyInfo(const int* key_codes, |
| size_t num_of_key_codes, |
| base::TimeDelta delay) { |
| DCHECK_GT(num_of_key_codes, 0); |
| key_codes_.assign(key_codes, key_codes + num_of_key_codes); |
| minimum_delay_ = delay; |
| maximum_delay_ = delay; |
| } |
| |
| InputDeviceManagerFuzzer::KeyInfo::KeyInfo(const int* key_codes, |
| size_t num_of_key_codes, |
| base::TimeDelta minimum_delay, |
| base::TimeDelta maximum_delay) { |
| DCHECK_GT(num_of_key_codes, 0); |
| DCHECK(minimum_delay <= maximum_delay); |
| key_codes_.assign(key_codes, key_codes + num_of_key_codes); |
| minimum_delay_ = minimum_delay; |
| maximum_delay_ = maximum_delay; |
| } |
| |
| InputDeviceManagerFuzzer::KeyInfo::KeyInfo(int key_code, |
| base::TimeDelta delay) { |
| key_codes_.push_back(key_code); |
| minimum_delay_ = delay; |
| maximum_delay_ = delay; |
| } |
| |
| InputDeviceManagerFuzzer::KeyInfo::KeyInfo(int key_code, |
| base::TimeDelta minimum_delay, |
| base::TimeDelta maximum_delay) { |
| DCHECK(minimum_delay <= maximum_delay); |
| key_codes_.push_back(key_code); |
| minimum_delay_ = minimum_delay; |
| maximum_delay_ = maximum_delay; |
| } |
| |
| int InputDeviceManagerFuzzer::KeyInfo::GetRandomKeyCode() const { |
| int index = static_cast<int>(base::RandGenerator(key_codes_.size())); |
| return key_codes_[index]; |
| } |
| |
| base::TimeDelta InputDeviceManagerFuzzer::KeyInfo::GetRandomDelay() const { |
| if (minimum_delay_ == maximum_delay_) { |
| return minimum_delay_; |
| } |
| int64 diff_in_microseconds = |
| (maximum_delay_ - minimum_delay_).InMicroseconds(); |
| diff_in_microseconds = static_cast<int64>( |
| base::RandGenerator(static_cast<uint64>(diff_in_microseconds))); |
| return minimum_delay_ + |
| base::TimeDelta::FromMicroseconds(diff_in_microseconds); |
| } |
| |
| InputDeviceManagerFuzzer::InputDeviceManagerFuzzer( |
| KeyboardEventCallback keyboard_event_callback) |
| : keyboard_event_callback_(keyboard_event_callback), |
| next_key_index_(0), |
| thread_("InputDevMgrFuzz") { |
| key_infos_.push_back(KeyInfo(kKeyCodes, arraysize(kKeyCodes), |
| base::TimeDelta::FromMilliseconds(400))); |
| // Modify the key_infos_ to use different input patterns. For example, the |
| // following pattern can be used to test play and stop of a video repeatedly. |
| // key_infos_.push_back(KeyInfo(keycode::kReturn, |
| // base::TimeDelta::FromSeconds(1))); |
| // key_infos_.push_back(KeyInfo(keycode::kEscape, |
| // base::TimeDelta::FromSeconds(1))); |
| |
| // Schedule task to send the first key event. Add an explicit delay to avoid |
| // possible conflicts with debug console. |
| thread_.Start(); |
| thread_.message_loop()->task_runner()->PostDelayedTask( |
| FROM_HERE, |
| base::Bind(&InputDeviceManagerFuzzer::OnNextEvent, |
| base::Unretained(this)), |
| base::TimeDelta::FromSeconds(5)); |
| } |
| |
| void InputDeviceManagerFuzzer::OnNextEvent() { |
| DCHECK_LT(next_key_index_, key_infos_.size()); |
| int key_code = key_infos_[next_key_index_].GetRandomKeyCode(); |
| |
| dom::KeyboardEventInit event_init; |
| event_init.set_key_code(key_code); |
| |
| keyboard_event_callback_.Run(base::Tokens::keydown(), event_init); |
| keyboard_event_callback_.Run(base::Tokens::keyup(), event_init); |
| |
| base::MessageLoop::current()->task_runner()->PostDelayedTask( |
| FROM_HERE, |
| base::Bind(&InputDeviceManagerFuzzer::OnNextEvent, |
| base::Unretained(this)), |
| key_infos_[next_key_index_].GetRandomDelay()); |
| next_key_index_ = (next_key_index_ + 1) % key_infos_.size(); |
| } |
| |
| } // namespace input |
| } // namespace cobalt |