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 |