selenium-webdriver 0.0.17 → 0.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. data/chrome/prebuilt/Win32/Release/npchromedriver.dll +0 -0
  2. data/chrome/prebuilt/x64/Release/npchromedriver.dll +0 -0
  3. data/chrome/src/extension/background.js +64 -48
  4. data/chrome/src/extension/content_script.js +253 -132
  5. data/chrome/src/extension/manifest-nonwin.json +1 -1
  6. data/chrome/src/extension/manifest-win.json +1 -1
  7. data/chrome/src/extension/utils.js +8 -8
  8. data/chrome/src/rb/lib/selenium/webdriver/chrome.rb +9 -0
  9. data/chrome/src/rb/lib/selenium/webdriver/chrome/bridge.rb +38 -280
  10. data/chrome/src/rb/lib/selenium/webdriver/chrome/command_executor.rb +119 -117
  11. data/chrome/src/rb/lib/selenium/webdriver/chrome/launcher.rb +36 -26
  12. data/common/src/js/abstractcommandprocessor.js +9 -11
  13. data/common/src/js/command.js +159 -83
  14. data/common/src/js/core/RemoteRunner.html +2 -2
  15. data/common/src/js/core/TestRunner-splash.html +3 -3
  16. data/common/src/js/core/TestRunner.html +5 -17
  17. data/common/src/js/core/scripts/htmlutils.js +4208 -2506
  18. data/common/src/js/core/scripts/selenium-api.js +2 -2
  19. data/common/src/js/core/scripts/selenium-browserbot.js +66 -58
  20. data/common/src/js/core/scripts/selenium-version.js +1 -1
  21. data/common/src/js/localcommandprocessor.js +5 -19
  22. data/common/src/js/testcase.js +2 -0
  23. data/common/src/js/webdriver.js +63 -93
  24. data/common/src/js/webelement.js +40 -42
  25. data/common/src/rb/lib/selenium/webdriver.rb +23 -14
  26. data/common/src/rb/lib/selenium/webdriver/bridge_helper.rb +8 -35
  27. data/common/src/rb/lib/selenium/webdriver/child_process.rb +2 -0
  28. data/common/src/rb/lib/selenium/webdriver/core_ext/dir.rb +1 -0
  29. data/common/src/rb/lib/selenium/webdriver/core_ext/string.rb +5 -0
  30. data/common/src/rb/lib/selenium/webdriver/driver.rb +20 -15
  31. data/common/src/rb/lib/selenium/webdriver/driver_extensions/takes_screenshot.rb +7 -2
  32. data/common/src/rb/lib/selenium/webdriver/element.rb +11 -2
  33. data/common/src/rb/lib/selenium/webdriver/error.rb +9 -5
  34. data/common/src/rb/lib/selenium/webdriver/keys.rb +1 -2
  35. data/common/src/rb/lib/selenium/webdriver/navigation.rb +16 -0
  36. data/common/src/rb/lib/selenium/webdriver/options.rb +32 -0
  37. data/common/src/rb/lib/selenium/webdriver/platform.rb +17 -1
  38. data/firefox/prebuilt/Win32/Release/webdriver-firefox.dll +0 -0
  39. data/firefox/src/extension/components/dispatcher.js +492 -0
  40. data/firefox/src/extension/components/driver-component.js +4 -1
  41. data/firefox/src/extension/components/errorcode.js +70 -0
  42. data/firefox/src/extension/components/firefoxDriver.js +173 -154
  43. data/firefox/src/extension/components/nsCommandProcessor.js +171 -132
  44. data/firefox/src/extension/components/promptService.js +5 -5
  45. data/firefox/src/extension/components/request.js +219 -0
  46. data/firefox/src/extension/components/response.js +276 -0
  47. data/firefox/src/extension/components/session.js +281 -0
  48. data/firefox/src/extension/components/sessionstore.js +226 -0
  49. data/firefox/src/extension/components/socketListener.js +350 -100
  50. data/firefox/src/extension/components/utils.js +166 -98
  51. data/firefox/src/extension/components/webdriverserver.js +9 -5
  52. data/firefox/src/extension/components/wrappedElement.js +189 -166
  53. data/firefox/src/extension/install.rdf +1 -1
  54. data/firefox/src/rb/lib/selenium/webdriver/firefox.rb +2 -0
  55. data/firefox/src/rb/lib/selenium/webdriver/firefox/binary.rb +39 -33
  56. data/firefox/src/rb/lib/selenium/webdriver/firefox/bridge.rb +7 -421
  57. data/firefox/src/rb/lib/selenium/webdriver/firefox/extension_connection.rb +7 -64
  58. data/firefox/src/rb/lib/selenium/webdriver/firefox/launcher.rb +2 -3
  59. data/firefox/src/rb/lib/selenium/webdriver/firefox/profile.rb +54 -10
  60. data/firefox/src/rb/lib/selenium/webdriver/firefox/profiles_ini.rb +2 -0
  61. data/firefox/src/rb/lib/selenium/webdriver/firefox/util.rb +6 -0
  62. data/jobbie/prebuilt/Win32/Release/InternetExplorerDriver.dll +0 -0
  63. data/jobbie/prebuilt/x64/Release/InternetExplorerDriver.dll +0 -0
  64. data/jobbie/src/rb/lib/selenium/webdriver/ie.rb +2 -0
  65. data/jobbie/src/rb/lib/selenium/webdriver/ie/bridge.rb +38 -13
  66. data/jobbie/src/rb/lib/selenium/webdriver/ie/lib.rb +9 -2
  67. data/jobbie/src/rb/lib/selenium/webdriver/ie/util.rb +5 -0
  68. data/remote/client/src/rb/lib/selenium/webdriver/remote.rb +2 -0
  69. data/remote/client/src/rb/lib/selenium/webdriver/remote/bridge.rb +42 -38
  70. data/remote/client/src/rb/lib/selenium/webdriver/remote/commands.rb +56 -47
  71. data/remote/client/src/rb/lib/selenium/webdriver/remote/default_http_client.rb +26 -26
  72. data/remote/client/src/rb/lib/selenium/webdriver/remote/patron_http_client.rb +58 -0
  73. data/remote/client/src/rb/lib/selenium/webdriver/remote/response.rb +10 -12
  74. data/remote/client/src/rb/lib/selenium/webdriver/remote/server_error.rb +2 -17
  75. metadata +44 -23
  76. data/common/src/js/context.js +0 -58
  77. data/firefox/src/extension/components/context.js +0 -37
