| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/event_recorder.h" | 5 #include "base/event_recorder.h" |
| 6 | 6 |
| 7 #include <mmsystem.h> | 7 #include <mmsystem.h> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/time.h" | 10 #include "base/time.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 if (is_recording_ || is_playing_) | 46 if (is_recording_ || is_playing_) |
| 47 return false; | 47 return false; |
| 48 | 48 |
| 49 // Open the recording file. | 49 // Open the recording file. |
| 50 DCHECK(file_ == NULL); | 50 DCHECK(file_ == NULL); |
| 51 if (_wfopen_s(&file_, filename.c_str(), L"wb+") != 0) { | 51 if (_wfopen_s(&file_, filename.c_str(), L"wb+") != 0) { |
| 52 DLOG(ERROR) << "EventRecorder could not open log file"; | 52 DLOG(ERROR) << "EventRecorder could not open log file"; |
| 53 return false; | 53 return false; |
| 54 } | 54 } |
| 55 | 55 |
| 56 // Set the faster clock, if possible. | |
| 57 ::timeBeginPeriod(1); | |
| 58 | |
| 59 // Set the recording hook. JOURNALRECORD can only be used as a global hook. | 56 // Set the recording hook. JOURNALRECORD can only be used as a global hook. |
| 60 journal_hook_ = ::SetWindowsHookEx(WH_JOURNALRECORD, StaticRecordWndProc, | 57 journal_hook_ = ::SetWindowsHookEx(WH_JOURNALRECORD, StaticRecordWndProc, |
| 61 GetModuleHandle(NULL), 0); | 58 GetModuleHandle(NULL), 0); |
| 62 if (!journal_hook_) { | 59 if (!journal_hook_) { |
| 63 DLOG(ERROR) << "EventRecorder Record Hook failed"; | 60 DLOG(ERROR) << "EventRecorder Record Hook failed"; |
| 64 fclose(file_); | 61 fclose(file_); |
| 65 return false; | 62 return false; |
| 66 } | 63 } |
| 67 | 64 |
| 68 is_recording_ = true; | 65 is_recording_ = true; |
| 69 return true; | 66 return true; |
| 70 } | 67 } |
| 71 | 68 |
| 72 void EventRecorder::StopRecording() { | 69 void EventRecorder::StopRecording() { |
| 73 if (is_recording_) { | 70 if (is_recording_) { |
| 74 DCHECK(journal_hook_ != NULL); | 71 DCHECK(journal_hook_ != NULL); |
| 75 | 72 |
| 76 if (!::UnhookWindowsHookEx(journal_hook_)) { | 73 if (!::UnhookWindowsHookEx(journal_hook_)) { |
| 77 DLOG(ERROR) << "EventRecorder Unhook failed"; | 74 DLOG(ERROR) << "EventRecorder Unhook failed"; |
| 78 // Nothing else we can really do here. | 75 // Nothing else we can really do here. |
| 79 return; | 76 return; |
| 80 } | 77 } |
| 81 | 78 |
| 82 ::timeEndPeriod(1); | |
| 83 | |
| 84 DCHECK(file_ != NULL); | 79 DCHECK(file_ != NULL); |
| 85 fclose(file_); | 80 fclose(file_); |
| 86 file_ = NULL; | 81 file_ = NULL; |
| 87 | 82 |
| 88 journal_hook_ = NULL; | 83 journal_hook_ = NULL; |
| 89 is_recording_ = false; | 84 is_recording_ = false; |
| 90 } | 85 } |
| 91 } | 86 } |
| 92 | 87 |
| 93 bool EventRecorder::StartPlayback(std::wstring& filename) { | 88 bool EventRecorder::StartPlayback(std::wstring& filename) { |
| 94 if (journal_hook_ != NULL) | 89 if (journal_hook_ != NULL) |
| 95 return false; | 90 return false; |
| 96 if (is_recording_ || is_playing_) | 91 if (is_recording_ || is_playing_) |
| 97 return false; | 92 return false; |
| 98 | 93 |
| 99 // Open the recording file. | 94 // Open the recording file. |
| 100 DCHECK(file_ == NULL); | 95 DCHECK(file_ == NULL); |
| 101 if (_wfopen_s(&file_, filename.c_str(), L"rb") != 0) { | 96 if (_wfopen_s(&file_, filename.c_str(), L"rb") != 0) { |
| 102 DLOG(ERROR) << "EventRecorder Playback could not open log file"; | 97 DLOG(ERROR) << "EventRecorder Playback could not open log file"; |
| 103 return false; | 98 return false; |
| 104 } | 99 } |
| 105 // Read the first event from the record. | 100 // Read the first event from the record. |
| 106 if (fread(&playback_msg_, sizeof(EVENTMSG), 1, file_) != 1) { | 101 if (fread(&playback_msg_, sizeof(EVENTMSG), 1, file_) != 1) { |
| 107 DLOG(ERROR) << "EventRecorder Playback has no records!"; | 102 DLOG(ERROR) << "EventRecorder Playback has no records!"; |
| 108 fclose(file_); | 103 fclose(file_); |
| 109 return false; | 104 return false; |
| 110 } | 105 } |
| 111 | 106 |
| 112 // Set the faster clock, if possible. | |
| 113 ::timeBeginPeriod(1); | |
| 114 | |
| 115 // Playback time is tricky. When playing back, we read a series of events, | 107 // Playback time is tricky. When playing back, we read a series of events, |
| 116 // each with timeouts. Simply subtracting the delta between two timers will | 108 // each with timeouts. Simply subtracting the delta between two timers will |
| 117 // lead to fast playback (about 2x speed). The API has two events, one | 109 // lead to fast playback (about 2x speed). The API has two events, one |
| 118 // which advances to the next event (HC_SKIP), and another that requests the | 110 // which advances to the next event (HC_SKIP), and another that requests the |
| 119 // event (HC_GETNEXT). The same event will be requested multiple times. | 111 // event (HC_GETNEXT). The same event will be requested multiple times. |
| 120 // Each time the event is requested, we must calculate the new delay. | 112 // Each time the event is requested, we must calculate the new delay. |
| 121 // To do this, we track the start time of the playback, and constantly | 113 // To do this, we track the start time of the playback, and constantly |
| 122 // re-compute the delay. I mention this only because I saw two examples | 114 // re-compute the delay. I mention this only because I saw two examples |
| 123 // of how to use this code on the net, and both were broken :-) | 115 // of how to use this code on the net, and both were broken :-) |
| 124 playback_start_time_ = timeGetTime(); | 116 playback_start_time_ = timeGetTime(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 143 | 135 |
| 144 if (!::UnhookWindowsHookEx(journal_hook_)) { | 136 if (!::UnhookWindowsHookEx(journal_hook_)) { |
| 145 DLOG(ERROR) << "EventRecorder Unhook failed"; | 137 DLOG(ERROR) << "EventRecorder Unhook failed"; |
| 146 // Nothing else we can really do here. | 138 // Nothing else we can really do here. |
| 147 } | 139 } |
| 148 | 140 |
| 149 DCHECK(file_ != NULL); | 141 DCHECK(file_ != NULL); |
| 150 fclose(file_); | 142 fclose(file_); |
| 151 file_ = NULL; | 143 file_ = NULL; |
| 152 | 144 |
| 153 ::timeEndPeriod(1); | |
| 154 | |
| 155 journal_hook_ = NULL; | 145 journal_hook_ = NULL; |
| 156 is_playing_ = false; | 146 is_playing_ = false; |
| 157 } | 147 } |
| 158 } | 148 } |
| 159 | 149 |
| 160 // Windows callback hook for the recorder. | 150 // Windows callback hook for the recorder. |
| 161 LRESULT EventRecorder::RecordWndProc(int nCode, WPARAM wParam, LPARAM lParam) { | 151 LRESULT EventRecorder::RecordWndProc(int nCode, WPARAM wParam, LPARAM lParam) { |
| 162 static bool recording_enabled = true; | 152 static bool recording_enabled = true; |
| 163 EVENTMSG *msg_ptr = NULL; | 153 EVENTMSG *msg_ptr = NULL; |
| 164 | 154 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 248 // PeekMessage processing. | 238 // PeekMessage processing. |
| 249 case HC_NOREMOVE: | 239 case HC_NOREMOVE: |
| 250 break; | 240 break; |
| 251 } | 241 } |
| 252 | 242 |
| 253 return CallNextHookEx(journal_hook_, nCode, wParam, lParam); | 243 return CallNextHookEx(journal_hook_, nCode, wParam, lParam); |
| 254 } | 244 } |
| 255 | 245 |
| 256 } // namespace base | 246 } // namespace base |
| 257 | 247 |
| OLD | NEW |