Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/cpp/iedriver/ActionSimulators/JavaScriptActionSimulator.cpp
2868 views
1
// Licensed to the Software Freedom Conservancy (SFC) under one
2
// or more contributor license agreements. See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership. The SFC licenses this file
5
// to you under the Apache License, Version 2.0 (the "License");
6
// you may not use this file except in compliance with the License.
7
// You may obtain a copy of the License at
8
//
9
// http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing, software
12
// distributed under the License is distributed on an "AS IS" BASIS,
13
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
// See the License for the specific language governing permissions and
15
// limitations under the License.
16
17
#include "JavaScriptActionSimulator.h"
18
19
#include "errorcodes.h"
20
#include "logging.h"
21
22
#include "../DocumentHost.h"
23
#include "../Generated/atoms.h"
24
#include "../Script.h"
25
26
#define WAIT_TIME_IN_MILLISECONDS_PER_INPUT_EVENT 100
27
28
namespace webdriver {
29
30
31
JavaScriptActionSimulator::JavaScriptActionSimulator() {
32
CComVariant keyboard_state;
33
keyboard_state.vt = VT_NULL;
34
this->keyboard_state_ = keyboard_state;
35
36
CComVariant mouse_state;
37
mouse_state.vt = VT_NULL;
38
this->mouse_state_ = mouse_state;
39
}
40
41
JavaScriptActionSimulator::~JavaScriptActionSimulator() {
42
}
43
44
int JavaScriptActionSimulator::SimulateActions(BrowserHandle browser_wrapper,
45
std::vector<INPUT> inputs,
46
InputState* input_state) {
47
LOG(TRACE) << "Entering JavaScriptActionSimulator::SimulateActions";
48
for (size_t i = 0; i < inputs.size(); ++i) {
49
INPUT current_input = inputs[i];
50
this->UpdateInputState(current_input, input_state);
51
if (current_input.type == INPUT_MOUSE) {
52
if (current_input.mi.dwFlags & MOUSEEVENTF_MOVE) {
53
this->SimulatePointerMove(browser_wrapper, current_input);
54
} else if (current_input.mi.dwFlags & MOUSEEVENTF_LEFTDOWN) {
55
this->SimulatePointerDown(browser_wrapper, current_input);
56
} else if (current_input.mi.dwFlags & MOUSEEVENTF_LEFTUP) {
57
this->SimulatePointerUp(browser_wrapper, current_input);
58
} else if (current_input.mi.dwFlags & MOUSEEVENTF_RIGHTDOWN) {
59
this->SimulatePointerDown(browser_wrapper, current_input);
60
} else if (current_input.mi.dwFlags & MOUSEEVENTF_RIGHTUP) {
61
this->SimulatePointerUp(browser_wrapper, current_input);
62
}
63
} else if (current_input.type == INPUT_KEYBOARD) {
64
this->SimulateKeyDown(browser_wrapper, current_input);
65
} else if (current_input.type == INPUT_HARDWARE) {
66
::Sleep(current_input.hi.uMsg);
67
}
68
}
69
return WD_SUCCESS;
70
}
71
72
int JavaScriptActionSimulator::SimulateKeyDown(BrowserHandle browser_wrapper,
73
INPUT input) {
74
KeyboardExtraInfo* extra_info = reinterpret_cast<KeyboardExtraInfo*>(input.ki.dwExtraInfo);
75
std::wstring key = extra_info->character;
76
delete extra_info;
77
LOG(DEBUG) << "Using synthetic events for sending keys";
78
std::wstring script_source = L"(function() { return function(){" +
79
atoms::asString(atoms::INPUTS_BIN) +
80
L"; return webdriver.atoms.inputs.sendKeys(" +
81
L"arguments[0], arguments[1], arguments[2], arguments[3]);" +
82
L"};})();";
83
CComPtr<IHTMLDocument2> doc;
84
browser_wrapper->GetDocument(&doc);
85
Script script_wrapper(doc, script_source, 4);
86
87
script_wrapper.AddNullArgument();
88
script_wrapper.AddArgument(key);
89
script_wrapper.AddArgument(this->keyboard_state_);
90
script_wrapper.AddArgument(true);
91
int status_code = script_wrapper.Execute();
92
if (status_code == WD_SUCCESS) {
93
this->keyboard_state_ = script_wrapper.result();
94
} else {
95
LOG(WARN) << "Unable to execute js to send keystrokes";
96
}
97
return status_code;
98
}
99
100
int JavaScriptActionSimulator::SimulatePointerMove(BrowserHandle browser_wrapper,
101
INPUT input) {
102
LOG(DEBUG) << "Using synthetic events for mouse move";
103
MouseExtraInfo* extra_info = reinterpret_cast<MouseExtraInfo*>(input.mi.dwExtraInfo);
104
int x_offset = extra_info->offset_x;
105
int y_offset = extra_info->offset_y;
106
bool is_offset_specified = extra_info->offset_specified;
107
CComPtr<IHTMLElement> target_element = extra_info->element;
108
delete extra_info;
109
110
std::wstring script_source = L"(function() { return function(){" +
111
atoms::asString(atoms::INPUTS_BIN) +
112
L"; return webdriver.atoms.inputs.mouseMove(arguments[0], arguments[1], arguments[2], arguments[3]);" +
113
L"};})();";
114
115
CComPtr<IHTMLDocument2> doc;
116
browser_wrapper->GetDocument(&doc);
117
Script script_wrapper(doc, script_source, 4);
118
119
if (target_element != NULL) {
120
script_wrapper.AddArgument(target_element);
121
} else {
122
script_wrapper.AddNullArgument();
123
}
124
125
if (is_offset_specified) {
126
script_wrapper.AddArgument(x_offset);
127
script_wrapper.AddArgument(y_offset);
128
} else {
129
script_wrapper.AddNullArgument();
130
script_wrapper.AddNullArgument();
131
}
132
133
script_wrapper.AddArgument(this->mouse_state_);
134
int status_code = script_wrapper.Execute();
135
if (status_code == WD_SUCCESS) {
136
this->mouse_state_ = script_wrapper.result();
137
} else {
138
LOG(WARN) << "Unable to execute js to mouse move";
139
}
140
return status_code;
141
}
142
143
int JavaScriptActionSimulator::SimulatePointerDown(BrowserHandle browser_wrapper,
144
INPUT input) {
145
LOG(DEBUG) << "Using synthetic events for mouse button down";
146
std::wstring script_source = L"(function() { return function(){" +
147
atoms::asString(atoms::INPUTS_BIN) +
148
L"; return webdriver.atoms.inputs.mouseButtonDown(arguments[0]);" +
149
L"};})();";
150
151
CComPtr<IHTMLDocument2> doc;
152
browser_wrapper->GetDocument(&doc);
153
Script script_wrapper(doc, script_source, 1);
154
script_wrapper.AddArgument(this->mouse_state_);
155
int status_code = script_wrapper.Execute();
156
if (status_code == WD_SUCCESS) {
157
this->mouse_state_ = script_wrapper.result();
158
} else {
159
LOG(WARN) << "Unable to execute js to perform mouse button down";
160
return status_code;
161
}
162
return status_code;
163
}
164
165
int JavaScriptActionSimulator::SimulatePointerUp(BrowserHandle browser_wrapper,
166
INPUT input) {
167
LOG(DEBUG) << "Using synthetic events for mouse button up";
168
std::wstring script_source = L"(function() { return function(){" +
169
atoms::asString(atoms::INPUTS_BIN) +
170
L"; return webdriver.atoms.inputs.mouseButtonUp(arguments[0]);" +
171
L"};})();";
172
173
CComPtr<IHTMLDocument2> doc;
174
browser_wrapper->GetDocument(&doc);
175
Script script_wrapper(doc, script_source, 1);
176
script_wrapper.AddArgument(this->mouse_state_);
177
int status_code = script_wrapper.Execute();
178
if (status_code == WD_SUCCESS) {
179
this->mouse_state_ = script_wrapper.result();
180
} else {
181
LOG(WARN) << "Unable to execute js to perform mouse button up";
182
return status_code;
183
}
184
return status_code;
185
}
186
187
int JavaScriptActionSimulator::SimulatePause(BrowserHandle browser_wrapper,
188
INPUT input) {
189
::Sleep(input.hi.uMsg);
190
return WD_SUCCESS;
191
}
192
193
} // namespace webdriver
194
195