selenium-webdriver 0.0.24 → 0.0.25

Sign up to get free protection for your applications and to get access to all the features.
Files changed (207) hide show
  1. data/{common/src/rb/CHANGES → CHANGES} +13 -0
  2. data/{common/src/rb/README → README} +1 -1
  3. data/{common/src/rb/lib → lib}/selenium-webdriver.rb +0 -0
  4. data/{common/src/rb/lib → lib}/selenium/webdriver.rb +2 -1
  5. data/{common/src/rb/lib → lib}/selenium/webdriver/bridge_helper.rb +0 -0
  6. data/{common/src/rb/lib → lib}/selenium/webdriver/child_process.rb +0 -0
  7. data/{chrome/src/rb/lib → lib}/selenium/webdriver/chrome.rb +0 -0
  8. data/{chrome/src/rb/lib → lib}/selenium/webdriver/chrome/bridge.rb +2 -2
  9. data/{chrome/src/rb/lib → lib}/selenium/webdriver/chrome/command_executor.rb +0 -0
  10. data/lib/selenium/webdriver/chrome/extension.zip +0 -0
  11. data/{chrome/src/rb/lib → lib}/selenium/webdriver/chrome/launcher.rb +26 -20
  12. data/{common/src/rb/lib → lib}/selenium/webdriver/core_ext/dir.rb +0 -0
  13. data/{common/src/rb/lib → lib}/selenium/webdriver/core_ext/string.rb +0 -0
  14. data/{common/src/rb/lib → lib}/selenium/webdriver/driver.rb +0 -0
  15. data/{common/src/rb/lib → lib}/selenium/webdriver/driver_extensions/takes_screenshot.rb +0 -0
  16. data/{common/src/rb/lib → lib}/selenium/webdriver/element.rb +0 -0
  17. data/{common/src/rb/lib → lib}/selenium/webdriver/error.rb +0 -0
  18. data/{common/src/rb/lib → lib}/selenium/webdriver/file_reaper.rb +2 -1
  19. data/{common/src/rb/lib → lib}/selenium/webdriver/find.rb +0 -0
  20. data/{firefox/src/rb/lib → lib}/selenium/webdriver/firefox.rb +2 -1
  21. data/{firefox/src/rb/lib → lib}/selenium/webdriver/firefox/binary.rb +32 -6
  22. data/{firefox/src/rb/lib → lib}/selenium/webdriver/firefox/bridge.rb +0 -0
  23. data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
  24. data/{firefox/src/rb/lib → lib}/selenium/webdriver/firefox/launcher.rb +0 -0
  25. data/lib/selenium/webdriver/firefox/native/linux/amd64/x_ignore_nofocus.so +0 -0
  26. data/lib/selenium/webdriver/firefox/native/linux/x86/x_ignore_nofocus.so +0 -0
  27. data/{firefox/src/rb/lib → lib}/selenium/webdriver/firefox/profile.rb +37 -72
  28. data/{firefox/src/rb/lib → lib}/selenium/webdriver/firefox/profiles_ini.rb +0 -0
  29. data/{firefox/src/rb/lib → lib}/selenium/webdriver/firefox/util.rb +0 -0
  30. data/{jobbie/src/rb/lib → lib}/selenium/webdriver/ie.rb +2 -2
  31. data/{jobbie/src/rb/lib → lib}/selenium/webdriver/ie/bridge.rb +7 -2
  32. data/{jobbie/src/rb/lib → lib}/selenium/webdriver/ie/lib.rb +0 -0
  33. data/{jobbie/prebuilt/Win32/Release → lib/selenium/webdriver/ie/native/win32}/InternetExplorerDriver.dll +0 -0
  34. data/lib/selenium/webdriver/ie/native/x64/InternetExplorerDriver.dll +0 -0
  35. data/{jobbie/src/rb/lib → lib}/selenium/webdriver/ie/util.rb +0 -0
  36. data/{common/src/rb/lib → lib}/selenium/webdriver/keys.rb +0 -0
  37. data/{common/src/rb/lib → lib}/selenium/webdriver/navigation.rb +0 -0
  38. data/{common/src/rb/lib → lib}/selenium/webdriver/options.rb +0 -0
  39. data/{common/src/rb/lib → lib}/selenium/webdriver/platform.rb +5 -1
  40. data/{remote/client/src/rb/lib → lib}/selenium/webdriver/remote.rb +0 -0
  41. data/{remote/client/src/rb/lib → lib}/selenium/webdriver/remote/bridge.rb +0 -0
  42. data/{remote/client/src/rb/lib → lib}/selenium/webdriver/remote/capabilities.rb +0 -0
  43. data/{remote/client/src/rb/lib → lib}/selenium/webdriver/remote/commands.rb +0 -0
  44. data/{remote/client/src/rb/lib → lib}/selenium/webdriver/remote/http/common.rb +0 -0
  45. data/{remote/client/src/rb/lib → lib}/selenium/webdriver/remote/http/curb.rb +0 -0
  46. data/{remote/client/src/rb/lib → lib}/selenium/webdriver/remote/http/default.rb +5 -1
  47. data/{remote/client/src/rb/lib → lib}/selenium/webdriver/remote/response.rb +0 -0
  48. data/{remote/client/src/rb/lib → lib}/selenium/webdriver/remote/server_error.rb +0 -0
  49. data/{common/src/rb/lib → lib}/selenium/webdriver/target_locator.rb +0 -0
  50. data/{common/src/rb/lib → lib}/selenium/webdriver/timeouts.rb +0 -0
  51. data/lib/selenium/webdriver/zip_helper.rb +30 -0
  52. metadata +73 -214
  53. data/COPYING +0 -204
  54. data/chrome/prebuilt/Win32/Release/npchromedriver.dll +0 -0
  55. data/chrome/prebuilt/x64/Release/npchromedriver.dll +0 -0
  56. data/chrome/src/extension/background.html +0 -9
  57. data/chrome/src/extension/background.js +0 -1029
  58. data/chrome/src/extension/content_script.js +0 -1488
  59. data/chrome/src/extension/icons/busy.png +0 -0
  60. data/chrome/src/extension/icons/free.png +0 -0
  61. data/chrome/src/extension/manifest-nonwin.json +0 -19
  62. data/chrome/src/extension/manifest-win.json +0 -20
  63. data/chrome/src/extension/utils.js +0 -231
  64. data/common/src/js/abstractcommandprocessor.js +0 -132
  65. data/common/src/js/asserts.js +0 -296
  66. data/common/src/js/by.js +0 -149
  67. data/common/src/js/command.js +0 -380
  68. data/common/src/js/core/Blank.html +0 -7
  69. data/common/src/js/core/InjectedRemoteRunner.html +0 -8
  70. data/common/src/js/core/RemoteRunner.html +0 -101
  71. data/common/src/js/core/SeleniumLog.html +0 -109
  72. data/common/src/js/core/TestPrompt.html +0 -145
  73. data/common/src/js/core/TestRunner-splash.html +0 -55
  74. data/common/src/js/core/TestRunner.html +0 -165
  75. data/common/src/js/core/icons/all.png +0 -0
  76. data/common/src/js/core/icons/continue.png +0 -0
  77. data/common/src/js/core/icons/continue_disabled.png +0 -0
  78. data/common/src/js/core/icons/pause.png +0 -0
  79. data/common/src/js/core/icons/pause_disabled.png +0 -0
  80. data/common/src/js/core/icons/selected.png +0 -0
  81. data/common/src/js/core/icons/step.png +0 -0
  82. data/common/src/js/core/icons/step_disabled.png +0 -0
  83. data/common/src/js/core/lib/cssQuery/cssQuery-p.js +0 -6
  84. data/common/src/js/core/lib/cssQuery/src/cssQuery-level2.js +0 -142
  85. data/common/src/js/core/lib/cssQuery/src/cssQuery-level3.js +0 -150
  86. data/common/src/js/core/lib/cssQuery/src/cssQuery-standard.js +0 -53
  87. data/common/src/js/core/lib/cssQuery/src/cssQuery.js +0 -356
  88. data/common/src/js/core/lib/prototype.js +0 -2006
  89. data/common/src/js/core/lib/scriptaculous/builder.js +0 -101
  90. data/common/src/js/core/lib/scriptaculous/controls.js +0 -815
  91. data/common/src/js/core/lib/scriptaculous/dragdrop.js +0 -915
  92. data/common/src/js/core/lib/scriptaculous/effects.js +0 -958
  93. data/common/src/js/core/lib/scriptaculous/scriptaculous.js +0 -47
  94. data/common/src/js/core/lib/scriptaculous/slider.js +0 -283
  95. data/common/src/js/core/lib/scriptaculous/unittest.js +0 -383
  96. data/common/src/js/core/lib/snapsie.js +0 -91
  97. data/common/src/js/core/scripts/find_matching_child.js +0 -69
  98. data/common/src/js/core/scripts/htmlutils.js +0 -8716
  99. data/common/src/js/core/scripts/injection.html +0 -72
  100. data/common/src/js/core/scripts/selenium-api.js +0 -3291
  101. data/common/src/js/core/scripts/selenium-browserbot.js +0 -2457
  102. data/common/src/js/core/scripts/selenium-browserdetect.js +0 -153
  103. data/common/src/js/core/scripts/selenium-commandhandlers.js +0 -379
  104. data/common/src/js/core/scripts/selenium-executionloop.js +0 -175
  105. data/common/src/js/core/scripts/selenium-logging.js +0 -148
  106. data/common/src/js/core/scripts/selenium-remoterunner.js +0 -695
  107. data/common/src/js/core/scripts/selenium-testrunner.js +0 -1362
  108. data/common/src/js/core/scripts/selenium-version.js +0 -5
  109. data/common/src/js/core/scripts/ui-doc.html +0 -808
  110. data/common/src/js/core/scripts/ui-element.js +0 -1644
  111. data/common/src/js/core/scripts/ui-map-sample.js +0 -979
  112. data/common/src/js/core/scripts/user-extensions.js +0 -3
  113. data/common/src/js/core/scripts/user-extensions.js.sample +0 -75
  114. data/common/src/js/core/scripts/xmlextras.js +0 -153
  115. data/common/src/js/core/selenium-logo.png +0 -0
  116. data/common/src/js/core/selenium-test.css +0 -43
  117. data/common/src/js/core/selenium.css +0 -316
  118. data/common/src/js/core/xpath/dom.js +0 -566
  119. data/common/src/js/core/xpath/javascript-xpath-0.1.11.js +0 -2816
  120. data/common/src/js/core/xpath/util.js +0 -549
  121. data/common/src/js/core/xpath/xmltoken.js +0 -149
  122. data/common/src/js/core/xpath/xpath.js +0 -2481
  123. data/common/src/js/extension/README +0 -2
  124. data/common/src/js/extension/dommessenger.js +0 -152
  125. data/common/src/js/factory.js +0 -55
  126. data/common/src/js/future.js +0 -141
  127. data/common/src/js/jsunit.js +0 -40
  128. data/common/src/js/jsunit/app/css/jsUnitStyle.css +0 -50
  129. data/common/src/js/jsunit/app/css/readme +0 -10
  130. data/common/src/js/jsunit/app/emptyPage.html +0 -11
  131. data/common/src/js/jsunit/app/jsUnitCore.js +0 -534
  132. data/common/src/js/jsunit/app/jsUnitMockTimeout.js +0 -81
  133. data/common/src/js/jsunit/app/jsUnitTestManager.js +0 -705
  134. data/common/src/js/jsunit/app/jsUnitTestSuite.js +0 -44
  135. data/common/src/js/jsunit/app/jsUnitTracer.js +0 -102
  136. data/common/src/js/jsunit/app/jsUnitVersionCheck.js +0 -59
  137. data/common/src/js/jsunit/app/main-counts-errors.html +0 -12
  138. data/common/src/js/jsunit/app/main-counts-failures.html +0 -13
  139. data/common/src/js/jsunit/app/main-counts-runs.html +0 -13
  140. data/common/src/js/jsunit/app/main-counts.html +0 -21
  141. data/common/src/js/jsunit/app/main-data.html +0 -178
  142. data/common/src/js/jsunit/app/main-errors.html +0 -23
  143. data/common/src/js/jsunit/app/main-frame.html +0 -19
  144. data/common/src/js/jsunit/app/main-loader.html +0 -45
  145. data/common/src/js/jsunit/app/main-progress.html +0 -25
  146. data/common/src/js/jsunit/app/main-results.html +0 -67
  147. data/common/src/js/jsunit/app/main-status.html +0 -13
  148. data/common/src/js/jsunit/app/testContainer.html +0 -16
  149. data/common/src/js/jsunit/app/testContainerController.html +0 -77
  150. data/common/src/js/jsunit/app/xbDebug.js +0 -306
  151. data/common/src/js/jsunit/changelog.txt +0 -60
  152. data/common/src/js/jsunit/css/jsUnitStyle.css +0 -83
  153. data/common/src/js/jsunit/images/green.gif +0 -0
  154. data/common/src/js/jsunit/images/logo_jsunit.gif +0 -0
  155. data/common/src/js/jsunit/images/powerby-transparent.gif +0 -0
  156. data/common/src/js/jsunit/images/red.gif +0 -0
  157. data/common/src/js/jsunit/licenses/JDOM_license.txt +0 -56
  158. data/common/src/js/jsunit/licenses/Jetty_license.html +0 -213
  159. data/common/src/js/jsunit/licenses/MPL-1.1.txt +0 -470
  160. data/common/src/js/jsunit/licenses/gpl-2.txt +0 -340
  161. data/common/src/js/jsunit/licenses/index.html +0 -141
  162. data/common/src/js/jsunit/licenses/lgpl-2.1.txt +0 -504
  163. data/common/src/js/jsunit/licenses/mpl-tri-license-c.txt +0 -35
  164. data/common/src/js/jsunit/licenses/mpl-tri-license-html.txt +0 -35
  165. data/common/src/js/jsunit/readme.txt +0 -19
  166. data/common/src/js/jsunit/testRunner.html +0 -167
  167. data/common/src/js/jsunit/version.txt +0 -1
  168. data/common/src/js/key.js +0 -117
  169. data/common/src/js/localcommandprocessor.js +0 -171
  170. data/common/src/js/testcase.js +0 -219
  171. data/common/src/js/timing.js +0 -89
  172. data/common/src/js/webdriver.js +0 -860
  173. data/common/src/js/webelement.js +0 -483
  174. data/firefox/prebuilt/Win32/Release/webdriver-firefox.dll +0 -0
  175. data/firefox/prebuilt/amd64/libnoblur64.so +0 -0
  176. data/firefox/prebuilt/i386/libnoblur.so +0 -0
  177. data/firefox/prebuilt/linux/Release/libwebdriver-firefox.so +0 -0
  178. data/firefox/prebuilt/linux64/Release/libwebdriver-firefox.so +0 -0
  179. data/firefox/prebuilt/nsICommandProcessor.xpt +0 -0
  180. data/firefox/prebuilt/nsINativeEvents.xpt +0 -0
  181. data/firefox/prebuilt/nsIResponseHandler.xpt +0 -0
  182. data/firefox/src/extension/chrome.manifest +0 -3
  183. data/firefox/src/extension/components/badCertListener.js +0 -295
  184. data/firefox/src/extension/components/dispatcher.js +0 -495
  185. data/firefox/src/extension/components/driver-component.js +0 -130
  186. data/firefox/src/extension/components/errorcode.js +0 -70
  187. data/firefox/src/extension/components/firefoxDriver.js +0 -831
  188. data/firefox/src/extension/components/json2.js +0 -273
  189. data/firefox/src/extension/components/keytest.html +0 -554
  190. data/firefox/src/extension/components/nsCommandProcessor.js +0 -684
  191. data/firefox/src/extension/components/promptService.js +0 -208
  192. data/firefox/src/extension/components/request.js +0 -219
  193. data/firefox/src/extension/components/response.js +0 -276
  194. data/firefox/src/extension/components/screenshooter.js +0 -81
  195. data/firefox/src/extension/components/session.js +0 -314
  196. data/firefox/src/extension/components/sessionstore.js +0 -226
  197. data/firefox/src/extension/components/socketListener.js +0 -435
  198. data/firefox/src/extension/components/utils.js +0 -1335
  199. data/firefox/src/extension/components/webLoadingListener.js +0 -57
  200. data/firefox/src/extension/components/webdriverserver.js +0 -110
  201. data/firefox/src/extension/components/wrappedElement.js +0 -706
  202. data/firefox/src/extension/content/fxdriver.xul +0 -30
  203. data/firefox/src/extension/content/server.js +0 -95
  204. data/firefox/src/extension/idl/nsICommandProcessor.idl +0 -38
  205. data/firefox/src/extension/idl/nsIResponseHandler.idl +0 -34
  206. data/firefox/src/extension/install.rdf +0 -29
  207. data/jobbie/prebuilt/x64/Release/InternetExplorerDriver.dll +0 -0
