selenium-webdriver 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) 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.html +9 -0
  4. data/chrome/src/extension/background.js +933 -0
  5. data/chrome/src/extension/content_script.js +1286 -0
  6. data/chrome/src/extension/manifest-nonwin.json +15 -0
  7. data/chrome/src/extension/manifest-win.json +16 -0
  8. data/chrome/src/extension/toolstrip.html +28 -0
  9. data/chrome/src/extension/utils.js +196 -0
  10. data/chrome/src/rb/lib/selenium/webdriver/chrome.rb +8 -0
  11. data/chrome/src/rb/lib/selenium/webdriver/chrome/bridge.rb +324 -0
  12. data/chrome/src/rb/lib/selenium/webdriver/chrome/command_executor.rb +70 -0
  13. data/chrome/src/rb/lib/selenium/webdriver/chrome/launcher.rb +119 -0
  14. data/common/src/js/abstractcommandprocessor.js +161 -0
  15. data/common/src/js/asserts.js +296 -0
  16. data/common/src/js/by.js +147 -0
  17. data/common/src/js/command.js +274 -0
  18. data/common/src/js/context.js +58 -0
  19. data/common/src/js/extension/README +2 -0
  20. data/common/src/js/extension/dommessenger.js +152 -0
  21. data/common/src/js/factory.js +55 -0
  22. data/common/src/js/future.js +118 -0
  23. data/common/src/js/key.js +117 -0
  24. data/common/src/js/localcommandprocessor.js +181 -0
  25. data/common/src/js/logging.js +249 -0
  26. data/common/src/js/testrunner.js +605 -0
  27. data/common/src/js/timing.js +89 -0
  28. data/common/src/js/wait.js +199 -0
  29. data/common/src/js/webdriver.js +853 -0
  30. data/common/src/js/webelement.js +683 -0
  31. data/common/src/rb/lib/selenium-webdriver.rb +1 -0
  32. data/common/src/rb/lib/selenium/webdriver.rb +52 -0
  33. data/common/src/rb/lib/selenium/webdriver/bridge_helper.rb +88 -0
  34. data/common/src/rb/lib/selenium/webdriver/child_process.rb +85 -0
  35. data/common/src/rb/lib/selenium/webdriver/core_ext/dir.rb +41 -0
  36. data/common/src/rb/lib/selenium/webdriver/driver.rb +128 -0
  37. data/common/src/rb/lib/selenium/webdriver/element.rb +126 -0
  38. data/common/src/rb/lib/selenium/webdriver/error.rb +68 -0
  39. data/common/src/rb/lib/selenium/webdriver/find.rb +69 -0
  40. data/common/src/rb/lib/selenium/webdriver/navigation.rb +23 -0
  41. data/common/src/rb/lib/selenium/webdriver/options.rb +50 -0
  42. data/common/src/rb/lib/selenium/webdriver/platform.rb +82 -0
  43. data/common/src/rb/lib/selenium/webdriver/target_locator.rb +23 -0
  44. data/firefox/prebuilt/nsICommandProcessor.xpt +0 -0
  45. data/firefox/prebuilt/nsINativeEvents.xpt +0 -0
  46. data/firefox/prebuilt/nsIResponseHandler.xpt +0 -0
  47. data/firefox/src/extension/chrome.manifest +3 -0
  48. data/firefox/src/extension/components/context.js +37 -0
  49. data/firefox/src/extension/components/driver-component.js +127 -0
  50. data/firefox/src/extension/components/firefoxDriver.js +706 -0
  51. data/firefox/src/extension/components/json2.js +273 -0
  52. data/firefox/src/extension/components/keytest.html +554 -0
  53. data/firefox/src/extension/components/nsCommandProcessor.js +586 -0
  54. data/firefox/src/extension/components/screenshooter.js +70 -0
  55. data/firefox/src/extension/components/socketListener.js +185 -0
  56. data/firefox/src/extension/components/utils.js +1200 -0
  57. data/firefox/src/extension/components/webLoadingListener.js +57 -0
  58. data/firefox/src/extension/components/webdriverserver.js +101 -0
  59. data/firefox/src/extension/components/wrappedElement.js +609 -0
  60. data/firefox/src/extension/content/fxdriver.xul +30 -0
  61. data/firefox/src/extension/content/server.js +95 -0
  62. data/firefox/src/extension/idl/nsICommandProcessor.idl +38 -0
  63. data/firefox/src/extension/idl/nsIResponseHandler.idl +34 -0
  64. data/firefox/src/extension/install.rdf +29 -0
  65. data/firefox/src/rb/lib/selenium/webdriver/firefox.rb +21 -0
  66. data/firefox/src/rb/lib/selenium/webdriver/firefox/binary.rb +86 -0
  67. data/firefox/src/rb/lib/selenium/webdriver/firefox/bridge.rb +426 -0
  68. data/firefox/src/rb/lib/selenium/webdriver/firefox/extension_connection.rb +82 -0
  69. data/firefox/src/rb/lib/selenium/webdriver/firefox/launcher.rb +132 -0
  70. data/firefox/src/rb/lib/selenium/webdriver/firefox/profile.rb +174 -0
  71. data/firefox/src/rb/lib/selenium/webdriver/firefox/profiles_ini.rb +60 -0
  72. data/firefox/src/rb/lib/selenium/webdriver/firefox/util.rb +23 -0
  73. data/jobbie/prebuilt/Win32/Release/InternetExplorerDriver.dll +0 -0
  74. data/jobbie/prebuilt/x64/Release/InternetExplorerDriver.dll +0 -0
  75. data/jobbie/src/rb/lib/selenium/webdriver/ie.rb +14 -0
  76. data/jobbie/src/rb/lib/selenium/webdriver/ie/bridge.rb +552 -0
  77. data/jobbie/src/rb/lib/selenium/webdriver/ie/lib.rb +94 -0
  78. data/jobbie/src/rb/lib/selenium/webdriver/ie/util.rb +147 -0
  79. data/remote/client/src/rb/lib/selenium/webdriver/remote.rb +16 -0
  80. data/remote/client/src/rb/lib/selenium/webdriver/remote/bridge.rb +374 -0
  81. data/remote/client/src/rb/lib/selenium/webdriver/remote/capabilities.rb +105 -0
  82. data/remote/client/src/rb/lib/selenium/webdriver/remote/commands.rb +53 -0
  83. data/remote/client/src/rb/lib/selenium/webdriver/remote/default_http_client.rb +71 -0
  84. data/remote/client/src/rb/lib/selenium/webdriver/remote/response.rb +43 -0
  85. data/remote/client/src/rb/lib/selenium/webdriver/remote/server_error.rb +32 -0
  86. metadata +182 -0
