| /* |
| * Copyright 2015 Google Inc. 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.h" |
| #include "base/rand_util.h" |
| #include "cobalt/base/tokens.h" |
| #include "cobalt/dom/keycode.h" |
| |
| namespace cobalt { |
| namespace input { |
| |
| using base::TimeDelta; |
| using dom::KeyboardEvent; |
| |
| 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]; |
| } |
| |
| 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_ + TimeDelta::FromMicroseconds(diff_in_microseconds); |
| } |
| |
| InputDeviceManagerFuzzer::InputDeviceManagerFuzzer( |
| KeyboardEventCallback keyboard_event_callback) |
| : keyboard_event_callback_(keyboard_event_callback), |
| next_key_index_(0), |
| thread_("InputDeviceManagerFuzzer") { |
| key_infos_.push_back(KeyInfo(kKeyCodes, arraysize(kKeyCodes), |
| 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, |
| // TimeDelta::FromSeconds(1))); |
| // key_infos_.push_back(KeyInfo(keycode::kEscape, |
| // 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()->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(); |
| |
| KeyboardEvent::Data key_down_event( |
| KeyboardEvent::kTypeKeyDown, KeyboardEvent::kDomKeyLocationStandard, |
| KeyboardEvent::kNoModifier, key_code, 0, false); |
| |
| keyboard_event_callback_.Run(key_down_event); |
| |
| KeyboardEvent::Data key_up_event( |
| KeyboardEvent::kTypeKeyUp, KeyboardEvent::kDomKeyLocationStandard, |
| KeyboardEvent::kNoModifier, key_code, 0, false); |
| |
| keyboard_event_callback_.Run(key_up_event); |
| |
| MessageLoop::current()->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 |