selenium-webdriver 0.0.17 → 0.0.18

Sign up to get free protection for your applications and to get access to all the features.
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
  }