rainux-selenium-webdriver 0.0.17

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 (192) hide show
  1. data/COPYING +204 -0
  2. data/chrome/prebuilt/Win32/Release/npchromedriver.dll +0 -0
  3. data/chrome/prebuilt/x64/Release/npchromedriver.dll +0 -0
  4. data/chrome/src/extension/background.html +9 -0
  5. data/chrome/src/extension/background.js +995 -0
  6. data/chrome/src/extension/content_script.js +1321 -0
  7. data/chrome/src/extension/icons/busy.png +0 -0
  8. data/chrome/src/extension/icons/free.png +0 -0
  9. data/chrome/src/extension/manifest-nonwin.json +19 -0
  10. data/chrome/src/extension/manifest-win.json +20 -0
  11. data/chrome/src/extension/utils.js +231 -0
  12. data/chrome/src/rb/lib/selenium/webdriver/chrome.rb +8 -0
  13. data/chrome/src/rb/lib/selenium/webdriver/chrome/bridge.rb +358 -0
  14. data/chrome/src/rb/lib/selenium/webdriver/chrome/command_executor.rb +124 -0
  15. data/chrome/src/rb/lib/selenium/webdriver/chrome/launcher.rb +135 -0
  16. data/common/src/js/abstractcommandprocessor.js +134 -0
  17. data/common/src/js/asserts.js +296 -0
  18. data/common/src/js/by.js +149 -0
  19. data/common/src/js/command.js +304 -0
  20. data/common/src/js/context.js +58 -0
  21. data/common/src/js/core/Blank.html +7 -0
  22. data/common/src/js/core/InjectedRemoteRunner.html +8 -0
  23. data/common/src/js/core/RemoteRunner.html +101 -0
  24. data/common/src/js/core/SeleniumLog.html +109 -0
  25. data/common/src/js/core/TestPrompt.html +145 -0
  26. data/common/src/js/core/TestRunner-splash.html +55 -0
  27. data/common/src/js/core/TestRunner.html +165 -0
  28. data/common/src/js/core/icons/all.png +0 -0
  29. data/common/src/js/core/icons/continue.png +0 -0
  30. data/common/src/js/core/icons/continue_disabled.png +0 -0
  31. data/common/src/js/core/icons/pause.png +0 -0
  32. data/common/src/js/core/icons/pause_disabled.png +0 -0
  33. data/common/src/js/core/icons/selected.png +0 -0
  34. data/common/src/js/core/icons/step.png +0 -0
  35. data/common/src/js/core/icons/step_disabled.png +0 -0
  36. data/common/src/js/core/lib/cssQuery/cssQuery-p.js +6 -0
  37. data/common/src/js/core/lib/cssQuery/src/cssQuery-level2.js +142 -0
  38. data/common/src/js/core/lib/cssQuery/src/cssQuery-level3.js +150 -0
  39. data/common/src/js/core/lib/cssQuery/src/cssQuery-standard.js +53 -0
  40. data/common/src/js/core/lib/cssQuery/src/cssQuery.js +356 -0
  41. data/common/src/js/core/lib/prototype.js +2006 -0
  42. data/common/src/js/core/lib/scriptaculous/builder.js +101 -0
  43. data/common/src/js/core/lib/scriptaculous/controls.js +815 -0
  44. data/common/src/js/core/lib/scriptaculous/dragdrop.js +915 -0
  45. data/common/src/js/core/lib/scriptaculous/effects.js +958 -0
  46. data/common/src/js/core/lib/scriptaculous/scriptaculous.js +47 -0
  47. data/common/src/js/core/lib/scriptaculous/slider.js +283 -0
  48. data/common/src/js/core/lib/scriptaculous/unittest.js +383 -0
  49. data/common/src/js/core/lib/snapsie.js +91 -0
  50. data/common/src/js/core/scripts/find_matching_child.js +69 -0
  51. data/common/src/js/core/scripts/htmlutils.js +8716 -0
  52. data/common/src/js/core/scripts/injection.html +72 -0
  53. data/common/src/js/core/scripts/selenium-api.js +3291 -0
  54. data/common/src/js/core/scripts/selenium-browserbot.js +2457 -0
  55. data/common/src/js/core/scripts/selenium-browserdetect.js +153 -0
  56. data/common/src/js/core/scripts/selenium-commandhandlers.js +379 -0
  57. data/common/src/js/core/scripts/selenium-executionloop.js +175 -0
  58. data/common/src/js/core/scripts/selenium-logging.js +148 -0
  59. data/common/src/js/core/scripts/selenium-remoterunner.js +695 -0
  60. data/common/src/js/core/scripts/selenium-testrunner.js +1362 -0
  61. data/common/src/js/core/scripts/selenium-version.js +5 -0
  62. data/common/src/js/core/scripts/ui-doc.html +808 -0
  63. data/common/src/js/core/scripts/ui-element.js +1644 -0
  64. data/common/src/js/core/scripts/ui-map-sample.js +979 -0
  65. data/common/src/js/core/scripts/user-extensions.js +3 -0
  66. data/common/src/js/core/scripts/user-extensions.js.sample +75 -0
  67. data/common/src/js/core/scripts/xmlextras.js +153 -0
  68. data/common/src/js/core/selenium-logo.png +0 -0
  69. data/common/src/js/core/selenium-test.css +43 -0
  70. data/common/src/js/core/selenium.css +316 -0
  71. data/common/src/js/core/xpath/dom.js +566 -0
  72. data/common/src/js/core/xpath/javascript-xpath-0.1.11.js +2816 -0
  73. data/common/src/js/core/xpath/util.js +549 -0
  74. data/common/src/js/core/xpath/xmltoken.js +149 -0
  75. data/common/src/js/core/xpath/xpath.js +2481 -0
  76. data/common/src/js/extension/README +2 -0
  77. data/common/src/js/extension/dommessenger.js +152 -0
  78. data/common/src/js/factory.js +55 -0
  79. data/common/src/js/future.js +141 -0
  80. data/common/src/js/jsunit.js +40 -0
  81. data/common/src/js/jsunit/app/css/jsUnitStyle.css +50 -0
  82. data/common/src/js/jsunit/app/css/readme +10 -0
  83. data/common/src/js/jsunit/app/emptyPage.html +11 -0
  84. data/common/src/js/jsunit/app/jsUnitCore.js +534 -0
  85. data/common/src/js/jsunit/app/jsUnitMockTimeout.js +81 -0
  86. data/common/src/js/jsunit/app/jsUnitTestManager.js +705 -0
  87. data/common/src/js/jsunit/app/jsUnitTestSuite.js +44 -0
  88. data/common/src/js/jsunit/app/jsUnitTracer.js +102 -0
  89. data/common/src/js/jsunit/app/jsUnitVersionCheck.js +59 -0
  90. data/common/src/js/jsunit/app/main-counts-errors.html +12 -0
  91. data/common/src/js/jsunit/app/main-counts-failures.html +13 -0
  92. data/common/src/js/jsunit/app/main-counts-runs.html +13 -0
  93. data/common/src/js/jsunit/app/main-counts.html +21 -0
  94. data/common/src/js/jsunit/app/main-data.html +178 -0
  95. data/common/src/js/jsunit/app/main-errors.html +23 -0
  96. data/common/src/js/jsunit/app/main-frame.html +19 -0
  97. data/common/src/js/jsunit/app/main-loader.html +45 -0
  98. data/common/src/js/jsunit/app/main-progress.html +25 -0
  99. data/common/src/js/jsunit/app/main-results.html +67 -0
  100. data/common/src/js/jsunit/app/main-status.html +13 -0
  101. data/common/src/js/jsunit/app/testContainer.html +16 -0
  102. data/common/src/js/jsunit/app/testContainerController.html +77 -0
  103. data/common/src/js/jsunit/app/xbDebug.js +306 -0
  104. data/common/src/js/jsunit/changelog.txt +60 -0
  105. data/common/src/js/jsunit/css/jsUnitStyle.css +83 -0
  106. data/common/src/js/jsunit/images/green.gif +0 -0
  107. data/common/src/js/jsunit/images/logo_jsunit.gif +0 -0
  108. data/common/src/js/jsunit/images/powerby-transparent.gif +0 -0
  109. data/common/src/js/jsunit/images/red.gif +0 -0
  110. data/common/src/js/jsunit/licenses/JDOM_license.txt +56 -0
  111. data/common/src/js/jsunit/licenses/Jetty_license.html +213 -0
  112. data/common/src/js/jsunit/licenses/MPL-1.1.txt +470 -0
  113. data/common/src/js/jsunit/licenses/gpl-2.txt +340 -0
  114. data/common/src/js/jsunit/licenses/index.html +141 -0
  115. data/common/src/js/jsunit/licenses/lgpl-2.1.txt +504 -0
  116. data/common/src/js/jsunit/licenses/mpl-tri-license-c.txt +35 -0
  117. data/common/src/js/jsunit/licenses/mpl-tri-license-html.txt +35 -0
  118. data/common/src/js/jsunit/readme.txt +19 -0
  119. data/common/src/js/jsunit/testRunner.html +167 -0
  120. data/common/src/js/jsunit/version.txt +1 -0
  121. data/common/src/js/key.js +117 -0
  122. data/common/src/js/localcommandprocessor.js +185 -0
  123. data/common/src/js/testcase.js +217 -0
  124. data/common/src/js/timing.js +89 -0
  125. data/common/src/js/webdriver.js +890 -0
  126. data/common/src/js/webelement.js +485 -0
  127. data/common/src/rb/README +30 -0
  128. data/common/src/rb/lib/selenium-webdriver.rb +1 -0
  129. data/common/src/rb/lib/selenium/webdriver.rb +67 -0
  130. data/common/src/rb/lib/selenium/webdriver/bridge_helper.rb +91 -0
  131. data/common/src/rb/lib/selenium/webdriver/child_process.rb +180 -0
  132. data/common/src/rb/lib/selenium/webdriver/core_ext/dir.rb +41 -0
  133. data/common/src/rb/lib/selenium/webdriver/driver.rb +252 -0
  134. data/common/src/rb/lib/selenium/webdriver/driver_extensions/takes_screenshot.rb +24 -0
  135. data/common/src/rb/lib/selenium/webdriver/element.rb +262 -0
  136. data/common/src/rb/lib/selenium/webdriver/error.rb +67 -0
  137. data/common/src/rb/lib/selenium/webdriver/find.rb +89 -0
  138. data/common/src/rb/lib/selenium/webdriver/keys.rb +84 -0
  139. data/common/src/rb/lib/selenium/webdriver/navigation.rb +27 -0
  140. data/common/src/rb/lib/selenium/webdriver/options.rb +50 -0
  141. data/common/src/rb/lib/selenium/webdriver/platform.rb +86 -0
  142. data/common/src/rb/lib/selenium/webdriver/target_locator.rb +70 -0
  143. data/firefox/prebuilt/Win32/Release/webdriver-firefox.dll +0 -0
  144. data/firefox/prebuilt/linux/Release/libwebdriver-firefox.so +0 -0
  145. data/firefox/prebuilt/linux/Release/x_ignore_nofocus.so +0 -0
  146. data/firefox/prebuilt/linux64/Release/libwebdriver-firefox.so +0 -0
  147. data/firefox/prebuilt/linux64/Release/x_ignore_nofocus.so +0 -0
  148. data/firefox/prebuilt/nsICommandProcessor.xpt +0 -0
  149. data/firefox/prebuilt/nsINativeEvents.xpt +0 -0
  150. data/firefox/prebuilt/nsIResponseHandler.xpt +0 -0
  151. data/firefox/src/extension/chrome.manifest +3 -0
  152. data/firefox/src/extension/components/badCertListener.js +294 -0
  153. data/firefox/src/extension/components/context.js +37 -0
  154. data/firefox/src/extension/components/driver-component.js +127 -0
  155. data/firefox/src/extension/components/firefoxDriver.js +810 -0
  156. data/firefox/src/extension/components/json2.js +273 -0
  157. data/firefox/src/extension/components/keytest.html +554 -0
  158. data/firefox/src/extension/components/nsCommandProcessor.js +643 -0
  159. data/firefox/src/extension/components/promptService.js +208 -0
  160. data/firefox/src/extension/components/screenshooter.js +81 -0
  161. data/firefox/src/extension/components/socketListener.js +185 -0
  162. data/firefox/src/extension/components/utils.js +1263 -0
  163. data/firefox/src/extension/components/webLoadingListener.js +57 -0
  164. data/firefox/src/extension/components/webdriverserver.js +106 -0
  165. data/firefox/src/extension/components/wrappedElement.js +683 -0
  166. data/firefox/src/extension/content/fxdriver.xul +30 -0
  167. data/firefox/src/extension/content/server.js +95 -0
  168. data/firefox/src/extension/idl/nsICommandProcessor.idl +38 -0
  169. data/firefox/src/extension/idl/nsIResponseHandler.idl +34 -0
  170. data/firefox/src/extension/install.rdf +29 -0
  171. data/firefox/src/rb/lib/selenium/webdriver/firefox.rb +31 -0
  172. data/firefox/src/rb/lib/selenium/webdriver/firefox/binary.rb +107 -0
  173. data/firefox/src/rb/lib/selenium/webdriver/firefox/bridge.rb +484 -0
  174. data/firefox/src/rb/lib/selenium/webdriver/firefox/extension_connection.rb +90 -0
  175. data/firefox/src/rb/lib/selenium/webdriver/firefox/launcher.rb +155 -0
  176. data/firefox/src/rb/lib/selenium/webdriver/firefox/profile.rb +233 -0
  177. data/firefox/src/rb/lib/selenium/webdriver/firefox/profiles_ini.rb +59 -0
  178. data/firefox/src/rb/lib/selenium/webdriver/firefox/util.rb +23 -0
  179. data/jobbie/prebuilt/Win32/Release/InternetExplorerDriver.dll +0 -0
  180. data/jobbie/prebuilt/x64/Release/InternetExplorerDriver.dll +0 -0
  181. data/jobbie/src/rb/lib/selenium/webdriver/ie.rb +14 -0
  182. data/jobbie/src/rb/lib/selenium/webdriver/ie/bridge.rb +565 -0
  183. data/jobbie/src/rb/lib/selenium/webdriver/ie/lib.rb +99 -0
  184. data/jobbie/src/rb/lib/selenium/webdriver/ie/util.rb +147 -0
  185. data/remote/client/src/rb/lib/selenium/webdriver/remote.rb +16 -0
  186. data/remote/client/src/rb/lib/selenium/webdriver/remote/bridge.rb +408 -0
  187. data/remote/client/src/rb/lib/selenium/webdriver/remote/capabilities.rb +105 -0
  188. data/remote/client/src/rb/lib/selenium/webdriver/remote/commands.rb +53 -0
  189. data/remote/client/src/rb/lib/selenium/webdriver/remote/default_http_client.rb +71 -0
  190. data/remote/client/src/rb/lib/selenium/webdriver/remote/response.rb +49 -0
  191. data/remote/client/src/rb/lib/selenium/webdriver/remote/server_error.rb +32 -0
  192. metadata +303 -0