@@ -1,435 +0,0 @@
1
- /*
2
- Copyright 2007-2009 WebDriver committers
3
- Copyright 2007-2009 Google Inc.
4
- Portions copyright 2007 ThoughtWorks, Inc
5
-
6
- Licensed under the Apache License, Version 2.0 (the "License");
7
- you may not use this file except in compliance with the License.
8
- You may obtain a copy of the License at
9
-
10
- http://www.apache.org/licenses/LICENSE-2.0
11
-
12
- Unless required by applicable law or agreed to in writing, software
13
- distributed under the License is distributed on an "AS IS" BASIS,
14
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- See the License for the specific language governing permissions and
16
- limitations under the License.
17
- */
18
-
19
- /**
20
- * @fileoverview Defines a class that reads commands from a socket and
21
- * dispatches them to the nsICommandProcessor. When the response is ready, it is
22
- * serialized and sent back to the client through the socket.
23
- */
24
-
25
-
26
- /**
27
- * Communicates with a client by reading and writing from a socket.
28
- * @param {Dispatcher} dispatcher The instance to send all parsed requests to.
29
- * @param {nsISocketTransport} transport The connected socket transport.
30
- * @constructor
31
- * @extends {nsIStreamListener}
32
- */
33
- function SocketListener(dispatcher, transport) {
34
-
35
- /**
36
- * The instance to send all parsed requests to.
37
- * @type {Dispatcher}
38
- * @private
39
- */
40
- this.dispatcher_ = dispatcher;
41
-
42
- /**
43
- * Transport for the socket this instance will read/write to.
44
- * @type {nsISocketTransport}
45
- * @private
46
- */
47
- this.transport_ = transport;
48
-
49
- /**
50
- * Output stream for the socket transport.
51
- * @type {nsIOutputStream}
52
- * @private
53
- */
54
- this.outputStream_ = transport.openOutputStream(
55
- Components.interfaces.nsITransport.OPEN_BLOCKING,
56
- /*segmentSize=*/0,
57
- /*segmentCount=*/0);
58
-
59
- var socketInputStream = transport.openInputStream(
60
- /*flags=*/0,
61
- /*segmentSize=*/0,
62
- /*segmentCount=*/0).QueryInterface(Components.interfaces.nsIAsyncInputStream);
63
-
64
- /**
65
- * The converter used when writing data back to the socket.
66
- * @type {nsIScriptableUnicodeConverter}
67
- * @private
68
- */
69
- this.converter_ = Components.
70
- classes['@mozilla.org/intl/scriptableunicodeconverter'].
71
- createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
72
-
73
- this.converter_.charset = SocketListener.CHARSET;
74
-
75
- /**
76
- * The HTTP request method.
77
- * @type {?Request.Method}
78
- * @private
79
- */
80
- this.method_ = null;
81
-
82
- /**
83
- * The HTTP request headers as a JSON object.
84
- * @type {object}
85
- * @private
86
- */
87
- this.headers_ = {};
88
- this.requestUrl_ = '';
89
- this.body_ = '';
90
- this.contentLengthRemaining_ = 0;
91
-
92
- /**
93
- * The raw UTF-8 request data that has been read so far.
94
- * @type {string}
95
- * @private
96
- */
97
- this.rawData_ = '';
98
-
99
- var threadManager = Components.classes['@mozilla.org/thread-manager;1'].
100
- getService(Components.interfaces.nsIThreadManager);
101
-
102
- /**
103
- * A reference to the main thread.
104
- * @type {nsIThread}
105
- * @private
106
- * @const
107
- */
108
- this.mainThread_ = threadManager.mainThread;
109
-
110
- socketInputStream.asyncWait(this, 0, 0, this.mainThread_);
111
- }
112
-
113
-
114
- /**
115
- * Enumeration of states for a SocketListener.
116
- * @enum {number}
117
- */
118
- SocketListener.State = {
119
- READING_REQUEST_LINE: 0,
120
- READING_HEADERS: 1,
121
- READING_BODY: 2,
122
- FINISHED: 3
123
- };
124
-
125
-
126
- /**
127
- * Charset used for socket I/O.
128
- * @type {string}
129
- * @const
130
- */
131
- SocketListener.CHARSET = 'UTF-8';
132
-
133
-
134
- /**
135
- * HTTP message sent in response to requests with an Expect:100-continue header.
136
- * @type {string}
137
- * @const
138
- */
139
- SocketListener.CONTINUE_MESSAGE = 'HTTP/1.1 100 Continue\r\n\r\n';
140
-
141
-
142
- /**
143
- * This instance's current state.
144
- * @type {SocketListener.State}
145
- * @private
146
- */
147
- SocketListener.prototype.state_ = SocketListener.State.READING_REQUEST_LINE;
148
-
149
-
150
- /**
151
- * Whether this instance has sent a 100-continue resposne to the client.
152
- * @type {boolean}
153
- * @private
154
- */
155
- SocketListener.prototype.continueSent_ = false;
156
-
157
-
158
- /**
159
- * Called when the underlying input stream has additional data ready to be read.
160
- * @param {nsIAsyncInputStream} inputStream The stream with data ready.
161
- * @see {nsIInputStreamCallback#onInputStreamReady}
162
- */
163
- SocketListener.prototype.onInputStreamReady = function(inputStream) {
164
- var binaryInputStream = Components.
165
- classes['@mozilla.org/binaryinputstream;1'].
166
- createInstance(Components.interfaces.nsIBinaryInputStream);
167
- binaryInputStream.setInputStream(inputStream);
168
-
169
- // Utils.dumpn('onInputStreamReady');
170
- var available;
171
- try {
172
- available = inputStream.available();
173
- } catch (ex) {
174
- // TODO: check for ex.result == Components.results.NS_BASE_STREAM_CLOSED?
175
- this.transport_.close(0);
176
- return;
177
- }
178
-
179
- var byteArray = binaryInputStream.readByteArray(available);
180
- var converted = this.converter_.convertFromByteArray(byteArray, available);
181
- this.rawData_ += converted;
182
-
183
- // Utils.dumpn('...converted:\n' + converted.replace(/\r\n/g, '\\r\\n\n'));
184
- // Utils.dumpn('...raw data:\n' + this.rawData_);
185
-
186
- try {
187
- switch (this.state_) {
188
- case SocketListener.State.READING_REQUEST_LINE:
189
- this.readRequestLine_();
190
- if (this.state_ != SocketListener.State.READING_HEADERS) {
191
- break;
192
- }
193
- // Read the request line, fall through to start reading headers.
194
-
195
- case SocketListener.State.READING_HEADERS:
196
- this.readHeaders_();
197
- if (this.state_ != SocketListener.State.READING_BODY) {
198
- break;
199
- }
200
- // Read all of the headers, fall through to start reading the body.
201
-
202
- case SocketListener.State.READING_BODY:
203
- this.readBody_();
204
- break;
205
- }
206
-
207
- if (this.state_ != SocketListener.State.FINISHED) {
208
- // Utils.dumpn('Waiting for more data...');
209
- inputStream.asyncWait(this, 0, 0, this.mainThread_);
210
- } else {
211
- inputStream.close();
212
- var clientRequest = new Request(
213
- this.method_, this.requestUrl_, this.headers_, this.rawData_);
214
- var clientResponse = new Response(
215
- clientRequest, this.outputStream_);
216
- // Utils.dumpn('Dispatching request:\n' + clientRequest.toDebugString());
217
- this.dispatcher_.dispatch(clientRequest, clientResponse);
218
- }
219
- } catch (ex) {
220
- // Utils.dumpn('Sending error:\n\t' + ex.toString());
221
- var status = ex.isBadRequest ? ex.status : Response.INTERNAL_ERROR;
222
- var response = new Response(null, this.outputStream_);
223
- response.sendError(status, ex.toString(), 'text/plain');
224
- this.transport_.close(0);
225
- }
226
- };
227
-
228
-
229
- /**
230
- * Reads a CRLF terminated line from the data that has been read from the socket
231
- * thus far.
232
- * @return {?string} The read line, minus the terminating CRLF, or null if none
233
- * are yet available.
234
- */
235
- SocketListener.prototype.readLine_ = function() {
236
- while (true) {
237
- var crlf = this.rawData_.search('\r\n');
238
- if (crlf == -1) {
239
- return null; // Haven't read a full line yet.
240
- }
241
-
242
- // Strip out the line from the request data.
243
- var line = this.rawData_.substring(0, crlf).
244
- replace(/^[\s\xa0]+|[\s\xa0]+$/g, '');
245
- this.rawData_ = this.rawData_.substring(crlf + '\r\n'.length);
246
-
247
- return line;
248
- }
249
- };
250
-
251
-
252
- /**
253
- * Attempt to parse the HTTP request line with the data that has been read from
254
- * the socket thus far.
255
- * @private
256
- */
257
- SocketListener.prototype.readRequestLine_ = function() {
258
- // Utils.dumpn('Reading request line...');
259
- // Read the first non-blank line in the request. We skip blank lines
260
- // according to RFC 2616, section 4.1.
261
- var line = this.readLine_();
262
- while (line != null && line.length == 0) {
263
- line = this.readLine();
264
- }
265
-
266
- if (null == line) {
267
- return; // Don't have a line to parse yet.
268
- }
269
-
270
- var parts = line.split(/\s+/);
271
- if (parts.length < 3) {
272
- throw new SocketListener.BadRequest('Invalid request line.');
273
- }
274
-
275
- this.method_ = parts.shift().toUpperCase();
276
- this.path_ = parts.shift();
277
- this.protocol_ = parts.shift().toUpperCase();
278
-
279
- // We only support HTTP/1.1 requests.
280
- if (this.protocol_ != 'HTTP/1.1') {
281
- throw new SocketListener.BadRequest(
282
- 'Not an HTTP/1.1 request: <' + this.protocol_ + '>');
283
- }
284
-
285
- // Make sure we were given a valid HTTP method.
286
- if (typeof Request.Method[this.method_] == 'undefined') {
287
- throw new SocketListener.BadRequest(
288
- 'Invalid HTTP method: <' + this.method_ + '>');
289
- }
290
- // Utils.dumpn('\t' + this.method_ + ' ' + this.path_ + ' ' + this.protocol_);
291
- this.state_ = SocketListener.State.READING_HEADERS;
292
- };
293
-
294
-
295
- /**
296
- * Read headers from the data that has been read from the socket.
297
- * @private
298
- */
299
- SocketListener.prototype.readHeaders_ = function() {
300
- // Utils.dumpn('Reading headers...');
301
- while (true) {
302
- var line = this.readLine_(false);
303
- if (null == line) {
304
- return; // No headers available yet.
305
- }
306
-
307
- if (!line.length) {
308
- // Blank line, end of headers.
309
-
310
- // Make sure the host was specified.
311
- if (typeof this.headers_['host'] == 'undefined') {
312
- throw new SocketListener.BadRequest('No "Host" header specified');
313
- }
314
-
315
- // Check the content-length.
316
- if (typeof this.headers_['content-length'] == 'undefined') {
317
- if (this.method_ == Request.Method.POST ||
318
- this.method_ == Request.Method.PUT) {
319
- throw new SocketListener.BadRequest(
320
- 'No "Content-Length" header specified for POST or PUT request',
321
- '411 Length Required');
322
- }
323
- } else {
324
- var contentLength = parseInt(this.headers_['content-length']);
325
- if (isNaN(contentLength)) {
326
- throw new SocketListener.BadRequest(
327
- 'Content-Length header is not a number: ' +
328
- this.headers_['content-length']);
329
- }
330
- this.headers_['content-length'] = contentLength;
331
- }
332
-
333
- // Reconstitute the original request URL.
334
- this.requestUrl_ = 'http://' + this.headers_['host'] + this.path_;
335
- try {
336
- this.requestUrl_ = Components.
337
- classes["@mozilla.org/network/io-service;1"].
338
- getService(Components.interfaces.nsIIOService).
339
- newURI(this.requestUrl_, null, null).
340
- QueryInterface(Components.interfaces.nsIURL);
341
- } catch (ex) {
342
- throw new SocketListener.BadRequest(
343
- 'Error parsing request URL: ' + this.requestUrl_);
344
- }
345
-
346
- this.state_ = SocketListener.State.READING_BODY;
347
- return;
348
- }
349
-
350
- var parts = line.match(/([^:\s]*)\s*:\s*([^\s].*)/);
351
- if (!parts) {
352
- throw new SocketListener.BadRequest(
353
- 'Error parsing header field <' + line + '>');
354
- }
355
- this.headers_[parts[1].toLowerCase()] = parts[2];
356
- // Utils.dumpn('\t' + parts[1] + ':' + parts[2]);
357
- }
358
- };
359
-
360
-
361
- /**
362
- * Read the request body from the data that has been read thus far.
363
- * @private
364
- */
365
- SocketListener.prototype.readBody_ = function() {
366
- // Utils.dumpn('Reading body...');
367
- if (!this.continueSent_) {
368
- // Need to send a 100 Continue if it is expected.
369
- // For more info, see RFC 2616, section 8.2.3
370
- if (this.headers_['expect'] == '100-continue') {
371
- // Utils.dumpn('Sending 100-continue...');
372
- this.continueSent_ = true;
373
- var continueResp = new Response(null, this.outputStream_);
374
- continueResp.setStatus(Response.CONTINUE);
375
- continueResp.commit();
376
- }
377
- }
378
-
379
- if (this.method_ != Request.Method.POST &&
380
- this.method_ != Request.Method.PUT) {
381
- // No body to read. Technically, if the client sends a body (as indicated
382
- // by the Content-Length header, we should read it in, even if it's ignored
383
- // for the request method. But this can lead to indefinite blocking with
384
- // clients that specify a Content-Length on a GET request and then never
385
- // send the body.
386
- this.state_ = SocketListener.State.FINISHED;
387
- return;
388
- }
389
-
390
- // This rigmarole is needed so we know the number of bytes read so we can tell
391
- // if we've read the entire body.
392
- var escaped = encodeURIComponent(this.rawData_);
393
- var escapedCharCount = 0;
394
- if (escaped.indexOf('%', 0) != -1) {
395
- escapedCharCount = escaped.split('%').length - 1;
396
- }
397
- var bytesRead = escaped.length - (2 * escapedCharCount);
398
- var bytesRemaining = this.headers_['content-length'] - bytesRead;
399
-
400
- // If we read more data than the Content-Length header specified, then too
401
- // much data was sent by the client, and we consider this a malformed
402
- // request.
403
- if (bytesRemaining < 0) {
404
- throw new SocketListener.BadRequest(
405
- 'Request body is longer than indicated "Content-Length" header;' +
406
- ' expected <' + this.headers_['content-length'] +'>, ' +
407
- ' but was <' + bytesRead + '>');
408
- } else if (bytesRemaining == 0) {
409
- // Utils.dumpn('Finished reading body!');
410
- this.state_ = SocketListener.State.FINISHED;
411
- // } else {
412
- // Utils.dumpn(
413
- // 'Read ' + bytesRead + '; ' + bytesRemaining + ' bytes remaining');
414
- }
415
- };
416
-
417
-
418
- /**
419
- * Thrown when a bad request is parsed.
420
- * @param {string} message The error message to return to the client.
421
- * @param {number} opt_status The HTTP status code to use when returning the
422
- * error to the client. Defaults to 400.
423
- * @constructor
424
- */
425
- SocketListener.BadRequest = function(message, opt_status) {
426
- this.message = message;
427
- this.status = opt_status || Response.BAD_REQUEST;
428
- this.isBadRequest = true;
429
- };
430
-
431
-
432
- /** @override */
433
- SocketListener.BadRequest.prototype.toString = function() {
434
- return this.message;
435
- };
@@ -1,1335 +0,0 @@
1
- /*
2
- Copyright 2007-2009 WebDriver committers
3
- Copyright 2007-2009 Google Inc.
4
- Portions copyright 2007 ThoughtWorks, Inc
5
-
6
- Licensed under the Apache License, Version 2.0 (the "License");
7
- you may not use this file except in compliance with the License.
8
- You may obtain a copy of the License at
9
-
10
- http://www.apache.org/licenses/LICENSE-2.0
11
-
12
- Unless required by applicable law or agreed to in writing, software
13
- distributed under the License is distributed on an "AS IS" BASIS,
14
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- See the License for the specific language governing permissions and
16
- limitations under the License.
17
- */
18
-
19
-
20
- /**
21
- * A WebDriver error.
22
- * @param {!number} code The error code.
23
- * @param {!string|Error} messageOrError The error message, or another Error to
24
- * propagate.
25
- * @constructor
26
- */
27
- function WebDriverError(code, messageOrError) {
28
-
29
- var message;
30
- var stack;
31
- if (messageOrError instanceof Error) {
32
- message = messageOrError.message;
33
- stack = messageOrError.stack;
34
- } else {
35
- message = messageOrError.toString();
36
- stack = Error(message).stack.split('\n');
37
- stack.shift();
38
- stack = stack.join('\n');
39
- }
40
-
41
- /**
42
- * This error's status code.
43
- * @type {!number}
44
- */
45
- this.code = code;
46
-
47
- /**
48
- * This error's message.
49
- * @type {string}
50
- */
51
- this.message = message;
52
-
53
- /**
54
- * Captures a stack trace for when this error was thrown.
55
- * @type {string}
56
- */
57
- this.stack = stack;
58
-
59
- /**
60
- * Used to identify this class since instanceof will not work across
61
- * component boundaries.
62
- * @type {!boolean}
63
- */
64
- this.isWebDriverError = true;
65
- }
66
-
67
-
68
- function createSwitchFile(file_content) {
69
- var filename = "/tmp/switch_window_started";
70
- var cc = Components.classes;
71
- var ci = Components.interfaces;
72
-
73
- try {
74
- // TODO(eran): Look at the OS and only do this where it makes sense.
75
- var tmpdir = cc['@mozilla.org/file/local;1'].createInstance(ci.nsILocalFile);
76
- tmpdir.initWithPath("/tmp");
77
-
78
- // Do not create a switch file on systems that do not have a /tmp directory
79
- // - this serves to prevent creation of a switch file on Windows systems.
80
- if (!tmpdir.exists()) {
81
- return;
82
- }
83
-
84
- var file = cc['@mozilla.org/file/local;1'].createInstance(ci.nsILocalFile);
85
- file.initWithPath(filename);
86
- var fileOutputStream = cc['@mozilla.org/network/safe-file-output-stream;1'].createInstance(ci.nsIFileOutputStream);
87
- fileOutputStream.init(file, -1, -1, null);
88
-
89
- fileOutputStream.write(file_content, file_content.length);
90
- if (fileOutputStream instanceof ci.nsISafeOutputStream) {
91
- fileOutputStream.finish();
92
- } else {
93
- fileOutputStream.close();
94
- }
95
- } catch (e) {
96
- // Fine. Log it and continue
97
- Utils.dumpn(e);
98
- }
99
- }
100
-
101
- function Utils() {
102
- }
103
-
104
-
105
- Utils.getUniqueId = function() {
106
- if (!Utils._generator) {
107
- Utils._generator =
108
- Utils.getService("@mozilla.org/uuid-generator;1", "nsIUUIDGenerator");
109
- }
110
- return Utils._generator.generateUUID().toString();
111
- };
112
-
113
-
114
- Utils.newInstance = function(className, interfaceName) {
115
- var clazz = Components.classes[className];
116
-
117
- if (!clazz)
118
- return undefined;
119
-
120
- var iface = Components.interfaces[interfaceName];
121
- return clazz.createInstance(iface);
122
- };
123
-
124
-
125
- Utils.getService = function(className, serviceName) {
126
- var clazz = Components.classes[className];
127
- if (clazz == undefined) {
128
- throw new Exception();
129
- }
130
-
131
- return clazz.getService(Components.interfaces[serviceName]);
132
- };
133
-
134
-
135
- Utils.getServer = function() {
136
- var handle =
137
- Utils.newInstance("@googlecode.com/webdriver/fxdriver;1", "nsISupports");
138
- return handle.wrappedJSObject;
139
- };
140
-
141
-
142
- Utils.getActiveElement = function(doc) {
143
-
144
- var element;
145
- if (doc["activeElement"]) {
146
- element = doc.activeElement;
147
- } else {
148
- var topWindow = doc.defaultView.top;
149
- var commandDispatcher = topWindow.getBrowser().ownerDocument.
150
- commandDispatcher;
151
-
152
- element = commandDispatcher.focusedElement;
153
-
154
- if (element && doc != element.ownerDocument)
155
- element = null;
156
- }
157
-
158
- // Default to the body
159
- if (!element) {
160
- element = doc.body;
161
- }
162
-
163
- return element;
164
- };
165
-
166
-
167
- function getTextFromNode(node, toReturn, textSoFar) {
168
- if (node['tagName'] && node.tagName == "SCRIPT") {
169
- return [toReturn, textSoFar];
170
- }
171
- var children = node.childNodes;
172
-
173
- var bits;
174
- for (var i = 0; i < children.length; i++) {
175
- var child = children[i];
176
-
177
- // Do we need to collapse the text so far?
178
- if (child["tagName"] && child.tagName == "PRE") {
179
- toReturn += collapseWhitespace(textSoFar);
180
- textSoFar = "";
181
- bits = getTextFromNode(child, toReturn, "", true);
182
- toReturn += bits[1];
183
- continue;
184
- }
185
-
186
- // Or is this just plain text?
187
- if (child.nodeName == "#text") {
188
- if (Utils.isDisplayed(child, false)) {
189
- var textToAdd = child.nodeValue;
190
- textToAdd =
191
- textToAdd.replace(new RegExp(String.fromCharCode(160), "gm"), " ");
192
- textSoFar += textToAdd;
193
- }
194
- continue;
195
- }
196
-
197
- // Treat as another child node.
198
- bits = getTextFromNode(child, toReturn, textSoFar, false);
199
- toReturn = bits[0];
200
- textSoFar = bits[1];
201
- }
202
-
203
- if (isBlockLevel(node)) {
204
- if (node["tagName"] && node.tagName != "PRE") {
205
- toReturn += collapseWhitespace(textSoFar) + "\n";
206
- textSoFar = "";
207
- } else {
208
- toReturn += "\n";
209
- }
210
- }
211
- return [toReturn, textSoFar];
212
- }
213
-
214
-
215
- function isBlockLevel(node) {
216
- if (node["tagName"] && node.tagName == "BR")
217
- return true;
218
-
219
- try {
220
- // Should we think about getting hold of the current document?
221
- return "block" == Utils.getStyleProperty(node, "display");
222
- } catch (e) {
223
- return false;
224
- }
225
- }
226
-
227
-
228
- Utils.isInHead = function(element) {
229
- while (element) {
230
- if (element.tagName && element.tagName.toLowerCase() == "head") {
231
- return true;
232
- }
233
- try {
234
- element = element.parentNode;
235
- } catch (e) {
236
- // Fine. the DOM has dispeared from underneath us
237
- return false;
238
- }
239
- }
240
-
241
- return false;
242
- };
243
-
244
-
245
- /**
246
- * Checks that the element is not hidden by dimensions or CSS
247
- */
248
- Utils.isDisplayed = function(element, scrollIfNecessary) {
249
- // Ensure that we're dealing with an element.
250
- var el = element;
251
- while (el.nodeType != 1 && !(el.nodeType >= 9 && el.nodeType <= 11)) {
252
- el = el.parentNode;
253
- }
254
-
255
- if (!el) {
256
- return false;
257
- }
258
-
259
- // Hidden input elements are, by definition, never displayed
260
- if (el.tagName == "input" && el.type == "hidden") {
261
- return false;
262
- }
263
-
264
- var box = scrollIfNecessary ? Utils.getLocationOnceScrolledIntoView(el) : Utils.getLocation(el);
265
- // Elements with zero width or height are never displayed
266
- if (box.width == 0 || box.height == 0) {
267
- return false;
268
- }
269
-
270
- var visibility = Utils.getStyleProperty(el, "visibility");
271
-
272
- var _isDisplayed = function(e) {
273
- var display = e.ownerDocument.defaultView.getComputedStyle(e, null).
274
- getPropertyValue("display");
275
- if (display == "none") return display;
276
- if (e && e.parentNode && e.parentNode.style) {
277
- return _isDisplayed(e.parentNode);
278
- }
279
- return undefined;
280
- };
281
-
282
- var displayed = _isDisplayed(el);
283
-
284
- return displayed != "none" && visibility != "hidden";
285
- };
286
-
287
-
288
- /**
289
- * Gets the computed style of a DOM {@code element}. If the computed style is
290
- * inherited from the element's parent, the parent will be queried for its
291
- * style value. If the style value is an RGB color string, it will be converted
292
- * to hex ("#rrggbb").
293
- * @param {Element} element The DOM element whose computed style to retrieve.
294
- * @param {string} propertyName The name of the CSS style proeprty to get.
295
- * @return {string} The computed style as a string.
296
- */
297
- Utils.getStyleProperty = function(element, propertyName) {
298
- if (!element) {
299
- return undefined;
300
- }
301
-
302
- var value = element.ownerDocument.defaultView.getComputedStyle(element, null).
303
- getPropertyValue(propertyName);
304
-
305
- if ('inherit' == value && element.parentNode.style) {
306
- value = Utils.getStyleProperty(element.parentNode, propertyName);
307
- }
308
-
309
- // Convert colours to hex if possible
310
- var raw = /rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)/.exec(value);
311
- if (raw) {
312
- var hex = (Number(raw[1]) << 16) +
313
- (Number(raw[2]) << 8) +
314
- (Number(raw[3]));
315
- hex = (hex & 0x00ffffff) | 0x1000000;
316
- value = '#' + hex.toString(16).substring(1);
317
- }
318
-
319
- return value;
320
- };
321
-
322
-
323
- function collapseWhitespace(textSoFar) {
324
- return textSoFar.replace(/\s+/g, " ");
325
- }
326
-
327
-
328
- function getPreformattedText(node) {
329
- var textToAdd = "";
330
- return getTextFromNode(node, "", textToAdd, true)[1];
331
- }
332
-
333
-
334
- function isWhiteSpace(character) {
335
- return character == '\n' || character == ' ' || character == '\t' || character
336
- == '\r';
337
- }
338
-
339
-
340
- Utils.getText = function(element) {
341
- var bits = getTextFromNode(element, "", "", element.tagName == "PRE");
342
- var text = bits[0] + collapseWhitespace(bits[1]);
343
- var start = 0;
344
- while (start < text.length && isWhiteSpace(text[start])) {
345
- ++start;
346
- }
347
- var end = text.length;
348
- while (end > start && isWhiteSpace(text[end - 1])) {
349
- --end;
350
- }
351
- return text.slice(start, end);
352
- };
353
-
354
-
355
- Utils.addToKnownElements = function(element, doc) {
356
- if (!doc.fxdriver_elements) {
357
- doc.fxdriver_elements = {};
358
- }
359
-
360
- for (var e in doc.fxdriver_elements) {
361
- if (doc.fxdriver_elements[e] == element) {
362
- return e;
363
- }
364
- }
365
-
366
- var id = Utils.getUniqueId();
367
- doc.fxdriver_elements[id] = element;
368
-
369
- return id;
370
- };
371
-
372
-
373
- Utils.getElementAt = function(index, doc) {
374
- var e = doc.fxdriver_elements ? doc.fxdriver_elements[index] : undefined;
375
- if (e) {
376
- // Is this a stale reference?
377
- var parent = e;
378
- while (parent && parent != e.ownerDocument.documentElement) {
379
- parent = parent.parentNode;
380
- }
381
-
382
- if (parent !== e.ownerDocument.documentElement) {
383
- // Remove from the cache
384
- delete doc.fxdriver_elements[index];
385
- throw new WebDriverError(ErrorCode.STALE_ELEMENT_REFERENCE,
386
- 'Element is no longer attached to the DOM');
387
- }
388
- } else {
389
- throw new WebDriverError(ErrorCode.STALE_ELEMENT_REFERENCE,
390
- 'Element not found in the cache');
391
- }
392
-
393
- return e;
394
- };
395
-
396
-
397
- Utils.platform = function(doc) {
398
- if (!this.userAgentPlatformLowercase) {
399
- var currentWindow = doc.defaultView;
400
- this.userAgentPlatformLowercase =
401
- currentWindow.navigator.platform.toLowerCase();
402
- }
403
-
404
- return this.userAgentPlatformLowercase;
405
- };
406
-
407
-
408
- Utils.shiftCount = 0;
409
-
410
-
411
- Utils.getNativeEvents = function() {
412
- try {
413
- const cid = "@openqa.org/nativeevents;1";
414
- var obj = Components.classes[cid].createInstance();
415
- return obj.QueryInterface(Components.interfaces.nsINativeEvents);
416
- } catch(e) {
417
- // Unable to retrieve native events. No biggie, because we fall back to
418
- // synthesis later
419
- return undefined;
420
- }
421
- };
422
-
423
-
424
- Utils.getNodeForNativeEvents = function(element) {
425
- try {
426
- // This stuff changes between releases.
427
- // Do as much up-front work in JS as possible
428
- var retrieval = Utils.newInstance(
429
- "@mozilla.org/accessibleRetrieval;1", "nsIAccessibleRetrieval");
430
- var accessible = retrieval.getAccessibleFor(element.ownerDocument);
431
- var accessibleDoc =
432
- accessible.QueryInterface(Components.interfaces.nsIAccessibleDocument);
433
- return accessibleDoc.QueryInterface(Components.interfaces.nsISupports);
434
- } catch(e) {
435
- // Unable to retrieve the accessible doc
436
- return undefined;
437
- }
438
- };
439
-
440
-
441
- Utils.type = function(doc, element, text, opt_useNativeEvents) {
442
-
443
- // For consistency between native and synthesized events, convert common
444
- // escape sequences to their Key enum aliases.
445
- text = text.replace(new RegExp('\b', 'g'), '\uE003'). // DOM_VK_BACK_SPACE
446
- replace(/\t/g, '\uE004'). // DOM_VK_TAB
447
- replace(/(\r\n|\n|\r)/g, '\uE006'); // DOM_VK_RETURN
448
-
449
- // Special-case file input elements. This is ugly, but should be okay
450
- if (element.tagName == "INPUT") {
451
- var inputtype = element.getAttribute("type");
452
- if (inputtype && inputtype.toLowerCase() == "file") {
453
- element.value = text;
454
- Utils.fireHtmlEvent(element, "change");
455
- return;
456
- }
457
- }
458
-
459
- var obj = Utils.getNativeEvents();
460
- var node = Utils.getNodeForNativeEvents(element);
461
- const thmgr_cls = Components.classes["@mozilla.org/thread-manager;1"];
462
-
463
- if (opt_useNativeEvents && obj && node && thmgr_cls) {
464
-
465
- // This indicates that a the page has been unloaded
466
- var pageHasBeenUnloaded = false;
467
-
468
- // This is the standard indicator that a page has been unloaded, but
469
- // due to Firefox's caching policy, will occur only when Firefox works
470
- // *without* caching at all.
471
- var unloadFunction = function() { pageHasBeenUnloaded = true; };
472
-
473
- element.ownerDocument.body.addEventListener("unload",
474
- unloadFunction, false);
475
-
476
- // This is a Firefox specific event - See:
477
- // https://developer.mozilla.org/En/Using_Firefox_1.5_caching
478
- element.ownerDocument.defaultView.addEventListener("pagehide",
479
- unloadFunction, false);
480
-
481
- // Now do the native thing.
482
- obj.sendKeys(node, text);
483
-
484
- var hasEvents = {};
485
- var threadmgr =
486
- thmgr_cls.getService(Components.interfaces.nsIThreadManager);
487
- var thread = threadmgr.currentThread;
488
-
489
- do {
490
-
491
- // This sleep is needed so that Firefox on Linux will manage to process
492
- // all of the keyboard events before returning control to the caller
493
- // code (otherwise the caller may not find all of the keystrokes it
494
- // has entered).
495
- var the_window = element.ownerDocument.defaultView;
496
-
497
- var doneNativeEventWait = false;
498
-
499
- if (the_window) {
500
- the_window.setTimeout(function() {
501
- doneNativeEventWait = true; }, 100);
502
- }
503
-
504
- // Do it as long as the timeout function has not been called and the
505
- // page has not been unloaded. If the page has been unloaded, there is no
506
- // point in waiting for other native events to be processed in this page
507
- // as they "belong" to the next page.
508
- while ((!doneNativeEventWait) && (!pageHasBeenUnloaded)) {
509
- thread.processNextEvent(true);
510
- }
511
-
512
- obj.hasUnhandledEvents(node, hasEvents);
513
-
514
- } while ((hasEvents.value == true) && (!pageHasBeenUnloaded));
515
-
516
- if (pageHasBeenUnloaded) {
517
- Utils.dumpn("Page has been reloaded while waiting for native events to "
518
- + "be processed. Remaining events? " + hasEvents.value);
519
- } else {
520
- // Remove event listeners...
521
- element.ownerDocument.body.removeEventListener("unload",
522
- unloadFunction, false);
523
- element.ownerDocument.defaultView.removeEventListener("pagehide",
524
- unloadFunction, false);
525
- }
526
-
527
- // It is possible that, even though the native code reports all of the
528
- // keyboard events are out of the GDK event queue, the process is not done.
529
- // These keyboard events are converted into Javascript events - and not all
530
- // of them may have been processed. In fact, this is the common case when
531
- // the sleep timeout above is less than 500 msec.
532
- // The appropriate thing to do is process all the remaining JS events.
533
- // Only existing events in the queue should be processed - hence the call
534
- // to processNextEvent with false.
535
-
536
- var numExtraEventsProcessed = 0;
537
- var hasMoreEvents = thread.processNextEvent(false);
538
- // A safety net to prevent the code from endlessly staying in this loop,
539
- // in case there is some source of events that's constantly generating them.
540
- var MAX_EXTRA_EVENTS_TO_PROCESS = 150;
541
-
542
- while ((hasMoreEvents) &&
543
- (numExtraEventsProcessed < MAX_EXTRA_EVENTS_TO_PROCESS)) {
544
- hasMoreEvents = thread.processNextEvent(false);
545
- numExtraEventsProcessed += 1;
546
- }
547
-
548
- return;
549
- }
550
-
551
- Utils.dumpn("Doing sendKeys in a non-native way...")
552
- var controlKey = false;
553
- var shiftKey = false;
554
- var altKey = false;
555
- var metaKey = false;
556
-
557
- Utils.shiftCount = 0;
558
-
559
- var upper = text.toUpperCase();
560
-
561
- for (var i = 0; i < text.length; i++) {
562
- var c = text.charAt(i);
563
-
564
- // NULL key: reset modifier key states, and continue
565
-
566
- if (c == '\uE000') {
567
- if (controlKey) {
568
- var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_CONTROL;
569
- Utils.keyEvent(doc, element, "keyup", kCode, 0,
570
- controlKey = false, shiftKey, altKey, metaKey);
571
- }
572
-
573
- if (shiftKey) {
574
- var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SHIFT;
575
- Utils.keyEvent(doc, element, "keyup", kCode, 0,
576
- controlKey, shiftKey = false, altKey, metaKey);
577
- }
578
-
579
- if (altKey) {
580
- var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_ALT;
581
- Utils.keyEvent(doc, element, "keyup", kCode, 0,
582
- controlKey, shiftKey, altKey = false, metaKey);
583
- }
584
-
585
- if (metaKey) {
586
- var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_META;
587
- Utils.keyEvent(doc, element, "keyup", kCode, 0,
588
- controlKey, shiftKey, altKey, metaKey = false);
589
- }
590
-
591
- continue;
592
- }
593
-
594
- // otherwise decode keyCode, charCode, modifiers ...
595
-
596
- var modifierEvent = "";
597
- var charCode = 0;
598
- var keyCode = 0;
599
-
600
- if (c == '\uE001') {
601
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_CANCEL;
602
- } else if (c == '\uE002') {
603
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_HELP;
604
- } else if (c == '\uE003') {
605
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_BACK_SPACE;
606
- } else if (c == '\uE004') {
607
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_TAB;
608
- } else if (c == '\uE005') {
609
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_CLEAR;
610
- } else if (c == '\uE006') {
611
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_RETURN;
612
- } else if (c == '\uE007') {
613
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_ENTER;
614
- } else if (c == '\uE008') {
615
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SHIFT;
616
- shiftKey = !shiftKey;
617
- modifierEvent = shiftKey ? "keydown" : "keyup";
618
- } else if (c == '\uE009') {
619
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_CONTROL;
620
- controlKey = !controlKey;
621
- modifierEvent = controlKey ? "keydown" : "keyup";
622
- } else if (c == '\uE00A') {
623
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_ALT;
624
- altKey = !altKey;
625
- modifierEvent = altKey ? "keydown" : "keyup";
626
- } else if (c == '\uE03D') {
627
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_META;
628
- metaKey = !metaKey;
629
- modifierEvent = metaKey ? "keydown" : "keyup";
630
- } else if (c == '\uE00B') {
631
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_PAUSE;
632
- } else if (c == '\uE00C') {
633
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_ESCAPE;
634
- } else if (c == '\uE00D') {
635
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SPACE;
636
- keyCode = charCode = ' '.charCodeAt(0); // printable
637
- } else if (c == '\uE00E') {
638
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_PAGE_UP;
639
- } else if (c == '\uE00F') {
640
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_PAGE_DOWN;
641
- } else if (c == '\uE010') {
642
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_END;
643
- } else if (c == '\uE011') {
644
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_HOME;
645
- } else if (c == '\uE012') {
646
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_LEFT;
647
- } else if (c == '\uE013') {
648
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_UP;
649
- } else if (c == '\uE014') {
650
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_RIGHT;
651
- } else if (c == '\uE015') {
652
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_DOWN;
653
- } else if (c == '\uE016') {
654
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_INSERT;
655
- } else if (c == '\uE017') {
656
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_DELETE;
657
- } else if (c == '\uE018') {
658
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SEMICOLON;
659
- charCode = ';'.charCodeAt(0);
660
- } else if (c == '\uE019') {
661
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_EQUALS;
662
- charCode = '='.charCodeAt(0);
663
- } else if (c == '\uE01A') {
664
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD0;
665
- charCode = '0'.charCodeAt(0);
666
- } else if (c == '\uE01B') {
667
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD1;
668
- charCode = '1'.charCodeAt(0);
669
- } else if (c == '\uE01C') {
670
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD2;
671
- charCode = '2'.charCodeAt(0);
672
- } else if (c == '\uE01D') {
673
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD3;
674
- charCode = '3'.charCodeAt(0);
675
- } else if (c == '\uE01E') {
676
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD4;
677
- charCode = '4'.charCodeAt(0);
678
- } else if (c == '\uE01F') {
679
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD5;
680
- charCode = '5'.charCodeAt(0);
681
- } else if (c == '\uE020') {
682
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD6;
683
- charCode = '6'.charCodeAt(0);
684
- } else if (c == '\uE021') {
685
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD7;
686
- charCode = '7'.charCodeAt(0);
687
- } else if (c == '\uE022') {
688
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD8;
689
- charCode = '8'.charCodeAt(0);
690
- } else if (c == '\uE023') {
691
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD9;
692
- charCode = '9'.charCodeAt(0);
693
- } else if (c == '\uE024') {
694
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_MULTIPLY;
695
- charCode = '*'.charCodeAt(0);
696
- } else if (c == '\uE025') {
697
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_ADD;
698
- charCode = '+'.charCodeAt(0);
699
- } else if (c == '\uE026') {
700
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SEPARATOR;
701
- charCode = ','.charCodeAt(0);
702
- } else if (c == '\uE027') {
703
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SUBTRACT;
704
- charCode = '-'.charCodeAt(0);
705
- } else if (c == '\uE028') {
706
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_DECIMAL;
707
- charCode = '.'.charCodeAt(0);
708
- } else if (c == '\uE029') {
709
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_DIVIDE;
710
- charCode = '/'.charCodeAt(0);
711
- } else if (c == '\uE031') {
712
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F1;
713
- } else if (c == '\uE032') {
714
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F2;
715
- } else if (c == '\uE033') {
716
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F3;
717
- } else if (c == '\uE034') {
718
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F4;
719
- } else if (c == '\uE035') {
720
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F5;
721
- } else if (c == '\uE036') {
722
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F6;
723
- } else if (c == '\uE037') {
724
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F7;
725
- } else if (c == '\uE038') {
726
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F8;
727
- } else if (c == '\uE039') {
728
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F9;
729
- } else if (c == '\uE03A') {
730
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F10;
731
- } else if (c == '\uE03B') {
732
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F11;
733
- } else if (c == '\uE03C') {
734
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F12;
735
- } else if (c == ',' || c == '<') {
736
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_COMMA;
737
- charCode = c.charCodeAt(0);
738
- } else if (c == '.' || c == '>') {
739
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_PERIOD;
740
- charCode = c.charCodeAt(0);
741
- } else if (c == '/' || c == '?') {
742
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SLASH;
743
- charCode = text.charCodeAt(i);
744
- } else if (c == '`' || c == '~') {
745
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_BACK_QUOTE;
746
- charCode = c.charCodeAt(0);
747
- } else if (c == '{' || c == '[') {
748
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_OPEN_BRACKET;
749
- charCode = c.charCodeAt(0);
750
- } else if (c == '\\' || c == '|') {
751
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_BACK_SLASH;
752
- charCode = c.charCodeAt(0);
753
- } else if (c == '}' || c == ']') {
754
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_CLOSE_BRACKET;
755
- charCode = c.charCodeAt(0);
756
- } else if (c == '\'' || c == '"') {
757
- keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_QUOTE;
758
- charCode = c.charCodeAt(0);
759
- } else {
760
- keyCode = upper.charCodeAt(i);
761
- charCode = text.charCodeAt(i);
762
- }
763
-
764
- // generate modifier key event if needed, and continue
765
-
766
- if (modifierEvent) {
767
- Utils.keyEvent(doc, element, modifierEvent, keyCode, 0,
768
- controlKey, shiftKey, altKey, metaKey);
769
- continue;
770
- }
771
-
772
- // otherwise, shift down if needed
773
-
774
- var needsShift = false;
775
- if (charCode) {
776
- needsShift = /[A-Z\!\$\^\*\(\)\+\{\}\:\?\|~@#%&_"<>]/.test(c);
777
- }
778
-
779
- if (needsShift && !shiftKey) {
780
- var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SHIFT;
781
- Utils.keyEvent(doc, element, "keydown", kCode, 0,
782
- controlKey, true, altKey, metaKey);
783
- Utils.shiftCount += 1;
784
- }
785
-
786
- // generate key[down/press/up] for key
787
-
788
- var pressCode = keyCode;
789
- if (charCode >= 32 && charCode < 127) {
790
- pressCode = 0;
791
- if (!needsShift && shiftKey && charCode > 32) {
792
- // If typing a lowercase character key and the shiftKey is down, the
793
- // charCode should be mapped to the shifted key value. This assumes
794
- // a default 104 international keyboard layout.
795
- if (charCode >= 97 && charCode <= 122) {
796
- charCode = charCode + 65 - 97; // [a-z] -> [A-Z]
797
- } else {
798
- var mapFrom = '`1234567890-=[]\\;\',./';
799
- var mapTo = '~!@#$%^&*()_+{}|:"<>?';
800
-
801
- var value = String.fromCharCode(charCode).
802
- replace(/([\[\\\.])/g, '\\$1');
803
- var index = mapFrom.search(value);
804
- if (index >= 0) {
805
- charCode = mapTo.charCodeAt(index);
806
- }
807
- }
808
- }
809
- }
810
-
811
- var accepted =
812
- Utils.keyEvent(doc, element, "keydown", keyCode, 0,
813
- controlKey, needsShift || shiftKey, altKey, metaKey);
814
-
815
- Utils.keyEvent(doc, element, "keypress", pressCode, charCode,
816
- controlKey, needsShift || shiftKey, altKey, metaKey, !accepted);
817
-
818
- Utils.keyEvent(doc, element, "keyup", keyCode, 0,
819
- controlKey, needsShift || shiftKey, altKey, metaKey);
820
-
821
- // shift up if needed
822
-
823
- if (needsShift && !shiftKey) {
824
- var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SHIFT;
825
- Utils.keyEvent(doc, element, "keyup", kCode, 0,
826
- controlKey, false, altKey, metaKey);
827
- }
828
- }
829
-
830
- // exit cleanup: keyup active modifier keys
831
-
832
- if (controlKey) {
833
- var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_CONTROL;
834
- Utils.keyEvent(doc, element, "keyup", kCode, 0,
835
- controlKey = false, shiftKey, altKey, metaKey);
836
- }
837
-
838
- if (shiftKey) {
839
- var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SHIFT;
840
- Utils.keyEvent(doc, element, "keyup", kCode, 0,
841
- controlKey, shiftKey = false, altKey, metaKey);
842
- }
843
-
844
- if (altKey) {
845
- var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_ALT;
846
- Utils.keyEvent(doc, element, "keyup", kCode, 0,
847
- controlKey, shiftKey, altKey = false, metaKey);
848
- }
849
-
850
- if (metaKey) {
851
- var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_META;
852
- Utils.keyEvent(doc, element, "keyup", kCode, 0,
853
- controlKey, shiftKey, altKey, metaKey = false);
854
- }
855
- };
856
-
857
-
858
- Utils.keyEvent = function(doc, element, type, keyCode, charCode,
859
- controlState, shiftState, altState, metaState,
860
- shouldPreventDefault) {
861
- var preventDefault = shouldPreventDefault == undefined ? false
862
- : shouldPreventDefault;
863
-
864
- var keyboardEvent = doc.createEvent("KeyEvents");
865
- var currentView = doc.defaultView;
866
-
867
- keyboardEvent.initKeyEvent(
868
- type, // in DOMString typeArg,
869
- true, // in boolean canBubbleArg
870
- true, // in boolean cancelableArg
871
- currentView, // in nsIDOMAbstractView viewArg
872
- controlState, // in boolean ctrlKeyArg
873
- altState, // in boolean altKeyArg
874
- shiftState, // in boolean shiftKeyArg
875
- metaState, // in boolean metaKeyArg
876
- keyCode, // in unsigned long keyCodeArg
877
- charCode); // in unsigned long charCodeArg
878
-
879
- if (preventDefault) {
880
- keyboardEvent.preventDefault();
881
- }
882
-
883
- return element.dispatchEvent(keyboardEvent);
884
- };
885
-
886
-
887
- Utils.fireHtmlEvent = function(element, eventName) {
888
- var doc = element.ownerDocument;
889
- var e = doc.createEvent("HTMLEvents");
890
- e.initEvent(eventName, true, true);
891
- return element.dispatchEvent(e);
892
- };
893
-
894
-
895
- Utils.findForm = function(element) {
896
- // Are we already on an element that can be used to submit the form?
897
- try {
898
- element.QueryInterface(Components.interfaces.nsIDOMHTMLButtonElement);
899
- return element;
900
- } catch(e) {
901
- }
902
-
903
- try {
904
- var input =
905
- element.QueryInterface(Components.interfaces.nsIDOMHTMLInputElement);
906
- if (input.type == "image" || input.type == "submit")
907
- return input;
908
- } catch(e) {
909
- }
910
-
911
- var form = element;
912
- while (form) {
913
- if (form["submit"])
914
- return form;
915
- form = form.parentNode;
916
- }
917
- return undefined;
918
- };
919
-
920
-
921
- Utils.fireMouseEventOn = function(element, eventName) {
922
- Utils.triggerMouseEvent(element, eventName, 0, 0);
923
- };
924
-
925
-
926
- Utils.triggerMouseEvent = function(element, eventType, clientX, clientY) {
927
- var event = element.ownerDocument.createEvent("MouseEvents");
928
- var view = element.ownerDocument.defaultView;
929
-
930
- event.initMouseEvent(eventType, true, true, view, 1, 0, 0, clientX, clientY,
931
- false, false, false, false, 0, element);
932
- element.dispatchEvent(event);
933
- };
934
-
935
-
936
- Utils.findDocumentInFrame = function(browser, frameId) {
937
- var frame = Utils.findFrame(browser, frameId);
938
- return frame ? frame.document : null;
939
- };
940
-
941
-
942
- Utils.findFrame = function(browser, frameId) {
943
- var stringId = "" + frameId;
944
- var names = stringId.split(".");
945
- var frame = browser.contentWindow;
946
- for (var i = 0; i < names.length; i++) {
947
- // Try a numerical index first
948
- var index = names[i] - 0;
949
- if (!isNaN(index)) {
950
- frame = frame.frames[index];
951
- if (frame) {
952
- return frame;
953
- }
954
- } else {
955
- // Fine. Use the name and loop
956
- var found = false;
957
- for (var j = 0; j < frame.frames.length; j++) {
958
- var f = frame.frames[j];
959
- var wholeRestOfName = names.slice(i).join(".");
960
- if (f.name == wholeRestOfName || f.frameElement.id == wholeRestOfName) {
961
- return f;
962
- }
963
- if (f.name == names[i] || f.frameElement.id == names[i]) {
964
- frame = f;
965
- found = true;
966
- break;
967
- }
968
- }
969
-
970
- if (!found) {
971
- return null;
972
- }
973
- }
974
- }
975
-
976
- return frame;
977
- };
978
-
979
-
980
- Utils.dumpText = function(text) {
981
- if (!Utils.dumpText.isLoggingInit_) {
982
- var prefs =
983
- Utils.getService("@mozilla.org/preferences-service;1", "nsIPrefBranch");
984
- Utils.dumpText.isLoggingInit_ = true;
985
- Utils.dumpText.logToConsole_ =
986
- prefs.prefHasUserValue("webdriver_log_to_console") &&
987
- prefs.getBoolPref("webdriver_log_to_console");
988
- }
989
- var consoleService = Utils.getService(
990
- "@mozilla.org/consoleservice;1", "nsIConsoleService");
991
- if (consoleService) {
992
- consoleService.logStringMessage(text);
993
- if (Utils.dumpText.logToConsole_) {
994
- dump(text);
995
- }
996
- } else {
997
- dump(text);
998
- }
999
- };
1000
-
1001
-
1002
- Utils.dumpn = function(text) {
1003
- Utils.dumpText(text + "\n");
1004
- };
1005
-
1006
-
1007
- Utils.dump = function(element) {
1008
- var dump = "=============\n";
1009
-
1010
- var rows = [];
1011
-
1012
- dump += "Supported interfaces: ";
1013
- for (var i in Components.interfaces) {
1014
- try {
1015
- var view = element.QueryInterface(Components.interfaces[i]);
1016
- dump += i + ", ";
1017
- } catch (e) {
1018
- // Doesn't support the interface
1019
- }
1020
- }
1021
- dump += "\n------------\n";
1022
-
1023
- try {
1024
- Utils.dumpProperties(element, rows);
1025
- } catch (e) {
1026
- Utils.dumpText("caught an exception: " + e);
1027
- }
1028
-
1029
- rows.sort();
1030
- for (var i in rows) {
1031
- dump += rows[i] + "\n";
1032
- }
1033
-
1034
- dump += "=============\n\n\n";
1035
- Utils.dumpText(dump);
1036
- };
1037
-
1038
-
1039
- Utils.dumpProperties = function(view, rows) {
1040
- for (var i in view) {
1041
- var value = "\t" + i + ": ";
1042
- try {
1043
- if (typeof(view[i]) == typeof(Function)) {
1044
- value += " function()";
1045
- } else {
1046
- value += String(view[i]);
1047
- }
1048
- } catch (e) {
1049
- value += " Cannot obtain value";
1050
- }
1051
-
1052
- rows.push(value);
1053
- }
1054
- };
1055
-
1056
-
1057
- Utils.stackTrace = function() {
1058
- var stack = Components.stack;
1059
- var i = 5;
1060
- var dump = "";
1061
- while (i && stack.caller) {
1062
- stack = stack.caller;
1063
- dump += stack + "\n";
1064
- }
1065
-
1066
- Utils.dumpText(dump);
1067
- };
1068
-
1069
-
1070
- Utils.getElementLocation = function(element) {
1071
- var x = element.offsetLeft;
1072
- var y = element.offsetTop;
1073
- var elementParent = element.offsetParent;
1074
- while (elementParent != null) {
1075
- if (elementParent.tagName == "TABLE") {
1076
- var parentBorder = parseInt(elementParent.border);
1077
- if (isNaN(parentBorder)) {
1078
- var parentFrame = elementParent.getAttribute('frame');
1079
- if (parentFrame != null) {
1080
- x += 1;
1081
- y += 1;
1082
- }
1083
- } else if (parentBorder > 0) {
1084
- x += parentBorder;
1085
- y += parentBorder;
1086
- }
1087
- }
1088
- x += elementParent.offsetLeft;
1089
- y += elementParent.offsetTop;
1090
- elementParent = elementParent.offsetParent;
1091
- }
1092
-
1093
- // Netscape can get confused in some cases, such that the height of the parent
1094
- // is smaller than that of the element (which it shouldn't really be). If this
1095
- // is the case, we need to exclude this element, since it will result in too
1096
- // large a 'top' return value.
1097
- if (element.offsetParent && element.offsetParent.offsetHeight
1098
- && element.offsetParent.offsetHeight < element.offsetHeight) {
1099
- // skip the parent that's too small
1100
- element = element.offsetParent.offsetParent;
1101
- } else {
1102
- // Next up...
1103
- element = element.offsetParent;
1104
- }
1105
- var location = new Object();
1106
- location.x = x;
1107
- location.y = y;
1108
- return location;
1109
- };
1110
-
1111
-
1112
- Utils.findElementsByXPath = function (xpath, contextNode, doc) {
1113
- var result = doc.evaluate(xpath, contextNode, null,
1114
- Components.interfaces.nsIDOMXPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
1115
- var indices = [];
1116
- var element = result.iterateNext();
1117
- while (element) {
1118
- var index = Utils.addToKnownElements(element, doc);
1119
- indices.push(index);
1120
- element = result.iterateNext();
1121
- }
1122
- return indices;
1123
- };
1124
-
1125
-
1126
- Utils.getLocation = function(element) {
1127
- var retrieval = Utils.newInstance(
1128
- "@mozilla.org/accessibleRetrieval;1", "nsIAccessibleRetrieval");
1129
-
1130
- try {
1131
- element = element.wrappedJSObject ? element.wrappedJSObject : element;
1132
-
1133
- var clientRect = element.getBoundingClientRect();
1134
-
1135
- // Firefox 3.5
1136
- if (clientRect['width']) {
1137
- return {
1138
- x : clientRect.left + 3,
1139
- y : clientRect.top,
1140
- width: clientRect.width,
1141
- height: clientRect.height
1142
- };
1143
- }
1144
-
1145
- // Firefox 3.0.14 seems to have top, bottom attributes.
1146
- if (clientRect['top'] !== undefined) {
1147
- var retWidth = clientRect.right - clientRect.left;
1148
- var retHeight = clientRect.bottom - clientRect.top;
1149
- return {
1150
- x : clientRect.left,
1151
- y : clientRect.top,
1152
- width: retWidth,
1153
- height: retHeight
1154
- }
1155
- }
1156
-
1157
- // Firefox 3.0, but lacking client rect
1158
- Utils.dumpn("Falling back to firefox3 mechanism");
1159
- var accessible = retrieval.getAccessibleFor(element);
1160
-
1161
- var x = {}, y = {}, width = {}, height = {};
1162
- accessible.getBounds(x, y, width, height);
1163
-
1164
- return {
1165
- x : clientRect.left + 3,
1166
- y : clientRect.top,
1167
- width: width.value,
1168
- height: height.value
1169
- };
1170
- } catch(e) {
1171
- Utils.dumpn(e);
1172
- // Element doesn't have an accessibility node
1173
- }
1174
-
1175
- // Firefox 2.0
1176
-
1177
- Utils.dumpn("Falling back to firefox2 mechanism");
1178
- // Fallback. Use the (deprecated) method to find out where the element is in
1179
- // the viewport. This should be fine to use because we only fall down this
1180
- // code path on older versions of Firefox (I think!)
1181
- var theDoc = element.ownerDocument;
1182
- var box = theDoc.getBoxObjectFor(element);
1183
-
1184
- // We've seen cases where width is 0, despite the element actually having
1185
- // children with width.
1186
- // This happens particularly with GWT.
1187
- if (box.width == 0 || box.height == 0) {
1188
- // Check the child, and hope the user doesn't nest this stuff. Walk the
1189
- // children til we find an element. At this point, we know that width and
1190
- // height are a polite fiction
1191
- for (var i = 0; i < element.childNodes.length; i++) {
1192
- var c = element.childNodes[i];
1193
- if (c.nodeType == 1) {
1194
- Utils.dumpn(
1195
- "Width and height are ficticious values, based on child node");
1196
- box = theDoc.getBoxObjectFor(c);
1197
- break;
1198
- }
1199
- }
1200
- }
1201
-
1202
- return {
1203
- x : box.x + 3,
1204
- y : box.y,
1205
- width: box.width,
1206
- height: box.height
1207
- };
1208
- };
1209
-
1210
-
1211
- Utils.getLocationOnceScrolledIntoView = function(element) {
1212
- // Some elements may not a scrollIntoView function - for example,
1213
- // elements under an SVG element. Call those only if they exist.
1214
- if (typeof element.scrollIntoView == 'function') {
1215
- element.scrollIntoView(true);
1216
- }
1217
-
1218
- return Utils.getLocation(element);
1219
- };
1220
-
1221
-
1222
- Utils.unwrapParameters = function(wrappedParameters, doc) {
1223
- var converted = [];
1224
- while (wrappedParameters && wrappedParameters.length > 0) {
1225
- var t = wrappedParameters.shift();
1226
- switch (typeof t) {
1227
- case 'number':
1228
- case 'string':
1229
- case 'boolean':
1230
- converted.push(t);
1231
- break;
1232
- case 'object':
1233
- if (t == null) {
1234
- converted.push(null);
1235
- } else if (typeof t.length === 'number' &&
1236
- !(t.propertyIsEnumerable('length'))) {
1237
- converted.push(Utils.unwrapParameters(t, doc));
1238
- } else if (typeof t['ELEMENT'] === 'string') {
1239
- var element = Utils.getElementAt(t['ELEMENT'], doc);
1240
- element = element.wrappedJSObject ? element.wrappedJSObject : element;
1241
- converted.push(element);
1242
- } else {
1243
- var convertedObj = {};
1244
- for (var prop in t) {
1245
- convertedObj[prop] = Utils.unwrapParameters(t[prop], doc);
1246
- }
1247
- converted.push(convertedObj);
1248
- }
1249
- break;
1250
- }
1251
- }
1252
- return converted;
1253
- };
1254
-
1255
-
1256
- Utils.isArray_ = function(obj) {
1257
- return (obj !== undefined &&
1258
- obj.constructor.toString().indexOf("Array") != -1);
1259
- }
1260
-
1261
-
1262
- Utils.isHtmlCollection_ = function(obj) {
1263
- return (obj !== undefined && obj['length'] &&
1264
- obj['item'] && obj['namedItem']);
1265
- }
1266
-
1267
-
1268
- Utils.wrapResult = function(result, doc) {
1269
- // Sophisticated.
1270
- switch (typeof result) {
1271
- case 'string':
1272
- case 'number':
1273
- case 'boolean':
1274
- return result;
1275
-
1276
- case 'function':
1277
- return result.toString();
1278
-
1279
- case 'undefined':
1280
- return null;
1281
-
1282
- case 'object':
1283
- if (result == null) {
1284
- return null;
1285
- }
1286
-
1287
- // There's got to be a more intelligent way of detecting this.
1288
- if (result['tagName']) {
1289
- return {'ELEMENT': Utils.addToKnownElements(result, doc)};
1290
- }
1291
-
1292
- if (typeof result.length === 'number' &&
1293
- !(result.propertyIsEnumerable('length'))) {
1294
- var array = [];
1295
- for (var i = 0; i < result.length; i++) {
1296
- array.push(Utils.wrapResult(result[i], doc));
1297
- }
1298
- return array;
1299
- }
1300
-
1301
- var convertedObj = {};
1302
- for (var prop in result) {
1303
- convertedObj[prop] = Utils.wrapResult(result[prop], doc);
1304
- }
1305
- return convertedObj;
1306
-
1307
- default:
1308
- return result;
1309
- }
1310
- };
1311
-
1312
- /**
1313
- * Gets canonical xpath of the passed element, e.g. /HTML[1]/BODY[1]/P[1]
1314
- */
1315
- Utils.getXPathOfElement = function(element) {
1316
- var path = "";
1317
- for (; element && element.nodeType == 1; element = element.parentNode) {
1318
- index = Utils.getElementIndexForXPath_(element);
1319
- path = "/" + element.tagName + "[" + index + "]" + path;
1320
- }
1321
- return path;
1322
- }
1323
-
1324
- /**
1325
- * Returns n for the nth child of the parent of that element, of type element.tagName, starting at 1
1326
- */
1327
- Utils.getElementIndexForXPath_ = function (element) {
1328
- var index = 1;
1329
- for (var sibling = element.previousSibling; sibling ; sibling = sibling.previousSibling) {
1330
- if (sibling.nodeType == 1 && sibling.tagName == element.tagName) {
1331
- index++;
1332
- }
1333
- }
1334
- return index;
1335
- }