| Index: base/event_recorder_win.cc
 | 
| diff --git a/base/event_recorder_win.cc b/base/event_recorder_win.cc
 | 
| deleted file mode 100644
 | 
| index b3076a11318c57744c7256e71987d6688d468d9c..0000000000000000000000000000000000000000
 | 
| --- a/base/event_recorder_win.cc
 | 
| +++ /dev/null
 | 
| @@ -1,258 +0,0 @@
 | 
| -// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 | 
| -// Use of this source code is governed by a BSD-style license that can be
 | 
| -// found in the LICENSE file.
 | 
| -
 | 
| -#include <stddef.h>
 | 
| -#include <windows.h>
 | 
| -#include <mmsystem.h>
 | 
| -
 | 
| -#include "base/event_recorder.h"
 | 
| -#include "base/files/file_util.h"
 | 
| -#include "base/logging.h"
 | 
| -
 | 
| -// A note about time.
 | 
| -// For perfect playback of events, you'd like a very accurate timer
 | 
| -// so that events are played back at exactly the same time that
 | 
| -// they were recorded.  However, windows has a clock which is only
 | 
| -// granular to ~15ms.  We see more consistent event playback when
 | 
| -// using a higher resolution timer.  To do this, we use the
 | 
| -// timeGetTime API instead of the default GetTickCount() API.
 | 
| -
 | 