@@ -0,0 +1,37 @@
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
+ function Context(windowId, frameId) {
20
+ this.windowId = windowId;
21
+
22
+ if (typeof frameId == 'number' || (typeof frameId == 'string' && frameId)) {
23
+ this.frameId = frameId;
24
+ }
25
+ }
26
+
27
+
28
+ Context.fromString = function(text) {
29
+ var bits = text.split(" ");
30
+ return new Context(bits[0], bits[1]);
31
+ };
32
+
33
+
34
+ Context.prototype.toString = function() {
35
+ return this.windowId + " " +
36
+ (this.frameId !== undefined ? this.frameId.toString() : "");
37
+ };
@@ -0,0 +1,127 @@
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
+ // constants
20
+ const nsISupports = Components.interfaces.nsISupports;
21
+ const CLASS_ID = Components.ID("{1C0E8D86-B661-40d0-AE3D-CA012FADF170}");
22
+ const CLASS_NAME = "Firefox WebDriver";
23
+ const CONTRACT_ID = "@googlecode.com/webdriver/fxdriver;1";
24
+
25
+ // The following code is derived from https://addons.mozilla.org/en-US/firefox/files/browse/3682/
26
+ // Its copyrights belong to its original author.
27
+
28
+ var ExternalScripts = [
29
+ "context.js",
30
+ "firefoxDriver.js",
31
+ "socketListener.js",
32
+ "utils.js",
33
+ "webdriverserver.js",
34
+ "webLoadingListener.js",
35
+ "wrappedElement.js",
36
+ "screenshooter.js"
37
+ ];
38
+
39
+
40
+ (function() {
41
+ var self;
42
+ var fileProtocolHandler = Components.
43
+ classes['@mozilla.org/network/protocol;1?name=file'].
44
+ createInstance(Components.interfaces.nsIFileProtocolHandler);
45
+ self = __LOCATION__;
46
+
47
+ var parent = self.parent;
48
+ // the directory this file is in
49
+ var loader = Components.classes['@mozilla.org/moz/jssubscript-loader;1'].
50
+ createInstance(Components.interfaces.mozIJSSubScriptLoader);
51
+
52
+ // Firefox 3.5+ has native JSON support; prefer that over our script from
53
+ // www.json.org, which may be slower.
54
+ var appInfo = Components.classes['@mozilla.org/xre/app-info;1'].
55
+ getService(Components.interfaces.nsIXULAppInfo);
56
+ var versionChecker = Components.classes['@mozilla.org/xpcom/version-comparator;1'].
57
+ getService(Components.interfaces.nsIVersionComparator);
58
+ if (versionChecker.compare(appInfo.version, '3.5') < 0) {
59
+ ExternalScripts.push('json2.js');
60
+ }
61
+
62
+ for (var index in ExternalScripts) {
63
+ var child = parent.clone();
64
+ child.append(ExternalScripts[index]);
65
+ // child is a nsILocalFile of the file we want to load
66
+ var childname = fileProtocolHandler.getURLSpecFromFile(child);
67
+ loader.loadSubScript(childname);
68
+ }
69
+ })();
70
+
71
+
72
+ // This code has been derived from the example code at
73
+ // http://developer-stage.mozilla.org/en/docs/How_to_Build_an_XPCOM_Component_in_Javascript
74
+ // Its copyrights belong to the original author
75
+
76
+ var ServerFactory = {
77
+ createInstance: function (aOuter, aIID) {
78
+ if (aOuter != null)
79
+ throw Components.results.NS_ERROR_NO_AGGREGATION;
80
+ if (!this.server)
81
+ this.server = new WebDriverServer();
82
+ return (this.server).QueryInterface(aIID);
83
+ }
84
+ };
85
+
86
+
87
+ //module definition (xpcom registration)
88
+ var ServerModule = {
89
+ firstTime_: true,
90
+
91
+ registerSelf: function(aCompMgr, aFileSpec, aLocation, aType) {
92
+ if (this.firstTime_) {
93
+ this.firstTime_ = false;
94
+ throw Components.results.NS_ERROR_FACTORY_REGISTER_AGAIN;
95
+ }
96
+ aCompMgr =
97
+ aCompMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
98
+ aCompMgr.registerFactoryLocation(
99
+ CLASS_ID, CLASS_NAME, CONTRACT_ID, aFileSpec, aLocation, aType);
100
+ },
101
+
102
+ unregisterSelf: function(aCompMgr, aLocation, aType) {
103
+ aCompMgr =
104
+ aCompMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
105
+ aCompMgr.unregisterFactoryLocation(CLASS_ID, aLocation);
106
+ },
107
+
108
+ getClassObject: function(aCompMgr, aCID, aIID) {
109
+ if (!aIID.equals(Components.interfaces.nsIFactory))
110
+ throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
111
+
112
+ if (aCID.equals(CLASS_ID))
113
+ return ServerFactory;
114
+
115
+ throw Components.results.NS_ERROR_NO_INTERFACE;
116
+ },
117
+
118
+ canUnload: function(aCompMgr) {
119
+ return true;
120
+ }
121
+ };
122
+
123
+
124
+ //module initialization
125
+ function NSGetModule(aCompMgr, aFileSpec) {
126
+ return ServerModule;
127
+ }
@@ -0,0 +1,810 @@
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
+ respond.response = Utils.wrapResult(result, respond.context);
150
+
151
+ } catch (e) {
152
+ respond.isError = true;
153
+ respond.response = e;
154
+ }
155
+ respond.send();
156
+ };
157
+
158
+
159
+ FirefoxDriver.prototype.getCurrentUrl = function(respond) {
160
+ var url = Utils.getDocument(respond.context).defaultView.location;
161
+ if (!url) {
162
+ url = Utils.getBrowser(respond.context).contentWindow.location;
163
+ }
164
+ respond.response = "" + url;
165
+ respond.send();
166
+ };
167
+
168
+
169
+ FirefoxDriver.prototype.title = function(respond) {
170
+ var browser = Utils.getBrowser(respond.context);
171
+ respond.response = browser.contentTitle;
172
+ respond.send();
173
+ };
174
+
175
+
176
+ FirefoxDriver.prototype.getPageSource = function(respond) {
177
+ var source = Utils.getDocument(respond.context).
178
+ getElementsByTagName("html")[0].innerHTML;
179
+
180
+ respond.response = "<html>" + source + "</html>";
181
+ respond.send();
182
+ };
183
+
184
+ var normalizeXPath = function(xpath, opt_contextNode) {
185
+ if (opt_contextNode && xpath) {
186
+ var parentXPath = Utils.getXPathOfElement(opt_contextNode);
187
+ if (parentXPath && parentXPath.length > 0) {
188
+ if (xpath[0] != '/' && xpath[0] != '(') {
189
+ return parentXPath + "/" + xpath;
190
+ } else {
191
+ return parentXPath + xpath;
192
+ }
193
+ }
194
+ }
195
+ return xpath;
196
+ };
197
+
198
+
199
+ /**
200
+ * Searches for the first element in {@code theDocument} matching the given
201
+ * {@code xpath} expression.
202
+ * @param {nsIDOMDocument} theDocument The document to search in.
203
+ * @param {string} xpath The XPath expression to evaluate.
204
+ * @param {nsIDOMNode} opt_contextNode The context node for the query; defaults
205
+ * to {@code theDocument}.
206
+ * @return {nsIDOMNode} The first matching node.
207
+ * @private
208
+ */
209
+ FirefoxDriver.prototype.findElementByXPath_ = function(theDocument, xpath,
210
+ opt_contextNode) {
211
+ var contextNode = theDocument;
212
+ if (opt_contextNode) {
213
+ contextNode = opt_contextNode;
214
+ xpath = normalizeXPath(xpath, opt_contextNode);
215
+ }
216
+ return theDocument.evaluate(xpath, contextNode, null,
217
+ Components.interfaces.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE, null).
218
+ singleNodeValue;
219
+ };
220
+
221
+
222
+ /**
223
+ * Searches for elements matching the given {@code xpath} expression in the
224
+ * specified document.
225
+ * @param {nsIDOMDocument} theDocument The document to search in.
226
+ * @param {string} xpath The XPath expression to evaluate.
227
+ * @param {nsIDOMNode} opt_contextNode The context node for the query; defaults
228
+ * to {@code theDocument}.
229
+ * @return {Array.<nsIDOMNode>} The matching nodes.
230
+ * @private
231
+ */
232
+ FirefoxDriver.prototype.findElementsByXPath_ = function(theDocument, xpath,
233
+ opt_contextNode) {
234
+ var contextNode = theDocument;
235
+ if (opt_contextNode) {
236
+ contextNode = opt_contextNode;
237
+ xpath = normalizeXPath(xpath, opt_contextNode);
238
+ }
239
+ var result = theDocument.evaluate(xpath, contextNode, null,
240
+ Components.interfaces.nsIDOMXPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
241
+ var elements = [];
242
+ var element = result.iterateNext();
243
+ while (element) {
244
+ elements.push(element);
245
+ element = result.iterateNext();
246
+ }
247
+ return elements;
248
+ };
249
+
250
+
251
+ /**
252
+ * Searches for the first element in {@code theDocument} using the given
253
+ * {@code Javascript} expression or {@code Javascript} code.
254
+ * @param {nsIDOMDocument} theDocument The document to search in.
255
+ * @param {string} javascript The Javascript expression or code to evaluate.
256
+ * @param {nsIDOMNode} opt_contextNode The context node for the query; defaults
257
+ * to {@code theDocument}.
258
+ * @param {boolean} js_expr Indicate if the javascript is a simple expression
259
+ * or bunch line of code.
260
+ * @return {nsIDOMNode} The first matching node.
261
+ * @private
262
+ */
263
+ FirefoxDriver.prototype.findElementByJavascript = function(theDocument, javascript, opt_contextNode, js_expr) {
264
+
265
+ if (js_expr) {
266
+ javascript = 'return this.' + javascript + ';';
267
+ }
268
+
269
+ var fn = new Function('window', javascript);
270
+
271
+ return fn.apply(theDocument.defaultView.wrappedJSObject, [
272
+ theDocument.defaultView.wrappedJSObject.window,
273
+ ]);
274
+ };
275
+
276
+
277
+ /**
278
+ * An enumeration of the supported element locator methods.
279
+ * @enum {string}
280
+ */
281
+ FirefoxDriver.ElementLocator = {
282
+ ID: 'id',
283
+ NAME: 'name',
284
+ CLASS_NAME: 'class name',
285
+ CSS_SELECTOR: 'css selector',
286
+ TAG_NAME: 'tag name',
287
+ LINK_TEXT: 'link text',
288
+ PARTIAL_LINK_TEXT: 'partial link text',
289
+ XPATH: 'xpath',
290
+ JS_EXPR: 'js expr',
291
+ JAVASCRIPT: 'javascript'
292
+ };
293
+
294
+
295
+ /**
296
+ * Finds an element on the current page. The response value will be the UUID of
297
+ * the located element, or an error message if an element could not be found.
298
+ * @param {Response} respond Object to send the command response with.
299
+ * @param {FirefoxDriver.ElementLocator} method The locator method to use.
300
+ * @param {string} selector What to search for; see {@code ElementLocator} for
301
+ * details on what the selector should be for each element.
302
+ * @param {string} opt_parentElementId If defined, the search will be restricted
303
+ * to the corresponding element's subtree.
304
+ * @private
305
+ */
306
+ FirefoxDriver.prototype.findElementInternal_ = function(respond, method,
307
+ selector,
308
+ opt_parentElementId) {
309
+ var theDocument = Utils.getDocument(respond.context);
310
+ var rootNode = typeof opt_parentElementId == 'string' ?
311
+ Utils.getElementAt(opt_parentElementId, respond.context) : theDocument;
312
+
313
+ var element;
314
+ switch (method) {
315
+ case FirefoxDriver.ElementLocator.ID:
316
+ element = rootNode === theDocument ?
317
+ theDocument.getElementById(selector) :
318
+ this.findElementByXPath_(
319
+ theDocument, './/*[@id="' + selector + '"]', rootNode);
320
+ break;
321
+
322
+ case FirefoxDriver.ElementLocator.NAME:
323
+ element = rootNode.getElementsByName ?
324
+ rootNode.getElementsByName(selector)[0] :
325
+ this.findElementByXPath_(
326
+ theDocument, './/*[@name ="' + selector + '"]', rootNode);
327
+ break;
328
+
329
+ case FirefoxDriver.ElementLocator.CLASS_NAME:
330
+ element = rootNode.getElementsByClassName ?
331
+ rootNode.getElementsByClassName(selector)[0] : // FF 3+
332
+ this.findElementByXPath_(theDocument, // FF 2
333
+ '//*[contains(concat(" ",normalize-space(@class)," ")," ' +
334
+ selector + ' ")]', rootNode);
335
+ break;
336
+
337
+ case FirefoxDriver.ElementLocator.CSS_SELECTOR:
338
+ if (rootNode['querySelector']) {
339
+ element = rootNode.querySelector(selector);
340
+ } else {
341
+ respond.isError = true;
342
+ respond.response = "CSS Selectors not supported natively";
343
+ respond.send();
344
+ }
345
+ break;
346
+
347
+ case FirefoxDriver.ElementLocator.TAG_NAME:
348
+ element = rootNode.getElementsByTagName(selector)[0];
349
+ break;
350
+
351
+ case FirefoxDriver.ElementLocator.XPATH:
352
+ element = this.findElementByXPath_(theDocument, selector, rootNode);
353
+ break;
354
+
355
+ case FirefoxDriver.ElementLocator.LINK_TEXT:
356
+ case FirefoxDriver.ElementLocator.PARTIAL_LINK_TEXT:
357
+ var allLinks = rootNode.getElementsByTagName('A');
358
+ for (var i = 0; i < allLinks.length && !element; i++) {
359
+ var text = Utils.getText(allLinks[i], true);
360
+ if (FirefoxDriver.ElementLocator.PARTIAL_LINK_TEXT == method) {
361
+ if (text.indexOf(selector) != -1) {
362
+ element = allLinks[i];
363
+ }
364
+ } else if (text == selector) {
365
+ element = allLinks[i];
366
+ }
367
+ }
368
+ break;
369
+
370
+ case FirefoxDriver.ElementLocator.JS_EXPR:
371
+ element = this.findElementByJavascript(theDocument, selector, rootNode, true);
372
+ break;
373
+
374
+ case FirefoxDriver.ElementLocator.JAVASCRIPT:
375
+ element = this.findElementByJavascript(theDocument, selector, rootNode, false);
376
+ break;
377
+
378
+ default:
379
+ respond.response = 'Unsupported element locator method: ' + method;
380
+ respond.isError = true;
381
+ respond.send();
382
+ return;
383
+ }
384
+
385
+ if (element) {
386
+ respond.response = Utils.addToKnownElements(element, respond.context);
387
+ } else {
388
+ respond.response = 'Unable to locate element: ' + JSON.stringify({
389
+ method: method,
390
+ selector: selector
391
+ });
392
+ respond.isError = true;
393
+ }
394
+ respond.send();
395
+ };
396
+
397
+
398
+ /**
399
+ * Finds an element on the current page. The response value will be the UUID of
400
+ * the located element, or an error message if an element could not be found.
401
+ * @param {Response} respond Object to send the command response with.
402
+ * @param {Array.<string>} parameters A two-element array: the first element
403
+ * should be a method listen in the {@code Firefox.ElementLocator} enum, and
404
+ * the second should be what to search for.
405
+ */
406
+ FirefoxDriver.prototype.findElement = function(respond, parameters) {
407
+ this.findElementInternal_(respond, parameters[0], parameters[1]);
408
+ };
409
+
410
+
411
+ /**
412
+ * Finds an element on the current page that is the child of a corresponding
413
+ * search parameter. The response value will be the UUID of the located element,
414
+ * or an error message if an element could not be found.
415
+ * @param {Response} respond Object to send the command response with.
416
+ * @param {Array.<{id:string, using:string, value:string}>} parameters A single
417
+ * element array. The array element should define what to search for with
418
+ * the following fields:
419
+ * - id: UUID of the element to base the search from.
420
+ * - using: A method to search with, as defined in the
421
+ * {@code Firefox.ElementLocator} enum.
422
+ * - value: What to search for.
423
+ */
424
+ FirefoxDriver.prototype.findChildElement = function(respond, parameters) {
425
+ var map = parameters[0];
426
+ this.findElementInternal_(respond, map.using, map.value, map.id);
427
+ };
428
+
429
+
430
+ /**
431
+ * Finds elements on the current page. The response value will an array of UUIDs
432
+ * for the located elements.
433
+ * @param {Response} respond Object to send the command response with.
434
+ * @param {FirefoxDriver.ElementLocator} method The locator method to use.
435
+ * @param {string} selector What to search for; see {@code ElementLocator} for
436
+ * details on what the selector should be for each element.
437
+ * @param {string} opt_parentElementId If defined, the search will be restricted
438
+ * to the corresponding element's subtree.
439
+ * @private
440
+ */
441
+ FirefoxDriver.prototype.findElementsInternal_ = function(respond, method,
442
+ selector,
443
+ opt_parentElementId) {
444
+ var theDocument = Utils.getDocument(respond.context);
445
+ var rootNode = typeof opt_parentElementId == 'string' ?
446
+ Utils.getElementAt(opt_parentElementId, respond.context) : theDocument;
447
+
448
+ var elements;
449
+ switch (method) {
450
+ case FirefoxDriver.ElementLocator.ID:
451
+ selector = './/*[@id="' + selector + '"]';
452
+ // Fall-through
453
+ case FirefoxDriver.ElementLocator.XPATH:
454
+ elements = this.findElementsByXPath_(
455
+ theDocument, selector, rootNode);
456
+ break;
457
+
458
+ case FirefoxDriver.ElementLocator.NAME:
459
+ elements = rootNode.getElementsByName ?
460
+ rootNode.getElementsByName(selector) :
461
+ this.findElementsByXPath_(
462
+ theDocument, './/*[@name="' + selector + '"]', rootNode);
463
+ break;
464
+
465
+ case FirefoxDriver.ElementLocator.CSS_SELECTOR:
466
+ if (rootNode['querySelector']) {
467
+ elements = rootNode.querySelectorAll(selector);
468
+ } else {
469
+ respond.isError = true;
470
+ respond.response = "CSS Selectors not supported natively";
471
+ respond.send();
472
+ }
473
+ break;
474
+
475
+ case FirefoxDriver.ElementLocator.TAG_NAME:
476
+ elements = rootNode.getElementsByTagName(selector);
477
+ break;
478
+
479
+ case FirefoxDriver.ElementLocator.CLASS_NAME:
480
+ elements = rootNode.getElementsByClassName ?
481
+ rootNode.getElementsByClassName(selector) : // FF 3+
482
+ this.findElementsByXPath_(theDocument, // FF 2
483
+ './/*[contains(concat(" ",normalize-space(@class)," ")," ' +
484
+ selector + ' ")]', rootNode);
485
+ break;
486
+
487
+ case FirefoxDriver.ElementLocator.LINK_TEXT:
488
+ case FirefoxDriver.ElementLocator.PARTIAL_LINK_TEXT:
489
+ elements = rootNode.getElementsByTagName('A');
490
+ elements = Array.filter(elements, function(element) {
491
+ var text = Utils.getText(element, true);
492
+ if (FirefoxDriver.ElementLocator.PARTIAL_LINK_TEXT == method) {
493
+ return text.indexOf(selector) != -1;
494
+ } else {
495
+ return text == selector;
496
+ }
497
+ });
498
+ break;
499
+
500
+ default:
501
+ respond.response = 'Unsupported element locator method: ' + method;
502
+ respond.isError = true;
503
+ respond.send();
504
+ return;
505
+ }
506
+
507
+ var elementIds = [];
508
+ for (var j = 0; j < elements.length; j++) {
509
+ var element = elements[j];
510
+ elementIds.push(Utils.addToKnownElements(element, respond.context));
511
+ }
512
+
513
+ respond.response = elementIds;
514
+ respond.send();
515
+ };
516
+
517
+
518
+ /**
519
+ * Searches for multiple elements on the page. The response value will be an
520
+ * array of UUIDs for the located elements.
521
+ * @param {Response} respond Object to send the command response with.
522
+ * @param {Array.<string>} parameters A two-element array: the first element
523
+ * should be the type of locator strategy to use, the second is the target
524
+ * of the search.
525
+ */
526
+ FirefoxDriver.prototype.findElements = function(respond, parameters) {
527
+ this.findElementsInternal_(respond, parameters[0], parameters[1]);
528
+ };
529
+
530
+
531
+ /**
532
+ * Searches for multiple elements on the page that are children of the
533
+ * corresponding search parameter. The response value will be an array of UUIDs
534
+ * for the located elements.
535
+ * @param {Array.<{id:string, using:string, value:string}>} parameters A single
536
+ * element array. The array element should define what to search for with
537
+ * the following fields:
538
+ * - id: UUID of the element to base the search from.
539
+ * - using: A method to search with, as defined in the
540
+ * {@code Firefox.ElementLocator} enum.
541
+ * - value: What to search for.
542
+ */
543
+ FirefoxDriver.prototype.findChildElements = function(respond, parameters) {
544
+ var map = parameters[0];
545
+ this.findElementsInternal_(respond, map.using, map.value, map.id);
546
+ };
547
+
548
+
549
+ FirefoxDriver.prototype.switchToFrame = function(respond, frameId) {
550
+ var browser = Utils.getBrowser(respond.context);
551
+ var frameDoc = Utils.findDocumentInFrame(browser, frameId[0]);
552
+
553
+ if (frameDoc) {
554
+ respond.context = new Context(respond.context.windowId, frameId[0]);
555
+ respond.send();
556
+ } else {
557
+ respond.isError = true;
558
+ respond.response = "Cannot find frame with id: " + frameId.toString();
559
+ respond.send();
560
+ }
561
+ };
562
+
563
+
564
+ FirefoxDriver.prototype.switchToDefaultContent = function(respond) {
565
+ respond.context.frameId = "?";
566
+ respond.send();
567
+ };
568
+
569
+
570
+ FirefoxDriver.prototype.switchToActiveElement = function(respond) {
571
+ var element = Utils.getActiveElement(respond.context);
572
+
573
+ respond.response = Utils.addToKnownElements(element, respond.context);
574
+ respond.send();
575
+ };
576
+
577
+
578
+ FirefoxDriver.prototype.goBack = function(respond) {
579
+ var browser = Utils.getBrowser(respond.context);
580
+
581
+ if (browser.canGoBack) {
582
+ browser.goBack();
583
+ }
584
+
585
+ respond.send();
586
+ };
587
+
588
+
589
+ FirefoxDriver.prototype.goForward = function(respond) {
590
+ var browser = Utils.getBrowser(respond.context);
591
+
592
+ if (browser.canGoForward) {
593
+ browser.goForward();
594
+ }
595
+
596
+ respond.send();
597
+ };
598
+
599
+
600
+ FirefoxDriver.prototype.refresh = function(respond) {
601
+ var browser = Utils.getBrowser(respond.context);
602
+ browser.contentWindow.location.reload(true);
603
+ // Wait for the reload to finish before sending the response.
604
+ new WebLoadingListener(browser, function() {
605
+ // Reset to the top frame.
606
+ respond.context.frameId = "?";
607
+ respond.send();
608
+ });
609
+ };
610
+
611
+
612
+ FirefoxDriver.prototype.addCookie = function(respond, cookieString) {
613
+ var cookie;
614
+ cookie = eval('(' + cookieString[0] + ')');
615
+
616
+ if (cookie.expiry) {
617
+ cookie.expiry = new Date(cookie.expiry);
618
+ } else {
619
+ var date = new Date();
620
+ date.setYear(2030);
621
+ cookie.expiry = date;
622
+ }
623
+
624
+ cookie.expiry = cookie.expiry.getTime() / 1000; // Stored in seconds
625
+
626
+ if (!cookie.domain) {
627
+ var location = Utils.getBrowser(respond.context).contentWindow.location;
628
+ cookie.domain = location.hostname;
629
+ } else {
630
+ var currLocation = Utils.getBrowser(respond.context).contentWindow.location;
631
+ var currDomain = currLocation.host;
632
+ if (currDomain.indexOf(cookie.domain) == -1) { // Not quite right, but close enough
633
+ respond.isError = true;
634
+ respond.response = "You may only set cookies for the current domain";
635
+ respond.send();
636
+ return;
637
+ }
638
+ }
639
+
640
+ // The cookie's domain may include a port. Which is bad. Remove it
641
+ // We'll catch ip6 addresses by mistake. Since no-one uses those
642
+ // this will be okay for now.
643
+ if (cookie.domain.match(/:\d+$/)) {
644
+ cookie.domain = cookie.domain.replace(/:\d+$/, "");
645
+ }
646
+
647
+ var document = Utils.getDocument(respond.context);
648
+ if (!document || !document.contentType.match(/html/i)) {
649
+ respond.isError = true;
650
+ respond.response = "You may only set cookies on html documents";
651
+ respond.send();
652
+ return;
653
+ }
654
+
655
+ var cookieManager =
656
+ Utils.getService("@mozilla.org/cookiemanager;1", "nsICookieManager2");
657
+
658
+ // The signature for "add" is different in firefox 3 and 2. We should sniff
659
+ // the browser version and call the right version of the method, but for now
660
+ // we'll use brute-force.
661
+ try {
662
+ cookieManager.add(cookie.domain, cookie.path, cookie.name, cookie.value,
663
+ cookie.secure, false, cookie.expiry);
664
+ } catch(e) {
665
+ cookieManager.add(cookie.domain, cookie.path, cookie.name, cookie.value,
666
+ cookie.secure, false, false, cookie.expiry);
667
+ }
668
+
669
+ respond.send();
670
+ };
671
+
672
+ function getVisibleCookies(location) {
673
+ var results = [];
674
+
675
+ var currentPath = location.pathname;
676
+ if (!currentPath) currentPath = "/";
677
+ var isForCurrentPath = function(aPath) {
678
+ return currentPath.indexOf(aPath) != -1;
679
+ };
680
+ var cm = Utils.getService("@mozilla.org/cookiemanager;1", "nsICookieManager");
681
+ var e = cm.enumerator;
682
+ while (e.hasMoreElements()) {
683
+ var cookie = e.getNext().QueryInterface(Components.interfaces["nsICookie"]);
684
+
685
+ // Take the hostname and progressively shorten it
686
+ var hostname = location.hostname;
687
+ do {
688
+ if ((cookie.host == "." + hostname || cookie.host == hostname)
689
+ && isForCurrentPath(cookie.path)) {
690
+ results.push(cookie);
691
+ break;
692
+ }
693
+ hostname = hostname.replace(/^.*?\./, "");
694
+ } while (hostname.indexOf(".") != -1);
695
+ }
696
+
697
+ return results;
698
+ };
699
+
700
+ FirefoxDriver.prototype.getCookie = function(respond) {
701
+ var cookieToString = function(c) {
702
+ return c.name + "=" + c.value + ";" + "domain=" + c.host + ";"
703
+ + "path=" + c.path + ";" + "expires=" + c.expires + ";"
704
+ + (c.isSecure ? "secure ;" : "");
705
+ };
706
+
707
+ var toReturn = [];
708
+ var cookies = getVisibleCookies(Utils.getBrowser(respond.context).
709
+ contentWindow.location);
710
+ for (var i = 0; i < cookies.length; i++) {
711
+ toReturn.push(cookieToString(cookies[i]));
712
+ }
713
+
714
+ respond.response = toReturn;
715
+ respond.send();
716
+ };
717
+
718
+
719
+ // This is damn ugly, but it turns out that just deleting a cookie from the document
720
+ // doesn't always do The Right Thing
721
+ FirefoxDriver.prototype.deleteCookie = function(respond, cookieString) {
722
+ var cm = Utils.getService("@mozilla.org/cookiemanager;1", "nsICookieManager");
723
+ // TODO(simon): Well, this is dumb. Sorry
724
+ var toDelete = eval('(' + cookieString + ')');
725
+
726
+ var cookies = getVisibleCookies(Utils.getBrowser(respond.context).
727
+ contentWindow.location);
728
+ for (var i = 0; i < cookies.length; i++) {
729
+ var cookie = cookies[i];
730
+ if (cookie.name == toDelete.name) {
731
+ cm.remove(cookie.host, cookie.name, cookie.path, false);
732
+ }
733
+ }
734
+
735
+ respond.send();
736
+ };
737
+
738
+
739
+ FirefoxDriver.prototype.deleteAllCookies = function(respond) {
740
+ var cm = Utils.getService("@mozilla.org/cookiemanager;1", "nsICookieManager");
741
+ var cookies = getVisibleCookies(Utils.getBrowser(respond.context).
742
+ contentWindow.location);
743
+
744
+ for (var i = 0; i < cookies.length; i++) {
745
+ var cookie = cookies[i];
746
+ cm.remove(cookie.host, cookie.name, cookie.path, false);
747
+ }
748
+
749
+ respond.send();
750
+ };
751
+
752
+
753
+ FirefoxDriver.prototype.setMouseSpeed = function(respond, speed) {
754
+ this.mouseSpeed = speed.shift();
755
+ respond.send();
756
+ };
757
+
758
+
759
+ FirefoxDriver.prototype.getMouseSpeed = function(respond) {
760
+ respond.response = this.mouseSpeed;
761
+ respond.send();
762
+ };
763
+
764
+
765
+ FirefoxDriver.prototype.saveScreenshot = function(respond, pngFile) {
766
+ var window = Utils.getBrowser(respond.context).contentWindow;
767
+ try {
768
+ var canvas = Screenshooter.grab(window);
769
+ try {
770
+ Screenshooter.save(canvas, pngFile);
771
+ } catch(e) {
772
+ respond.isError = true;
773
+ respond.response = 'Could not save screenshot to ' + pngFile + ' - ' + e;
774
+ }
775
+ } catch(e) {
776
+ respond.isError = true;
777
+ respond.response = 'Could not take screenshot of current page - ' + e;
778
+ }
779
+ respond.send();
780
+ };
781
+
782
+
783
+ FirefoxDriver.prototype.getScreenshotAsBase64 = function(respond) {
784
+ var window = Utils.getBrowser(respond.context).contentWindow;
785
+ try {
786
+ var canvas = Screenshooter.grab(window);
787
+ respond.isError = false;
788
+ respond.response = Screenshooter.toBase64(canvas);
789
+ } catch (e) {
790
+ respond.isError = true;
791
+ respond.response = 'Could not take screenshot of current page - ' + e;
792
+ }
793
+ respond.send();
794
+ };
795
+
796
+ FirefoxDriver.prototype.dismissAlert = function(respond, alertText) {
797
+ // TODO(simon): Is there a type for alerts?
798
+ var wm = Utils.getService("@mozilla.org/appshell/window-mediator;1", "nsIWindowMediator");
799
+ var allWindows = wm.getEnumerator("");
800
+ while (allWindows.hasMoreElements()) {
801
+ var alert = allWindows.getNext();
802
+ var doc = alert.document;
803
+ if (doc && doc.documentURI == "chrome://global/content/commonDialog.xul") {
804
+ var dialog = doc.getElementsByTagName("dialog")[0];
805
+ dialog.getButton("accept").click();
806
+ break;
807
+ }
808
+ }
809
+ respond.send();
810
+ };