@@ -29,6 +29,13 @@ function WebDriverServer() {
29
29
  // loaded and cause a "too deep recursion" error.
30
30
  var overrideService = Components.classes["@mozilla.org/security/certoverride;1"]
31
31
  .getService(Components.interfaces.nsICertOverrideService);
32
+
33
+ /**
34
+ * This server's request dispatcher.
35
+ * @type {Dispatcher}
36
+ * @private
37
+ */
38
+ this.dispatcher_ = new Dispatcher();
32
39
  }
33
40
 
34
41
 
@@ -44,10 +51,7 @@ WebDriverServer.prototype.newDriver = function(window) {
44
51
  prefs.getBoolPref("webdriver_enable_native_events") : false;
45
52
  Utils.dumpn('Enable native events: ' + this.enableNativeEvents);
46
53
  }
47
- window.fxdriver = new FirefoxDriver(this, this.enableNativeEvents);
48
- // Yuck. But it allows us to refer to it later.
49
- window.fxdriver.window = window;
50
-
54
+ window.fxdriver = new FirefoxDriver(this, this.enableNativeEvents, window);
51
55
  return window.fxdriver;
52
56
  };
53
57
 
@@ -59,7 +63,7 @@ WebDriverServer.prototype.getNextId = function() {
59
63
 
60
64
  WebDriverServer.prototype.onSocketAccepted = function(socket, transport) {
61
65
  try {
62
- var socketListener = new SocketListener(transport);
66
+ var socketListener = new SocketListener(this.dispatcher_, transport);
63
67
  } catch(e) {
64
68
  dump(e);
65
69
  }
@@ -17,15 +17,23 @@
17
17
  */
18
18
 
19
19
 
20
- FirefoxDriver.prototype.click = function(respond) {
21
- var element = Utils.getElementAt(respond.elementId, respond.context);
20
+ FirefoxDriver.prototype.elementEquals = function(respond, parameters) {
21
+ var elementA = Utils.getElementAt(parameters.id,
22
+ respond.session.getDocument());
23
+ var elementB = Utils.getElementAt(parameters.other,
24
+ respond.session.getDocument());
25
+ respond.value = elementA == elementB;
26
+ respond.send();
27
+ };
28
+
29
+
30
+ FirefoxDriver.prototype.clickElement = function(respond, parameters) {
31
+ var element = Utils.getElementAt(parameters.id,
32
+ respond.session.getDocument());
22
33
 
23
34
  if (!Utils.isDisplayed(element, true) && !Utils.isInHead(element)) {
24
- respond.isError = true;
25
- respond.response =
26
- "Element is not currently visible and so may not be clicked";
27
- respond.send();
28
- return;
35
+ throw new WebDriverError(ErrorCode.ELEMENT_NOT_VISIBLE,
36
+ "Element is not currently visible and so may not be clicked");
29
37
  }
30
38
 
31
39
  var nativeEvents = Utils.getNativeEvents();
@@ -84,10 +92,7 @@ FirefoxDriver.prototype.click = function(respond) {
84
92
  Utils.dumpn("Detected error when clicking: " + e.name);
85
93
 
86
94
  if (e.name != "NS_ERROR_NOT_IMPLEMENTED") {
87
- respond.isError = true;
88
- respond.response = e.toString();
89
- respond.send();
90
- return;
95
+ throw new WebDriverError(ErrorCode.INVALID_ELEMENT_STATE, e);
91
96
  }
92
97
 
93
98
  // Fall through to the synthesized click code.
@@ -95,11 +100,12 @@ FirefoxDriver.prototype.click = function(respond) {
95
100
  }
96
101
 
97
102
  Utils.dumpn("Falling back to synthesized click");
98
- var currentlyActive = Utils.getActiveElement(respond.context);
103
+ var doc = respond.session.getDocument()
104
+ var currentlyActive = Utils.getActiveElement(doc);
99
105
 
100
- Utils.fireMouseEventOn(respond.context, element, "mouseover");
101
- Utils.fireMouseEventOn(respond.context, element, "mousemove");
102
- Utils.fireMouseEventOn(respond.context, element, "mousedown");
106
+ Utils.fireMouseEventOn(element, "mouseover");
107
+ Utils.fireMouseEventOn(element, "mousemove");
108
+ Utils.fireMouseEventOn(element, "mousedown");
103
109
  if (element != currentlyActive) {
104
110
  // Some elements may not have blur, focus functions - for example,
105
111
  // elements under an SVG element. Call those only if they exist.
@@ -111,10 +117,10 @@ FirefoxDriver.prototype.click = function(respond) {
111
117
  }
112
118
  }
113
119
 
114
- Utils.fireMouseEventOn(respond.context, element, "mouseup");
115
- Utils.fireMouseEventOn(respond.context, element, "click");
120
+ Utils.fireMouseEventOn(element, "mouseup");
121
+ Utils.fireMouseEventOn(element, "click");
116
122
 
117
- var browser = Utils.getBrowser(respond.context);
123
+ var browser = respond.session.getBrowser();
118
124
  var alreadyReplied = false;
119
125
 
120
126
  var clickListener = new WebLoadingListener(browser, function(event) {
@@ -145,6 +151,8 @@ FirefoxDriver.prototype.click = function(respond) {
145
151
 
146
152
 
147
153
  if (contentWindow.closed) {
154
+ // Nulls out the session; client will have to switch to another
155
+ // window on their own.
148
156
  respond.send();
149
157
  return;
150
158
  }
@@ -152,52 +160,51 @@ FirefoxDriver.prototype.click = function(respond) {
152
160
  };
153
161
 
154
162
 
155
- FirefoxDriver.prototype.getText = function(respond) {
156
- var element = Utils.getElementAt(respond.elementId, respond.context);
163
+ FirefoxDriver.prototype.getElementText = function(respond, parameters) {
164
+ var element = Utils.getElementAt(parameters.id,
165
+ respond.session.getDocument());
157
166
 
158
167
  if (element.tagName == "TITLE") {
159
- respond.response = Utils.getBrowser(respond.context).contentTitle;
168
+ respond.value = respond.session.getBrowser().contentTitle;
160
169
  } else {
161
- respond.response = Utils.getText(element, true);
170
+ respond.value = Utils.getText(element, true);
162
171
  }
163
172
 
164
173
  respond.send();
165
174
  };
166
175
 
167
176
 
168
- FirefoxDriver.prototype.getValue = function(respond) {
169
- var element = Utils.getElementAt(respond.elementId, respond.context);
177
+ FirefoxDriver.prototype.getElementValue = function(respond, parameters) {
178
+ var element = Utils.getElementAt(parameters.id,
179
+ respond.session.getDocument());
170
180
 
171
181
  if (element["value"] !== undefined) {
172
- respond.response = element.value;
182
+ respond.value = element.value;
173
183
  respond.send();
174
184
  return;
175
185
  }
176
186
 
177
187
  if (element.hasAttribute("value")) {
178
- respond.response = element.getAttribute("value");
188
+ respond.value = element.getAttribute("value");
179
189
  respond.send();
180
190
  return;
181
191
  }
182
192
 
183
- respond.isError = true;
184
- respond.response = "No match";
185
- respond.send();
193
+ throw new WebDriverError(ErrorCode.INVALID_ELEMENT_STATE,
194
+ 'Element does not have a value attribute');
186
195
  };
187
196
 
188
197
 
189
- FirefoxDriver.prototype.sendKeys = function(respond, value) {
190
- var element = Utils.getElementAt(respond.elementId, respond.context);
198
+ FirefoxDriver.prototype.sendKeysToElement = function(respond, parameters) {
199
+ var element = Utils.getElementAt(parameters.id,
200
+ respond.session.getDocument());
191
201
 
192
202
  if (!Utils.isDisplayed(element, true) && !Utils.isInHead(element)) {
193
- respond.isError = true;
194
- respond.response =
195
- "Element is not currently visible and so may not be used for typing";
196
- respond.send();
197
- return;
203
+ throw new WebDriverError(ErrorCode.ELEMENT_NOT_VISIBLE,
204
+ "Element is not currently visible and so may not be used for typing");
198
205
  }
199
206
 
200
- var currentlyActive = Utils.getActiveElement(respond.context);
207
+ var currentlyActive = Utils.getActiveElement(respond.session.getDocument());
201
208
  if (currentlyActive != element) {
202
209
  currentlyActive.blur();
203
210
  element.focus();
@@ -214,26 +221,24 @@ FirefoxDriver.prototype.sendKeys = function(respond, value) {
214
221
  use = element.ownerDocument.getElementsByTagName("html")[0];
215
222
  }
216
223
 
217
- Utils.type(respond.context, use, value[0], this.enableNativeEvents);
224
+ Utils.type(respond.session.getDocument(), use, parameters.value.join(''), this.enableNativeEvents);
218
225
 
219
226
  respond.send();
220
227
  };
221
228
 
222
229
 
223
- FirefoxDriver.prototype.clear = function(respond) {
224
- var element = Utils.getElementAt(respond.elementId, respond.context);
230
+ FirefoxDriver.prototype.clearElement = function(respond, parameters) {
231
+ var element = Utils.getElementAt(parameters.id,
232
+ respond.session.getDocument());
225
233
 
226
234
  if (!Utils.isDisplayed(element, true) && !Utils.isInHead(element)) {
227
- respond.isError = true;
228
- respond.response =
229
- "Element is not currently visible and so may not be cleared";
230
- respond.send();
231
- return;
235
+ throw new WebDriverError(ErrorCode.ELEMENT_NOT_VISIBLE,
236
+ "Element is not currently visible and so may not be cleared");
232
237
  }
233
238
 
234
239
  var isTextField = element["value"] !== undefined;
235
240
 
236
- var currentlyActive = Utils.getActiveElement(respond.context);
241
+ var currentlyActive = Utils.getActiveElement(respond.session.getDocument());
237
242
  if (currentlyActive != element) {
238
243
  currentlyActive.blur();
239
244
  element.focus();
@@ -253,37 +258,39 @@ FirefoxDriver.prototype.clear = function(respond) {
253
258
  }
254
259
 
255
260
  if (currentValue !== undefined && currentValue != "") {
256
- Utils.fireHtmlEvent(respond.context, element, "change");
261
+ Utils.fireHtmlEvent(element, "change");
257
262
  }
258
263
 
259
264
  respond.send();
260
265
  };
261
266
 
262
267
 
263
- FirefoxDriver.prototype.getTagName = function(respond) {
264
- var element = Utils.getElementAt(respond.elementId, respond.context);
268
+ FirefoxDriver.prototype.getElementTagName = function(respond, parameters) {
269
+ var element = Utils.getElementAt(parameters.id,
270
+ respond.session.getDocument());
265
271
 
266
- respond.response = element.tagName.toLowerCase();
272
+ respond.value = element.tagName.toLowerCase();
267
273
  respond.send();
268
274
  };
269
275
 
270
276
 
271
- FirefoxDriver.prototype.getAttribute = function(respond, value) {
272
- var element = Utils.getElementAt(respond.elementId, respond.context);
277
+ FirefoxDriver.prototype.getElementAttribute = function(respond, parameters) {
278
+ var element = Utils.getElementAt(parameters.id,
279
+ respond.session.getDocument());
273
280
 
274
- var attributeName = value[0];
281
+ var attributeName = parameters.name;
275
282
 
276
283
  if (element.hasAttribute(attributeName)) {
277
- respond.response = element.getAttribute(attributeName);
284
+ respond.value = element.getAttribute(attributeName);
278
285
  // Is this block necessary?
279
286
  if (attributeName.toLowerCase() == "disabled") {
280
- respond.response = element.disabled;
287
+ respond.value = element.disabled;
281
288
  } else if (attributeName.toLowerCase() == "selected") {
282
- respond.response = element.selected;
289
+ respond.value = element.selected;
283
290
  } else if (attributeName.toLowerCase() == "checked") {
284
- respond.response = element.checked;
291
+ respond.value = element.checked;
285
292
  } else if (attributeName.toLowerCase() == "readonly") {
286
- respond.response = element.readOnly;
293
+ respond.value = element.readOnly;
287
294
  }
288
295
 
289
296
  respond.send();
@@ -293,32 +300,41 @@ FirefoxDriver.prototype.getAttribute = function(respond, value) {
293
300
  attributeName = attributeName.toLowerCase();
294
301
 
295
302
  if (attributeName == "disabled") {
296
- respond.response = (element.disabled === undefined ? false : element.disabled);
303
+ respond.value = (element.disabled === undefined ? false : element.disabled);
297
304
  respond.send();
298
305
  return;
299
306
  } else if ((attributeName == "checked" || attributeName == "selected") &&
300
307
  element.tagName.toLowerCase() == "input") {
301
- respond.response = element.checked;
308
+ respond.value = element.checked;
302
309
  respond.send();
303
310
  return;
304
311
  } else if (attributeName == "selected" && element.tagName.toLowerCase()
305
312
  == "option") {
306
- respond.response = element.selected;
313
+ respond.value = element.selected;
307
314
  respond.send();
308
315
  return;
309
316
  } else if (attributeName == "index" && element.tagName.toLowerCase()
310
317
  == "option") {
311
- respond.response = element.index;
318
+ respond.value = element.index;
312
319
  respond.send();
313
320
  return;
314
321
  }
315
- respond.response = null;
322
+ respond.value = null;
316
323
  respond.send();
317
324
  };
318
325
 
319
326
 
320
- FirefoxDriver.prototype.hover = function(respond) {
321
- var element = Utils.getElementAt(respond.elementId, respond.context);
327
+ FirefoxDriver.prototype.isElementEnabled = function(respond, parameters) {
328
+ var element = Utils.getElementAt(parameters.id,
329
+ respond.session.getDocument());
330
+ respond.value = !!!element.disabled;
331
+ respond.send();
332
+ };
333
+
334
+
335
+ FirefoxDriver.prototype.hoverOverElement = function(respond, parameters) {
336
+ var element = Utils.getElementAt(parameters.id,
337
+ respond.session.getDocument());
322
338
 
323
339
  var events = Utils.getNativeEvents();
324
340
  var node = Utils.getNodeForNativeEvents(element);
@@ -333,23 +349,25 @@ FirefoxDriver.prototype.hover = function(respond) {
333
349
  this.currentX = x;
334
350
  this.currentY = y;
335
351
  } else {
336
- respond.isError = true;
337
- respond.response = "Unable to hover over element";
352
+ // TODO: use the correct error type here.
353
+ throw new WebDriverError(ErrorCode.INVALID_ELEMENT_STATE,
354
+ "Unable to hover over element");
338
355
  }
339
356
 
340
357
  respond.send();
341
358
  };
342
359
 
343
- FirefoxDriver.prototype.submit = function(respond) {
344
- var element = Utils.getElementAt(respond.elementId, respond.context);
360
+ FirefoxDriver.prototype.submitElement = function(respond, parameters) {
361
+ var element = Utils.getElementAt(parameters.id,
362
+ respond.session.getDocument());
345
363
 
346
364
  if (element) {
347
365
  while (element.parentNode != null && element.tagName.toLowerCase() != "form") {
348
366
  element = element.parentNode;
349
367
  }
350
368
  if (element.tagName && element.tagName.toLowerCase() == "form") {
351
- if (Utils.fireHtmlEvent(respond.context, element, "submit")) {
352
- new WebLoadingListener(Utils.getBrowser(respond.context), function() {
369
+ if (Utils.fireHtmlEvent(element, "submit")) {
370
+ new WebLoadingListener(respond.session.getBrowser(), function() {
353
371
  respond.send();
354
372
  });
355
373
  element.submit();
@@ -360,10 +378,8 @@ FirefoxDriver.prototype.submit = function(respond) {
360
378
  return;
361
379
  }
362
380
  } else {
363
- respond.isError = true;
364
- respond.response = "Element was not in a form so couldn't submit";
365
- respond.send();
366
- return;
381
+ throw new WebDriverError(ErrorCode.INVALID_ELEMENT_STATE,
382
+ "Element was not in a form so couldn't submit");
367
383
  }
368
384
  } else {
369
385
  respond.send();
@@ -371,8 +387,9 @@ FirefoxDriver.prototype.submit = function(respond) {
371
387
  }
372
388
  };
373
389
 
374
- FirefoxDriver.prototype.isSelected = function(respond) {
375
- var element = Utils.getElementAt(respond.elementId, respond.context);
390
+ FirefoxDriver.prototype.isElementSelected = function(respond, parameters) {
391
+ var element = Utils.getElementAt(parameters.id,
392
+ respond.session.getDocument());
376
393
 
377
394
  var selected = false;
378
395
 
@@ -392,87 +409,87 @@ FirefoxDriver.prototype.isSelected = function(respond) {
392
409
  } catch(e) {
393
410
  }
394
411
 
395
- respond.response = selected;
412
+ respond.value = selected;
396
413
  respond.send();
397
414
  };
398
415
 
399
416
 
400
- FirefoxDriver.prototype.setSelected = function(respond) {
401
- var element = Utils.getElementAt(respond.elementId, respond.context);
417
+ FirefoxDriver.prototype.setElementSelected = function(respond, parameters) {
418
+ var element = Utils.getElementAt(parameters.id,
419
+ respond.session.getDocument());
402
420
 
403
421
  if (!Utils.isDisplayed(element, true) && !Utils.isInHead(element)) {
404
- respond.isError = true;
405
- respond.response =
406
- "Element is not currently visible and so may not be selected";
407
- respond.send();
408
- return;
422
+ throw new WebDriverError(ErrorCode.ELEMENT_NOT_VISIBLE,
423
+ "Element is not currently visible and so may not be selected");
409
424
  }
410
425
 
411
- var wasSet = "You may not select an unselectable element";
412
- respond.isError = true;
413
-
414
- try {
415
- var inputElement =
416
- element.QueryInterface(Components.interfaces.nsIDOMHTMLInputElement);
417
- if (inputElement.disabled) {
418
- respond.response = "You may not select a disabled element";
419
- respond.send();
420
- return;
426
+ function safeQueryInterface(element, queryFor) {
427
+ try {
428
+ return element.QueryInterface(queryFor);
429
+ } catch (ignored) {
430
+ return null;
421
431
  }
422
- } catch(e) {
423
432
  }
424
433
 
425
- try {
426
- var option =
427
- element.QueryInterface(Components.interfaces.nsIDOMHTMLOptionElement);
434
+ var option = safeQueryInterface(
435
+ element, Components.interfaces.nsIDOMHTMLOptionElement);
436
+ if (option) {
428
437
  var select = element;
429
- while (select.parentNode != null && select.tagName.toLowerCase() != "select") {
438
+ while (select.parentNode && select.tagName.toLowerCase() != 'select') {
430
439
  select = select.parentNode;
431
440
  }
432
- if (select.tagName.toLowerCase() == "select") {
433
- select = select.QueryInterface(Components.interfaces.nsIDOMHTMLSelectElement);
434
- } else {
441
+ select = safeQueryInterface(
442
+ select, Components.interfaces.nsIDOMHTMLSelectElement);
443
+ if (!select) {
435
444
  //If we're not within a select element, fire the event from the option, and hope that it bubbles up
436
445
  Utils.dumpn("Falling back to event firing from option, not select element");
437
446
  select = option;
438
447
  }
439
- respond.isError = false;
448
+
440
449
  if (!option.selected) {
441
450
  option.selected = true;
442
- Utils.fireHtmlEvent(respond.context, select, "change");
451
+ Utils.fireHtmlEvent(select, 'change');
443
452
  }
444
- wasSet = "";
445
- } catch(e) {
453
+
454
+ respond.status = ErrorCode.SUCCESS;
455
+ respond.value = '';
456
+ respond.send();
457
+ return;
446
458
  }
447
459
 
448
- try {
449
- var checkbox =
450
- element.QueryInterface(Components.interfaces.nsIDOMHTMLInputElement);
451
- respond.isError = false;
452
- if (checkbox.type == "checkbox" || checkbox.type == "radio") {
453
- if (!checkbox.checked) {
454
- checkbox.checked = true;
455
- Utils.fireHtmlEvent(respond.context, checkbox, "change");
460
+ var inputElement = safeQueryInterface(
461
+ element, Components.interfaces.nsIDOMHTMLInputElement);
462
+ if (inputElement) {
463
+ if (inputElement.disabled) {
464
+ throw new WebDriverError(ErrorCode.INVALID_ELEMENT_STATE,
465
+ "You may not select a disabled element");
466
+ }
467
+
468
+ if (inputElement.type == 'checkbox' || inputElement.type == 'radio') {
469
+ if (!inputElement.checked) {
470
+ inputElement.checked = true;
471
+ Utils.fireHtmlEvent(inputElement, 'change');
456
472
  }
457
- wasSet = "";
473
+
474
+ respond.status = ErrorCode.SUCCESS;
475
+ respond.value = '';
476
+ respond.send();
477
+ return;
458
478
  }
459
- } catch(e) {
460
479
  }
461
480
 
462
- respond.response = wasSet;
463
- respond.send();
481
+ throw new WebDriverError(ErrorCode.INVALID_ELEMENT_STATE,
482
+ 'You may not select an unselectable element');
464
483
  };
465
484
 
466
485
 
467
- FirefoxDriver.prototype.toggle = function(respond) {
468
- var element = Utils.getElementAt(respond.elementId, respond.context);
486
+ FirefoxDriver.prototype.toggleElement = function(respond, parameters) {
487
+ var element = Utils.getElementAt(parameters.id,
488
+ respond.session.getDocument());
469
489
 
470
490
  if (!Utils.isDisplayed(element) && !Utils.isInHead(element)) {
471
- respond.isError = true;
472
- respond.response =
473
- "Element is not currently visible and so may not be toggled";
474
- respond.send();
475
- return;
491
+ throw new WebDriverError(ErrorCode.ELEMENT_NOT_VISIBLE,
492
+ "Element is not currently visible and so may not be toggled");
476
493
  }
477
494
 
478
495
  try {
@@ -480,7 +497,8 @@ FirefoxDriver.prototype.toggle = function(respond) {
480
497
  element.QueryInterface(Components.interfaces.nsIDOMHTMLInputElement);
481
498
  if (checkbox.type == "checkbox") {
482
499
  checkbox.checked = !checkbox.checked;
483
- Utils.fireHtmlEvent(respond.context, checkbox, "change");
500
+ Utils.fireHtmlEvent(checkbox, "change");
501
+ respond.value = checkbox.checked;
484
502
  respond.send();
485
503
  return;
486
504
  }
@@ -499,47 +517,50 @@ FirefoxDriver.prototype.toggle = function(respond) {
499
517
 
500
518
  if (select && select.multiple) {
501
519
  option.selected = !option.selected;
502
- Utils.fireHtmlEvent(respond.context, option, "change");
520
+ Utils.fireHtmlEvent(option, "change");
521
+ respond.value = option.selected;
503
522
  respond.send();
504
523
  return;
505
524
  }
506
525
  } catch(e) {
507
526
  }
508
527
 
509
- respond.isError = true;
510
- respond.response =
528
+ throw new WebDriverError(ErrorCode.INVALID_ELEMENT_STATE,
511
529
  "You may only toggle an element that is either a checkbox or an " +
512
- "option in a select that allows multiple selections";
513
- respond.send();
530
+ "option in a select that allows multiple selections");
514
531
  };
515
532
 
516
533
 
517
- FirefoxDriver.prototype.isDisplayed = function(respond) {
518
- var element = Utils.getElementAt(respond.elementId, respond.context);
519
- respond.response = Utils.isDisplayed(element, false);
534
+ FirefoxDriver.prototype.isElementDisplayed = function(respond, parameters) {
535
+ var element = Utils.getElementAt(parameters.id,
536
+ respond.session.getDocument());
537
+ respond.value = Utils.isDisplayed(element, false);
520
538
  respond.send();
521
539
  };
522
540
 
523
541
 
524
- FirefoxDriver.prototype.getLocation = function(respond) {
525
- var element = Utils.getElementAt(respond.elementId, respond.context);
542
+ FirefoxDriver.prototype.getElementLocation = function(respond, parameters) {
543
+ var element = Utils.getElementAt(parameters.id,
544
+ respond.session.getDocument());
526
545
 
527
- var location = Utils.getElementLocation(element, respond.context);
546
+ var location = Utils.getElementLocation(element);
528
547
 
529
- respond.response = {
548
+ respond.value = {
530
549
  x: Math.round(location.x),
531
550
  y: Math.round(location.y)
532
551
  };
552
+
533
553
  respond.send();
534
554
  };
535
555
 
536
556
 
537
- FirefoxDriver.prototype.getSize = function(respond) {
538
- var element = Utils.getElementAt(respond.elementId, respond.context);
557
+ FirefoxDriver.prototype.getElementSize = function(respond, parameters) {
558
+ var element = Utils.getElementAt(parameters.id,
559
+ respond.session.getDocument());
539
560
 
540
561
  var box = Utils.getLocationOnceScrolledIntoView(element);
541
562
 
542
- respond.response = {
563
+ respond.value = {
543
564
  width: Math.round(box.width),
544
565
  height: Math.round(box.height)
545
566
  };
@@ -547,27 +568,26 @@ FirefoxDriver.prototype.getSize = function(respond) {
547
568
  };
548
569
 
549
570
 
550
- FirefoxDriver.prototype.dragElement = function(respond, movementString) {
551
- var element = Utils.getElementAt(respond.elementId, respond.context);
571
+ FirefoxDriver.prototype.dragElement = function(respond, parameters) {
572
+ var element = Utils.getElementAt(parameters.id,
573
+ respond.session.getDocument());
552
574
 
553
575
  if (!Utils.isDisplayed(element, true) && !Utils.isInHead(element)) {
554
- respond.isError = true;
555
- respond.response =
556
- "Element is not currently visible and so may not be used for drag and drop";
557
- respond.send();
558
- return;
576
+ throw new WebDriverError(ErrorCode.ELEMENT_NOT_VISIBLE,
577
+ "Element is not currently visible and so may not be used for " +
578
+ "drag and drop");
559
579
  }
560
580
 
561
581
  // Scroll the first element into view
562
582
  // element.scrollIntoView(true);
563
583
 
564
- var clientStartXY = Utils.getElementLocation(element, respond.context);
584
+ var clientStartXY = Utils.getElementLocation(element);
565
585
 
566
586
  var clientStartX = clientStartXY.x;
567
587
  var clientStartY = clientStartXY.y;
568
588
 
569
- var movementX = movementString[0];
570
- var movementY = movementString[1];
589
+ var movementX = parameters.x;
590
+ var movementY = parameters.y;
571
591
 
572
592
  var clientFinishX = ((clientStartX + movementX) < 0) ? 0 : (clientStartX
573
593
  + movementX);
@@ -582,7 +602,7 @@ FirefoxDriver.prototype.dragElement = function(respond, movementString) {
582
602
  if (clientFinishY > body.scrollHeight)
583
603
  clientFinishY = body.scrollHeight;
584
604
 
585
- var mouseSpeed = this.mouseSpeed;
605
+ var mouseSpeed = respond.session.getInputSpeed();
586
606
  var move = function(current, dest) {
587
607
  if (current == dest) return current;
588
608
  if (Math.abs(current - dest) < mouseSpeed) return dest;
@@ -607,27 +627,29 @@ FirefoxDriver.prototype.dragElement = function(respond, movementString) {
607
627
  // send the mouseup to that
608
628
  Utils.triggerMouseEvent(element, 'mouseup', clientFinishX, clientFinishY);
609
629
 
610
- var finalLoc = Utils.getElementLocation(element, respond.context)
630
+ var finalLoc = Utils.getElementLocation(element);
611
631
 
612
- respond.response = finalLoc.x + "," + finalLoc.y;
632
+ respond.value = finalLoc.x + "," + finalLoc.y;
613
633
  respond.send();
614
634
  };
615
635
 
616
636
 
617
- FirefoxDriver.prototype.getValueOfCssProperty = function(respond,
618
- propertyName) {
619
- var element = Utils.getElementAt(respond.elementId, respond.context);
620
-
621
- respond.response = Utils.getStyleProperty(element, propertyName); // Coeerce to a string
637
+ FirefoxDriver.prototype.getElementValueOfCssProperty = function(respond,
638
+ parameters) {
639
+ var element = Utils.getElementAt(parameters.id,
640
+ respond.session.getDocument());
641
+ respond.value = Utils.getStyleProperty(element, parameters.propertyName); // Coeerce to a string
622
642
  respond.send();
623
643
  };
624
644
 
625
645
 
626
- FirefoxDriver.prototype.getLocationOnceScrolledIntoView = function(respond) {
627
- var element = Utils.getElementAt(respond.elementId, respond.context);
646
+ FirefoxDriver.prototype.getElementLocationOnceScrolledIntoView = function(
647
+ respond, parameters) {
648
+ var element = Utils.getElementAt(parameters.id,
649
+ respond.session.getDocument());
628
650
 
629
651
  if (!Utils.isDisplayed(element, true)) {
630
- respond.response = undefined;
652
+ respond.value = undefined;
631
653
  respond.send();
632
654
  return;
633
655
  }
@@ -644,7 +666,7 @@ FirefoxDriver.prototype.getLocationOnceScrolledIntoView = function(respond) {
644
666
  var x = {}, y = {}, width = {}, height = {};
645
667
  accessible.getBounds(x, y, width, height);
646
668
 
647
- respond.response = {
669
+ respond.value = {
648
670
  x : x.value,
649
671
  y : y.value
650
672
  };
@@ -655,6 +677,7 @@ FirefoxDriver.prototype.getLocationOnceScrolledIntoView = function(respond) {
655
677
  }
656
678
 
657
679
  // If we have the box object (which is deprecated) we could try using it
680
+ var theDoc = respond.session.getDocument();
658
681
  if (theDoc.getBoxObjectFor) {
659
682
  // Fallback. Use the (deprecated) method to find out where the element is in
660
683
  // the viewport. This should be fine to use because we only fall down this
@@ -662,7 +685,7 @@ FirefoxDriver.prototype.getLocationOnceScrolledIntoView = function(respond) {
662
685
 
663
686
  var box = theDoc.getBoxObjectFor(element);
664
687
 
665
- respond.response = {
688
+ respond.value = {
666
689
  x : box.screenX,
667
690
  y : box.screenY
668
691
  };
@@ -675,7 +698,7 @@ FirefoxDriver.prototype.getLocationOnceScrolledIntoView = function(respond) {
675
698
  var y = theDoc.defaultView.screenY;
676
699
 
677
700
  var rect = element.getBoundingClientRect()
678
- respond.response = {
701
+ respond.value = {
679
702
  x : x + rect.left,
680
703
  y : y + rect.top
681
704
  }