| -namespace base {
 | 
| -
 | 
| -EventRecorder* EventRecorder::current_ = NULL;
 | 
| -
 | 
| -LRESULT CALLBACK StaticRecordWndProc(int nCode, WPARAM wParam,
 | 
| -                                     LPARAM lParam) {
 | 
| -  DCHECK(EventRecorder::current());
 | 
| -  return EventRecorder::current()->RecordWndProc(nCode, wParam, lParam);
 | 
| -}
 | 
| -
 | 
| -LRESULT CALLBACK StaticPlaybackWndProc(int nCode, WPARAM wParam,
 | 
| -                                       LPARAM lParam) {
 | 
| -  DCHECK(EventRecorder::current());
 | 
| -  return EventRecorder::current()->PlaybackWndProc(nCode, wParam, lParam);
 | 
| -}
 | 
| -
 | 
| -EventRecorder::~EventRecorder() {
 | 
| -  // Try to assert early if the caller deletes the recorder
 | 
| -  // while it is still in use.
 | 
| -  DCHECK(!journal_hook_);
 | 
| -  DCHECK(!is_recording_ && !is_playing_);
 | 
| -}
 | 
| -
 | 
| -bool EventRecorder::StartRecording(const FilePath& filename) {
 | 
| -  if (journal_hook_ != NULL)
 | 
| -    return false;
 | 
| -  if (is_recording_ || is_playing_)
 | 
| -    return false;
 | 
| -
 | 
| -  // Open the recording file.
 | 
| -  DCHECK(!file_);
 | 
| -  file_ = OpenFile(filename, "wb+");
 | 
| -  if (!file_) {
 | 
| -    DLOG(ERROR) << "EventRecorder could not open log file";
 | 
| -    return false;
 | 
| -  }
 | 
| -
 | 
| -  // Set the faster clock, if possible.
 | 
| -  ::timeBeginPeriod(1);
 | 
| -
 | 
| -  // Set the recording hook.  JOURNALRECORD can only be used as a global hook.
 | 
| -  journal_hook_ = ::SetWindowsHookEx(WH_JOURNALRECORD, StaticRecordWndProc,
 | 
| -                                     GetModuleHandle(NULL), 0);
 | 
| -  if (!journal_hook_) {
 | 
| -    DLOG(ERROR) << "EventRecorder Record Hook failed";
 | 
| -    CloseFile(file_);
 | 
| -    return false;
 | 
| -  }
 | 
| -
 | 
| -  is_recording_ = true;
 | 
| -  return true;
 | 
| -}
 | 
| -
 | 
| -void EventRecorder::StopRecording() {
 | 
| -  if (is_recording_) {
 | 
| -    DCHECK(journal_hook_ != NULL);
 | 
| -
 | 
| -    if (!::UnhookWindowsHookEx(journal_hook_)) {
 | 
| -      DLOG(ERROR) << "EventRecorder Unhook failed";
 | 
| -      // Nothing else we can really do here.
 | 
| -      return;
 | 
| -    }
 | 
| -
 | 
| -    ::timeEndPeriod(1);
 | 
| -
 | 
| -    DCHECK(file_ != NULL);
 | 
| -    CloseFile(file_);
 | 
| -    file_ = NULL;
 | 
| -
 | 
| -    journal_hook_ = NULL;
 | 
| -    is_recording_ = false;
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -bool EventRecorder::StartPlayback(const FilePath& filename) {
 | 
| -  if (journal_hook_ != NULL)
 | 
| -    return false;
 | 
| -  if (is_recording_ || is_playing_)
 | 
| -    return false;
 | 
| -
 | 
| -  // Open the recording file.
 | 
| -  DCHECK(!file_);
 | 
| -  file_ = OpenFile(filename, "rb");
 | 
| -  if (!file_) {
 | 
| -    DLOG(ERROR) << "EventRecorder Playback could not open log file";
 | 
| -    return false;
 | 
| -  }
 | 
| -  // Read the first event from the record.
 | 
| -  if (fread(&playback_msg_, sizeof(EVENTMSG), 1, file_) != 1) {
 | 
| -    DLOG(ERROR) << "EventRecorder Playback has no records!";
 | 
| -    CloseFile(file_);
 | 
| -    return false;
 | 
| -  }
 | 
| -
 | 
| -  // Set the faster clock, if possible.
 | 
| -  ::timeBeginPeriod(1);
 | 
| -
 | 
| -  // Playback time is tricky.  When playing back, we read a series of events,
 | 
| -  // each with timeouts.  Simply subtracting the delta between two timers will
 | 
| -  // lead to fast playback (about 2x speed).  The API has two events, one
 | 
| -  // which advances to the next event (HC_SKIP), and another that requests the
 | 
| -  // event (HC_GETNEXT).  The same event will be requested multiple times.
 | 
| -  // Each time the event is requested, we must calculate the new delay.
 | 
| -  // To do this, we track the start time of the playback, and constantly
 | 
| -  // re-compute the delay.   I mention this only because I saw two examples
 | 
| -  // of how to use this code on the net, and both were broken :-)
 | 
| -  playback_start_time_ = timeGetTime();
 | 
| -  playback_first_msg_time_ = playback_msg_.time;
 | 
| -
 | 
| -  // Set the hook.  JOURNALPLAYBACK can only be used as a global hook.
 | 
| -  journal_hook_ = ::SetWindowsHookEx(WH_JOURNALPLAYBACK, StaticPlaybackWndProc,
 | 
| -                                     GetModuleHandle(NULL), 0);
 | 
| -  if (!journal_hook_) {
 | 
| -    DLOG(ERROR) << "EventRecorder Playback Hook failed";
 | 
| -    return false;
 | 
| -  }
 | 
| -
 | 
| -  is_playing_ = true;
 | 
| -
 | 
| -  return true;
 | 
| -}
 | 
| -
 | 
| -void EventRecorder::StopPlayback() {
 | 
| -  if (is_playing_) {
 | 
| -    DCHECK(journal_hook_ != NULL);
 | 
| -
 | 
| -    if (!::UnhookWindowsHookEx(journal_hook_)) {
 | 
| -      DLOG(ERROR) << "EventRecorder Unhook failed";
 | 
| -      // Nothing else we can really do here.
 | 
| -    }
 | 
| -
 | 
| -    DCHECK(file_ != NULL);
 | 
| -    CloseFile(file_);
 | 
| -    file_ = NULL;
 | 
| -
 | 
| -    ::timeEndPeriod(1);
 | 
| -
 | 
| -    journal_hook_ = NULL;
 | 
| -    is_playing_ = false;
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -// Windows callback hook for the recorder.
 | 
| -LRESULT EventRecorder::RecordWndProc(int nCode, WPARAM wParam, LPARAM lParam) {
 | 
| -  static bool recording_enabled = true;
 | 
| -  EVENTMSG* msg_ptr = NULL;
 | 
| -
 | 
| -  // The API says we have to do this.
 | 
| -  // See http://msdn2.microsoft.com/en-us/library/ms644983(VS.85).aspx
 | 
| -  if (nCode < 0)
 | 
| -    return ::CallNextHookEx(journal_hook_, nCode, wParam, lParam);
 | 
| -
 | 
| -  // Check for the break key being pressed and stop recording.
 | 
| -  if (::GetKeyState(VK_CANCEL) & 0x8000) {
 | 
| -    StopRecording();
 | 
| -    return ::CallNextHookEx(journal_hook_, nCode, wParam, lParam);
 | 
| -  }
 | 
| -
 | 
| -  // The Journal Recorder must stop recording events when system modal
 | 
| -  // dialogs are present. (see msdn link above)
 | 
| -  switch (nCode) {
 | 
| -    case HC_SYSMODALON:
 | 
| -      recording_enabled = false;
 | 
| -      break;
 | 
| -    case HC_SYSMODALOFF:
 | 
| -      recording_enabled = true;
 | 
| -      break;
 | 
| -  }
 | 
| -
 | 
| -  if (nCode == HC_ACTION && recording_enabled) {
 | 
| -    // Aha - we have an event to record.
 | 
| -    msg_ptr = reinterpret_cast<EVENTMSG*>(lParam);
 | 
| -    msg_ptr->time = timeGetTime();
 | 
| -    fwrite(msg_ptr, sizeof(EVENTMSG), 1, file_);
 | 
| -    fflush(file_);
 | 
| -  }
 | 
| -
 | 
| -  return CallNextHookEx(journal_hook_, nCode, wParam, lParam);
 | 
| -}
 | 
| -
 | 
| -// Windows callback for the playback mode.
 | 
| -LRESULT EventRecorder::PlaybackWndProc(int nCode, WPARAM wParam,
 | 
| -                                       LPARAM lParam) {
 | 
| -  static bool playback_enabled = true;
 | 
| -  int delay = 0;
 | 
| -
 | 
| -  switch (nCode) {
 | 
| -    // A system modal dialog box is being displayed.  Stop playing back
 | 
| -    // messages.
 | 
| -    case HC_SYSMODALON:
 | 
| -      playback_enabled = false;
 | 
| -      break;
 | 
| -
 | 
| -    // A system modal dialog box is destroyed.  We can start playing back
 | 
| -    // messages again.
 | 
| -    case HC_SYSMODALOFF:
 | 
| -      playback_enabled = true;
 | 
| -      break;
 | 
| -
 | 
| -    // Prepare to copy the next mouse or keyboard event to playback.
 | 
| -    case HC_SKIP:
 | 
| -      if (!playback_enabled)
 | 
| -        break;
 | 
| -
 | 
| -      // Read the next event from the record.
 | 
| -      if (fread(&playback_msg_, sizeof(EVENTMSG), 1, file_) != 1)
 | 
| -        this->StopPlayback();
 | 
| -      break;
 | 
| -
 | 
| -    // Copy the mouse or keyboard event to the EVENTMSG structure in lParam.
 | 
| -    case HC_GETNEXT:
 | 
| -      if (!playback_enabled)
 | 
| -        break;
 | 
| -
 | 
| -      memcpy(reinterpret_cast<void*>(lParam), &playback_msg_,
 | 
| -             sizeof(playback_msg_));
 | 
| -
 | 
| -      // The return value is the amount of time (in milliseconds) to wait
 | 
| -      // before playing back the next message in the playback queue.  Each
 | 
| -      // time this is called, we recalculate the delay relative to our current
 | 
| -      // wall clock.
 | 
| -      delay = (playback_msg_.time - playback_first_msg_time_) -
 | 
| -              (timeGetTime() - playback_start_time_);
 | 
| -      if (delay < 0)
 | 
| -        delay = 0;
 | 
| -      return delay;
 | 
| -
 | 
| -    // An application has called PeekMessage with wRemoveMsg set to PM_NOREMOVE
 | 
| -    // indicating that the message is not removed from the message queue after
 | 
| -    // PeekMessage processing.
 | 
| -    case HC_NOREMOVE:
 | 
| -      break;
 | 
| -  }
 | 
| -
 | 
| -  return CallNextHookEx(journal_hook_, nCode, wParam, lParam);
 | 
| -}
 | 
| -
 | 
| -}  // namespace base
 | 
| 
 |