@@ -0,0 +1,706 @@
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
+ function FirefoxDriver(server, enableNativeEvents) {
21
+ this.server = server;
22
+ this.mouseSpeed = 1;
23
+ this.enableNativeEvents = enableNativeEvents;
24
+
25
+ this.currentX = 0;
26
+ this.currentY = 0;
27
+ }
28
+
29
+ FirefoxDriver.prototype.__defineGetter__("id", function() {
30
+ if (!this.id_) {
31
+ this.id_ = this.server.getNextId();
32
+ }
33
+
34
+ return this.id_;
35
+ });
36
+
37
+
38
+ FirefoxDriver.prototype.getCurrentWindowHandle = function(respond) {
39
+ respond.response = this.id;
40
+ respond.send();
41
+ };
42
+
43
+
44
+ FirefoxDriver.prototype.get = function(respond, url) {
45
+ // Check to see if the given url is the same as the current one, but
46
+ // with a different anchor tag.
47
+ var current = Utils.getBrowser(respond.context).contentWindow.location;
48
+ var ioService =
49
+ Utils.getService("@mozilla.org/network/io-service;1", "nsIIOService");
50
+ var currentUri = ioService.newURI(current, "", null);
51
+ var futureUri = ioService.newURI(url, "", currentUri);
52
+
53
+ var loadEventExpected = true;
54
+
55
+ if (currentUri && futureUri &&
56
+ currentUri.prePath == futureUri.prePath &&
57
+ currentUri.filePath == futureUri.filePath) {
58
+ // Looks like we're at the same url with a ref
59
+ // Being clever and checking the ref was causing me headaches.
60
+ // Brute force for now
61
+ loadEventExpected = futureUri.path.indexOf("#") == -1;
62
+ }
63
+
64
+ if (loadEventExpected) {
65
+ new WebLoadingListener(Utils.getBrowser(respond.context), function() {
66
+ // TODO: Rescue the URI and response code from the event
67
+ var responseText = "";
68
+ respond.context.frameId = "?";
69
+ respond.response = responseText;
70
+ respond.send();
71
+ });
72
+ }
73
+
74
+ Utils.getBrowser(respond.context).loadURI(url);
75
+
76
+ if (!loadEventExpected) {
77
+ respond.send();
78
+ }
79
+ };
80
+
81
+
82
+ FirefoxDriver.prototype.close = function(respond) {
83
+ // Grab all the references we'll need. Once we call close all this might go away
84
+ var wm = Utils.getService(
85
+ "@mozilla.org/appshell/window-mediator;1", "nsIWindowMediator");
86
+ var appService = Utils.getService(
87
+ "@mozilla.org/toolkit/app-startup;1", "nsIAppStartup");
88
+ var forceQuit = Components.interfaces.nsIAppStartup.eForceQuit;
89
+
90
+ // Here we go!
91
+ try {
92
+ var browser = Utils.getBrowser(respond.context);
93
+ createSwitchFile("close:" + browser.id);
94
+ browser.contentWindow.close();
95
+ } catch(e) {
96
+ dump(e);
97
+ }
98
+
99
+ // If we're on a Mac we might have closed all the windows but not quit, so
100
+ // ensure that we do actually quit :)
101
+ var allWindows = wm.getEnumerator("navigator:browser");
102
+ if (!allWindows.hasMoreElements()) {
103
+ appService.quit(forceQuit);
104
+ return; // The client should catch the fact that the socket suddenly closes
105
+ }
106
+
107
+ // If we're still running, return
108
+ respond.send();
109
+ };
110
+
111
+
112
+ FirefoxDriver.prototype.executeScript = function(respond, script) {
113
+ var doc = Utils.getDocument(respond.context);
114
+ var window = doc ? doc.defaultView :
115
+ Utils.getBrowser(respond.context).contentWindow;
116
+
117
+ var parameters = new Array();
118
+ var runScript;
119
+
120
+ // Pre 2.0.0.15
121
+ if (window['alert'] && !window.wrappedJSObject) {
122
+ runScript = function(scriptSrc) {
123
+ return window.eval(scriptSrc);
124
+ };
125
+ } else {
126
+ runScript = function(scriptSrc) {
127
+ window = window.wrappedJSObject;
128
+ var sandbox = new Components.utils.Sandbox(window);
129
+ sandbox.window = window;
130
+ sandbox.__webdriverParams = parameters;
131
+ sandbox.document = window.document;
132
+ sandbox.unsafeWindow = window;
133
+ sandbox.__proto__ = window;
134
+
135
+ return Components.utils.evalInSandbox(scriptSrc, sandbox);
136
+ };
137
+ }
138
+
139
+ try {
140
+ var scriptSrc = "var __webdriverFunc = function(){" + script.shift()
141
+ + "}; __webdriverFunc.apply(window, __webdriverParams);";
142
+
143
+ var convert = script.shift();
144
+
145
+ Utils.unwrapParameters(convert, parameters, respond.context);
146
+
147
+ var result = runScript(scriptSrc, parameters);
148
+
149
+ var wrappedResult = Utils.wrapResult(result, respond.context);
150
+
151
+ if (wrappedResult.resultType !== undefined) {
152
+ respond.setField("resultType", wrappedResult.resultType);
153
+ }
154
+
155
+ if (wrappedResult.response !== undefined) {
156
+ respond.response = wrappedResult.response;
157
+ }
158
+
159
+ } catch (e) {
160
+ respond.isError = true;
161
+ respond.response = e;
162
+ }
163
+ respond.send();
164
+ };
165
+
166
+
167
+ FirefoxDriver.prototype.getCurrentUrl = function(respond) {
168
+ var url = Utils.getDocument(respond.context).defaultView.location;
169
+ if (!url) {
170
+ url = Utils.getBrowser(respond.context).contentWindow.location;
171
+ }
172
+ respond.response = "" + url;
173
+ respond.send();
174
+ };
175
+
176
+
177
+ FirefoxDriver.prototype.title = function(respond) {
178
+ var browser = Utils.getBrowser(respond.context);
179
+ respond.response = browser.contentTitle;
180
+ respond.send();
181
+ };
182
+
183
+
184
+ FirefoxDriver.prototype.getPageSource = function(respond) {
185
+ var source = Utils.getDocument(respond.context).
186
+ getElementsByTagName("html")[0].innerHTML;
187
+
188
+ respond.response = "<html>" + source + "</html>";
189
+ respond.send();
190
+ };
191
+
192
+
193
+ /**
194
+ * Searches for the first element in {@code theDocument} matching the given
195
+ * {@code xpath} expression.
196
+ * @param {nsIDOMDocument} theDocument The document to search in.
197
+ * @param {string} xpath The XPath expression to evaluate.
198
+ * @param {nsIDOMNode} opt_contextNode The context node for the query; defaults
199
+ * to {@code theDocument}.
200
+ * @return {nsIDOMNode} The first matching node.
201
+ * @private
202
+ */
203
+ FirefoxDriver.prototype.findElementByXPath_ = function(theDocument, xpath,
204
+ opt_contextNode) {
205
+ var contextNode = opt_contextNode || theDocument;
206
+ return theDocument.evaluate(xpath, contextNode, null,
207
+ Components.interfaces.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE, null).
208
+ singleNodeValue;
209
+ };
210
+
211
+
212
+ /**
213
+ * Searches for elements matching the given {@code xpath} expression in the
214
+ * specified document.
215
+ * @param {nsIDOMDocument} theDocument The document to search in.
216
+ * @param {string} xpath The XPath expression to evaluate.
217
+ * @param {nsIDOMNode} opt_contextNode The context node for the query; defaults
218
+ * to {@code theDocument}.
219
+ * @return {Array.<nsIDOMNode>} The matching nodes.
220
+ * @private
221
+ */
222
+ FirefoxDriver.prototype.findElementsByXPath_ = function(theDocument, xpath,
223
+ opt_contextNode) {
224
+ var contextNode = opt_contextNode || theDocument;
225
+ var result = theDocument.evaluate(xpath, contextNode, null,
226
+ Components.interfaces.nsIDOMXPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
227
+ var elements = [];
228
+ var element = result.iterateNext();
229
+ while (element) {
230
+ elements.push(element);
231
+ element = result.iterateNext();
232
+ }
233
+ return elements;
234
+ };
235
+
236
+
237
+ /**
238
+ * An enumeration of the supported element locator methods.
239
+ * @enum {string}
240
+ */
241
+ FirefoxDriver.ElementLocator = {
242
+ ID: 'id',
243
+ NAME: 'name',
244
+ CLASS_NAME: 'class name',
245
+ TAG_NAME: 'tag name',
246
+ LINK_TEXT: 'link text',
247
+ PARTIAL_LINK_TEXT: 'partial link text',
248
+ XPATH: 'xpath'
249
+ };
250
+
251
+
252
+ /**
253
+ * Finds an element on the current page. The response value will be the UUID of
254
+ * the located element, or an error message if an element could not be found.
255
+ * @param {Response} respond Object to send the command response with.
256
+ * @param {FirefoxDriver.ElementLocator} method The locator method to use.
257
+ * @param {string} selector What to search for; see {@code ElementLocator} for
258
+ * details on what the selector should be for each element.
259
+ * @param {string} opt_parentElementId If defined, the search will be restricted
260
+ * to the corresponding element's subtree.
261
+ * @private
262
+ */
263
+ FirefoxDriver.prototype.findElementInternal_ = function(respond, method,
264
+ selector,
265
+ opt_parentElementId) {
266
+ var theDocument = Utils.getDocument(respond.context);
267
+ var rootNode = typeof opt_parentElementId == 'string' ?
268
+ Utils.getElementAt(opt_parentElementId, respond.context) : theDocument;
269
+
270
+ var element;
271
+ switch (method) {
272
+ case FirefoxDriver.ElementLocator.ID:
273
+ element = rootNode === theDocument ?
274
+ theDocument.getElementById(selector) :
275
+ this.findElementByXPath_(
276
+ theDocument, './/*[@id="' + selector + '"]', rootNode);
277
+ break;
278
+
279
+ case FirefoxDriver.ElementLocator.NAME:
280
+ element = rootNode.getElementsByName ?
281
+ rootNode.getElementsByName(selector)[0] :
282
+ this.findElementByXPath_(
283
+ theDocument, './/*[@name ="' + selector + '"]', rootNode);
284
+ break;
285
+
286
+ case FirefoxDriver.ElementLocator.CLASS_NAME:
287
+ element = rootNode.getElementsByClassName ?
288
+ rootNode.getElementsByClassName(selector)[0] : // FF 3+
289
+ this.findElementByXPath_(theDocument, // FF 2
290
+ '//*[contains(concat(" ",normalize-space(@class)," ")," ' +
291
+ selector + ' ")]', rootNode);
292
+ break;
293
+
294
+ case FirefoxDriver.ElementLocator.TAG_NAME:
295
+ element = rootNode.getElementsByTagName(selector)[0];
296
+ break;
297
+
298
+ case FirefoxDriver.ElementLocator.XPATH:
299
+ element = this.findElementByXPath_(theDocument, selector, rootNode);
300
+ break;
301
+
302
+ case FirefoxDriver.ElementLocator.LINK_TEXT:
303
+ case FirefoxDriver.ElementLocator.PARTIAL_LINK_TEXT:
304
+ var allLinks = rootNode.getElementsByTagName('A');
305
+ for (var i = 0; i < allLinks.length && !element; i++) {
306
+ var text = Utils.getText(allLinks[i], true);
307
+ if (FirefoxDriver.ElementLocator.PARTIAL_LINK_TEXT == method) {
308
+ if (text.indexOf(selector) != -1) {
309
+ element = allLinks[i];
310
+ }
311
+ } else if (text == selector) {
312
+ element = allLinks[i];
313
+ }
314
+ }
315
+ break;
316
+
317
+ default:
318
+ respond.response = 'Unsupported element locator method: ' + method;
319
+ respond.isError = true;
320
+ respond.send();
321
+ return;
322
+ }
323
+
324
+ if (element) {
325
+ respond.response = Utils.addToKnownElements(element, respond.context);
326
+ } else {
327
+ respond.response = 'Unable to locate element: ' + JSON.stringify({
328
+ method: method,
329
+ selector: selector
330
+ });
331
+ respond.isError = true;
332
+ }
333
+ respond.send();
334
+ };
335
+
336
+
337
+ /**
338
+ * Finds an element on the current page. The response value will be the UUID of
339
+ * the located element, or an error message if an element could not be found.
340
+ * @param {Response} respond Object to send the command response with.
341
+ * @param {Array.<string>} parameters A two-element array: the first element
342
+ * should be a method listen in the {@code Firefox.ElementLocator} enum, and
343
+ * the second should be what to search for.
344
+ */
345
+ FirefoxDriver.prototype.findElement = function(respond, parameters) {
346
+ this.findElementInternal_(respond, parameters[0], parameters[1]);
347
+ };
348
+
349
+
350
+ /**
351
+ * Finds an element on the current page that is the child of a corresponding
352
+ * search parameter. The response value will be the UUID of the located element,
353
+ * or an error message if an element could not be found.
354
+ * @param {Response} respond Object to send the command response with.
355
+ * @param {Array.<{id:string, using:string, value:string}>} parameters A single
356
+ * element array. The array element should define what to search for with
357
+ * the following fields:
358
+ * - id: UUID of the element to base the search from.
359
+ * - using: A method to search with, as defined in the
360
+ * {@code Firefox.ElementLocator} enum.
361
+ * - value: What to search for.
362
+ */
363
+ FirefoxDriver.prototype.findChildElement = function(respond, parameters) {
364
+ var map = parameters[0];
365
+ this.findElementInternal_(respond, map.using, map.value, map.id);
366
+ };
367
+
368
+
369
+ /**
370
+ * Finds elements on the current page. The response value will an array of UUIDs
371
+ * for the located elements.
372
+ * @param {Response} respond Object to send the command response with.
373
+ * @param {FirefoxDriver.ElementLocator} method The locator method to use.
374
+ * @param {string} selector What to search for; see {@code ElementLocator} for
375
+ * details on what the selector should be for each element.
376
+ * @param {string} opt_parentElementId If defined, the search will be restricted
377
+ * to the corresponding element's subtree.
378
+ * @private
379
+ */
380
+ FirefoxDriver.prototype.findElementsInternal_ = function(respond, method,
381
+ selector,
382
+ opt_parentElementId) {
383
+ var theDocument = Utils.getDocument(respond.context);
384
+ var rootNode = typeof opt_parentElementId == 'string' ?
385
+ Utils.getElementAt(opt_parentElementId, respond.context) : theDocument;
386
+
387
+ var elements;
388
+ switch (method) {
389
+ case FirefoxDriver.ElementLocator.ID:
390
+ selector = './/*[@id="' + selector + '"]';
391
+ // Fall-through
392
+ case FirefoxDriver.ElementLocator.XPATH:
393
+ elements = this.findElementsByXPath_(
394
+ theDocument, selector, rootNode);
395
+ break;
396
+
397
+ case FirefoxDriver.ElementLocator.NAME:
398
+ elements = rootNode.getElementsByName ?
399
+ rootNode.getElementsByName(selector) :
400
+ this.findElementsByXPath_(
401
+ theDocument, './/*[@name="' + selector + '"]', rootNode);
402
+ break;
403
+
404
+ case FirefoxDriver.ElementLocator.TAG_NAME:
405
+ elements = rootNode.getElementsByTagName(selector);
406
+ break;
407
+
408
+ case FirefoxDriver.ElementLocator.CLASS_NAME:
409
+ elements = rootNode.getElementsByClassName ?
410
+ rootNode.getElementsByClassName(selector) : // FF 3+
411
+ this.findElementsByXPath_(theDocument, // FF 2
412
+ './/*[contains(concat(" ",normalize-space(@class)," ")," ' +
413
+ selector + ' ")]', rootNode);
414
+ break;
415
+
416
+ case FirefoxDriver.ElementLocator.LINK_TEXT:
417
+ case FirefoxDriver.ElementLocator.PARTIAL_LINK_TEXT:
418
+ elements = rootNode.getElementsByTagName('A');
419
+ elements = Array.filter(elements, function(element) {
420
+ var text = Utils.getText(element, true);
421
+ if (FirefoxDriver.ElementLocator.PARTIAL_LINK_TEXT == method) {
422
+ return text.indexOf(selector) != -1;
423
+ } else {
424
+ return text == selector;
425
+ }
426
+ });
427
+ break;
428
+
429
+ default:
430
+ respond.response = 'Unsupported element locator method: ' + method;
431
+ respond.isError = true;
432
+ respond.send();
433
+ return;
434
+ }
435
+
436
+ var elementIds = [];
437
+ for (var j = 0; j < elements.length; j++) {
438
+ var element = elements[j];
439
+ elementIds.push(Utils.addToKnownElements(element, respond.context));
440
+ }
441
+
442
+ respond.response = elementIds.join(',');
443
+ respond.send();
444
+ };
445
+
446
+
447
+ /**
448
+ * Searches for multiple elements on the page. The response value will be an
449
+ * array of UUIDs for the located elements.
450
+ * @param {Response} respond Object to send the command response with.
451
+ * @param {Array.<string>} parameters A two-element array: the first element
452
+ * should be the type of locator strategy to use, the second is the target
453
+ * of the search.
454
+ */
455
+ FirefoxDriver.prototype.findElements = function(respond, parameters) {
456
+ this.findElementsInternal_(respond, parameters[0], parameters[1]);
457
+ };
458
+
459
+
460
+ /**
461
+ * Searches for multiple elements on the page that are children of the
462
+ * corresponding search parameter. The response value will be an array of UUIDs
463
+ * for the located elements.
464
+ * @param {Array.<{id:string, using:string, value:string}>} parameters A single
465
+ * element array. The array element should define what to search for with
466
+ * the following fields:
467
+ * - id: UUID of the element to base the search from.
468
+ * - using: A method to search with, as defined in the
469
+ * {@code Firefox.ElementLocator} enum.
470
+ * - value: What to search for.
471
+ */
472
+ FirefoxDriver.prototype.findChildElements = function(respond, parameters) {
473
+ var map = parameters[0];
474
+ this.findElementsInternal_(respond, map.using, map.value, map.id);
475
+ };
476
+
477
+
478
+ FirefoxDriver.prototype.switchToFrame = function(respond, frameId) {
479
+ var browser = Utils.getBrowser(respond.context);
480
+ var frameDoc = Utils.findDocumentInFrame(browser, frameId[0]);
481
+
482
+ if (frameDoc) {
483
+ respond.context = new Context(respond.context.windowId, frameId[0]);
484
+ respond.send();
485
+ } else {
486
+ respond.isError = true;
487
+ respond.response = "Cannot find frame with id: " + frameId.toString();
488
+ respond.send();
489
+ }
490
+ };
491
+
492
+
493
+ FirefoxDriver.prototype.switchToDefaultContent = function(respond) {
494
+ respond.context.frameId = "?";
495
+ respond.send();
496
+ };
497
+
498
+
499
+ FirefoxDriver.prototype.switchToActiveElement = function(respond) {
500
+ var element = Utils.getActiveElement(respond.context);
501
+
502
+ respond.response = Utils.addToKnownElements(element, respond.context);
503
+ respond.send();
504
+ };
505
+
506
+
507
+ FirefoxDriver.prototype.goBack = function(respond) {
508
+ var browser = Utils.getBrowser(respond.context);
509
+
510
+ if (browser.canGoBack) {
511
+ browser.goBack();
512
+ }
513
+
514
+ respond.send();
515
+ };
516
+
517
+
518
+ FirefoxDriver.prototype.goForward = function(respond) {
519
+ var browser = Utils.getBrowser(respond.context);
520
+
521
+ if (browser.canGoForward) {
522
+ browser.goForward();
523
+ }
524
+
525
+ respond.send();
526
+ };
527
+
528
+
529
+ FirefoxDriver.prototype.refresh = function(respond) {
530
+ var browser = Utils.getBrowser(respond.context);
531
+ browser.contentWindow.location.reload(true);
532
+
533
+ respond.send();
534
+ };
535
+
536
+
537
+ FirefoxDriver.prototype.addCookie = function(respond, cookieString) {
538
+ var cookie;
539
+ cookie = eval('(' + cookieString[0] + ')');
540
+
541
+ if (cookie.expiry) {
542
+ cookie.expiry = new Date(cookie.expiry);
543
+ } else {
544
+ var date = new Date();
545
+ date.setYear(2030);
546
+ cookie.expiry = date;
547
+ }
548
+
549
+ cookie.expiry = cookie.expiry.getTime() / 1000; // Stored in seconds
550
+
551
+ if (!cookie.domain) {
552
+ var location = Utils.getBrowser(respond.context).contentWindow.location;
553
+ cookie.domain = location.hostname;
554
+ } else {
555
+ var currLocation = Utils.getBrowser(respond.context).contentWindow.location;
556
+ var currDomain = currLocation.host;
557
+ if (currDomain.indexOf(cookie.domain) == -1) { // Not quite right, but close enough
558
+ respond.isError = true;
559
+ respond.response = "You may only set cookies for the current domain";
560
+ respond.send();
561
+ return;
562
+ }
563
+ }
564
+
565
+ // The cookie's domain may include a port. Which is bad. Remove it
566
+ // We'll catch ip6 addresses by mistake. Since no-one uses those
567
+ // this will be okay for now.
568
+ if (cookie.domain.match(/:\d+$/)) {
569
+ cookie.domain = cookie.domain.replace(/:\d+$/, "");
570
+ }
571
+
572
+ var document = Utils.getDocument(respond.context);
573
+ if (!document || !document.contentType.match(/html/i)) {
574
+ respond.isError = true;
575
+ respond.response = "You may only set cookies on html documents";
576
+ respond.send();
577
+ return;
578
+ }
579
+
580
+ var cookieManager =
581
+ Utils.getService("@mozilla.org/cookiemanager;1", "nsICookieManager2");
582
+
583
+ // The signature for "add" is different in firefox 3 and 2. We should sniff
584
+ // the browser version and call the right version of the method, but for now
585
+ // we'll use brute-force.
586
+ try {
587
+ cookieManager.add(cookie.domain, cookie.path, cookie.name, cookie.value,
588
+ cookie.secure, false, cookie.expiry);
589
+ } catch(e) {
590
+ cookieManager.add(cookie.domain, cookie.path, cookie.name, cookie.value,
591
+ cookie.secure, false, false, cookie.expiry);
592
+ }
593
+
594
+ respond.send();
595
+ };
596
+
597
+ function getVisibleCookies(location) {
598
+ var results = [];
599
+
600
+ var currentPath = location.pathname;
601
+ if (!currentPath) currentPath = "/";
602
+ var isForCurrentPath = function(aPath) {
603
+ return currentPath.indexOf(aPath) != -1;
604
+ };
605
+ var cm = Utils.getService("@mozilla.org/cookiemanager;1", "nsICookieManager");
606
+ var e = cm.enumerator;
607
+ while (e.hasMoreElements()) {
608
+ var cookie = e.getNext().QueryInterface(Components.interfaces["nsICookie"]);
609
+
610
+ // Take the hostname and progressively shorten it
611
+ var hostname = location.hostname;
612
+ do {
613
+ if ((cookie.host == "." + hostname || cookie.host == hostname)
614
+ && isForCurrentPath(cookie.path)) {
615
+ results.push(cookie);
616
+ break;
617
+ }
618
+ hostname = hostname.replace(/^.*?\./, "");
619
+ } while (hostname.indexOf(".") != -1);
620
+ }
621
+
622
+ return results;
623
+ };
624
+
625
+ FirefoxDriver.prototype.getCookie = function(respond) {
626
+ var cookieToString = function(c) {
627
+ return c.name + "=" + c.value + ";" + "domain=" + c.host + ";"
628
+ + "path=" + c.path + ";" + "expires=" + c.expires + ";"
629
+ + (c.isSecure ? "secure ;" : "");
630
+ };
631
+
632
+ var toReturn = "";
633
+ var cookies = getVisibleCookies(Utils.getBrowser(respond.context).
634
+ contentWindow.location);
635
+ for (var i = 0; i < cookies.length; i++) {
636
+ var toAdd = cookieToString(cookies[i]);
637
+ toReturn += toAdd + "\n";
638
+ }
639
+
640
+ respond.response = toReturn;
641
+ respond.send();
642
+ };
643
+
644
+
645
+ // This is damn ugly, but it turns out that just deleting a cookie from the document
646
+ // doesn't always do The Right Thing
647
+ FirefoxDriver.prototype.deleteCookie = function(respond, cookieString) {
648
+ var cm = Utils.getService("@mozilla.org/cookiemanager;1", "nsICookieManager");
649
+ // TODO(simon): Well, this is dumb. Sorry
650
+ var toDelete = eval('(' + cookieString + ')');
651
+
652
+ var cookies = getVisibleCookies(Utils.getBrowser(respond.context).
653
+ contentWindow.location);
654
+ for (var i = 0; i < cookies.length; i++) {
655
+ var cookie = cookies[i];
656
+ if (cookie.name == toDelete.name) {
657
+ cm.remove(cookie.host, cookie.name, cookie.path, false);
658
+ }
659
+ }
660
+
661
+ respond.send();
662
+ };
663
+
664
+
665
+ FirefoxDriver.prototype.deleteAllCookies = function(respond) {
666
+ var cm = Utils.getService("@mozilla.org/cookiemanager;1", "nsICookieManager");
667
+ var cookies = getVisibleCookies(Utils.getBrowser(respond.context).
668
+ contentWindow.location);
669
+
670
+ for (var i = 0; i < cookies.length; i++) {
671
+ var cookie = cookies[i];
672
+ cm.remove(cookie.host, cookie.name, cookie.path, false);
673
+ }
674
+
675
+ respond.send();
676
+ };
677
+
678
+
679
+ FirefoxDriver.prototype.setMouseSpeed = function(respond, speed) {
680
+ this.mouseSpeed = speed;
681
+ respond.send();
682
+ };
683
+
684
+
685
+ FirefoxDriver.prototype.getMouseSpeed = function(respond) {
686
+ respond.response = "" + this.mouseSpeed;
687
+ respond.send();
688
+ };
689
+
690
+
691
+ FirefoxDriver.prototype.saveScreenshot = function(respond, pngFile) {
692
+ var window = Utils.getBrowser(respond.context).contentWindow;
693
+ try {
694
+ var canvas = Screenshooter.grab(window);
695
+ try {
696
+ Screenshooter.save(canvas, pngFile);
697
+ } catch(e) {
698
+ respond.isError = true;
699
+ respond.response = 'Could not save screenshot to ' + pngFile + ' - ' + e;
700
+ }
701
+ } catch(e) {
702
+ respond.isError = true;
703
+ respond.response = 'Could not take screenshot of current page - ' + e;
704
+ }
705
+ respond.send();
706
+ };