michael@0: // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #ifndef BASE_EVENT_RECORDER_H_ michael@0: #define BASE_EVENT_RECORDER_H_ michael@0: michael@0: #include michael@0: #if defined(OS_WIN) michael@0: #include michael@0: #endif michael@0: #include "base/basictypes.h" michael@0: michael@0: class FilePath; michael@0: michael@0: namespace base { michael@0: michael@0: // A class for recording and playing back keyboard and mouse input events. michael@0: // michael@0: // Note - if you record events, and the playback with the windows in michael@0: // different sizes or positions, the playback will fail. When michael@0: // recording and playing, you should move the relevant windows michael@0: // to constant sizes and locations. michael@0: // TODO(mbelshe) For now this is a singleton. I believe that this class michael@0: // could be easily modified to: michael@0: // support two simultaneous recorders michael@0: // be playing back events while already recording events. michael@0: // Why? Imagine if the product had a "record a macro" feature. michael@0: // You might be recording globally, while recording or playing back michael@0: // a macro. I don't think two playbacks make sense. michael@0: class EventRecorder { michael@0: public: michael@0: // Get the singleton EventRecorder. michael@0: // We can only handle one recorder/player at a time. michael@0: static EventRecorder* current() { michael@0: if (!current_) michael@0: current_ = new EventRecorder(); michael@0: return current_; michael@0: } michael@0: michael@0: // Starts recording events. michael@0: // Will clobber the file if it already exists. michael@0: // Returns true on success, or false if an error occurred. michael@0: bool StartRecording(const FilePath& filename); michael@0: michael@0: // Stops recording. michael@0: void StopRecording(); michael@0: michael@0: // Is the EventRecorder currently recording. michael@0: bool is_recording() const { return is_recording_; } michael@0: michael@0: // Plays events previously recorded. michael@0: // Returns true on success, or false if an error occurred. michael@0: bool StartPlayback(const FilePath& filename); michael@0: michael@0: // Stops playback. michael@0: void StopPlayback(); michael@0: michael@0: // Is the EventRecorder currently playing. michael@0: bool is_playing() const { return is_playing_; } michael@0: michael@0: #if defined(OS_WIN) michael@0: // C-style callbacks for the EventRecorder. michael@0: // Used for internal purposes only. michael@0: LRESULT RecordWndProc(int nCode, WPARAM wParam, LPARAM lParam); michael@0: LRESULT PlaybackWndProc(int nCode, WPARAM wParam, LPARAM lParam); michael@0: #endif michael@0: michael@0: private: michael@0: // Create a new EventRecorder. Events are saved to the file filename. michael@0: // If the file already exists, it will be deleted before recording michael@0: // starts. michael@0: explicit EventRecorder() michael@0: : is_recording_(false), michael@0: is_playing_(false), michael@0: #if defined(OS_WIN) michael@0: journal_hook_(NULL), michael@0: file_(NULL), michael@0: #endif michael@0: playback_first_msg_time_(0), michael@0: playback_start_time_(0) { michael@0: } michael@0: ~EventRecorder(); michael@0: michael@0: static EventRecorder* current_; // Our singleton. michael@0: michael@0: bool is_recording_; michael@0: bool is_playing_; michael@0: #if defined(OS_WIN) michael@0: HHOOK journal_hook_; michael@0: FILE* file_; michael@0: EVENTMSG playback_msg_; michael@0: #endif michael@0: int playback_first_msg_time_; michael@0: int playback_start_time_; michael@0: michael@0: DISALLOW_EVIL_CONSTRUCTORS(EventRecorder); michael@0: }; michael@0: michael@0: } // namespace base michael@0: michael@0: #endif // BASE_EVENT_RECORDER_H_