blob: 1215128dcd3201b05ad22714ed2376e5f399816b [file] [log] [blame]
// 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/memory/scoped_ptr.h"
#include "base/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_("InputDeviceManagerFuzzer") {
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()->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);
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