15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef BASE_EVENT_RECORDER_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE_EVENT_RECORDER_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_export.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h> 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class FilePath; 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A class for recording and playing back keyboard and mouse input events. 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note - if you record events, and the playback with the windows in 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// different sizes or positions, the playback will fail. When 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// recording and playing, you should move the relevant windows 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to constant sizes and locations. 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(mbelshe) For now this is a singleton. I believe that this class 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// could be easily modified to: 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// support two simultaneous recorders 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be playing back events while already recording events. 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Why? Imagine if the product had a "record a macro" feature. 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// You might be recording globally, while recording or playing back 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a macro. I don't think two playbacks make sense. 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BASE_EXPORT EventRecorder { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the singleton EventRecorder. 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can only handle one recorder/player at a time. 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static EventRecorder* current() { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!current_) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_ = new EventRecorder(); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return current_; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Starts recording events. 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Will clobber the file if it already exists. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true on success, or false if an error occurred. 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool StartRecording(const FilePath& filename); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Stops recording. 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StopRecording(); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Is the EventRecorder currently recording. 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_recording() const { return is_recording_; } 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Plays events previously recorded. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true on success, or false if an error occurred. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool StartPlayback(const FilePath& filename); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Stops playback. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StopPlayback(); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Is the EventRecorder currently playing. 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_playing() const { return is_playing_; } 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // C-style callbacks for the EventRecorder. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Used for internal purposes only. 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LRESULT RecordWndProc(int nCode, WPARAM wParam, LPARAM lParam); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LRESULT PlaybackWndProc(int nCode, WPARAM wParam, LPARAM lParam); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a new EventRecorder. Events are saved to the file filename. 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the file already exists, it will be deleted before recording 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // starts. 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EventRecorder() 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : is_recording_(false), 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_playing_(false), 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) journal_hook_(NULL), 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_(NULL), 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) playback_first_msg_time_(0), 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) playback_start_time_(0) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&playback_msg_, 0, sizeof(playback_msg_)); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~EventRecorder(); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static EventRecorder* current_; // Our singleton. 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_recording_; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_playing_; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HHOOK journal_hook_; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE* file_; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVENTMSG playback_msg_; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int playback_first_msg_time_; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int playback_start_time_; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(EventRecorder); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // BASE_EVENT_RECORDER_H_ 110