browserstack-webdriver 0.0.1

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 (202) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +791 -0
  3. data/README.md +31 -0
  4. data/build.desc +334 -0
  5. data/lib/selenium-client.rb +2 -0
  6. data/lib/selenium-webdriver.rb +1 -0
  7. data/lib/selenium/client.rb +37 -0
  8. data/lib/selenium/client/base.rb +132 -0
  9. data/lib/selenium/client/driver.rb +10 -0
  10. data/lib/selenium/client/errors.rb +9 -0
  11. data/lib/selenium/client/extensions.rb +118 -0
  12. data/lib/selenium/client/idiomatic.rb +488 -0
  13. data/lib/selenium/client/javascript_expression_builder.rb +116 -0
  14. data/lib/selenium/client/javascript_frameworks/jquery.rb +13 -0
  15. data/lib/selenium/client/javascript_frameworks/prototype.rb +13 -0
  16. data/lib/selenium/client/legacy_driver.rb +1720 -0
  17. data/lib/selenium/client/protocol.rb +104 -0
  18. data/lib/selenium/client/selenium_helper.rb +34 -0
  19. data/lib/selenium/rake/server_task.rb +157 -0
  20. data/lib/selenium/server.rb +248 -0
  21. data/lib/selenium/webdriver.rb +71 -0
  22. data/lib/selenium/webdriver/android.rb +9 -0
  23. data/lib/selenium/webdriver/android/bridge.rb +47 -0
  24. data/lib/selenium/webdriver/chrome.rb +26 -0
  25. data/lib/selenium/webdriver/chrome/bridge.rb +120 -0
  26. data/lib/selenium/webdriver/chrome/profile.rb +90 -0
  27. data/lib/selenium/webdriver/chrome/service.rb +75 -0
  28. data/lib/selenium/webdriver/common.rb +44 -0
  29. data/lib/selenium/webdriver/common/action_builder.rb +352 -0
  30. data/lib/selenium/webdriver/common/alert.rb +30 -0
  31. data/lib/selenium/webdriver/common/bridge_helper.rb +67 -0
  32. data/lib/selenium/webdriver/common/core_ext/base64.rb +9 -0
  33. data/lib/selenium/webdriver/common/core_ext/dir.rb +42 -0
  34. data/lib/selenium/webdriver/common/core_ext/string.rb +5 -0
  35. data/lib/selenium/webdriver/common/driver.rb +301 -0
  36. data/lib/selenium/webdriver/common/driver_extensions/has_browser_connection.rb +17 -0
  37. data/lib/selenium/webdriver/common/driver_extensions/has_input_devices.rb +39 -0
  38. data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +25 -0
  39. data/lib/selenium/webdriver/common/driver_extensions/has_remote_status.rb +13 -0
  40. data/lib/selenium/webdriver/common/driver_extensions/has_session_id.rb +22 -0
  41. data/lib/selenium/webdriver/common/driver_extensions/has_touch_screen.rb +19 -0
  42. data/lib/selenium/webdriver/common/driver_extensions/has_web_storage.rb +22 -0
  43. data/lib/selenium/webdriver/common/driver_extensions/rotatable.rb +45 -0
  44. data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +43 -0
  45. data/lib/selenium/webdriver/common/driver_extensions/uploads_files.rb +46 -0
  46. data/lib/selenium/webdriver/common/element.rb +293 -0
  47. data/lib/selenium/webdriver/common/error.rb +207 -0
  48. data/lib/selenium/webdriver/common/file_reaper.rb +47 -0
  49. data/lib/selenium/webdriver/common/html5/local_storage.rb +42 -0
  50. data/lib/selenium/webdriver/common/html5/location.rb +0 -0
  51. data/lib/selenium/webdriver/common/html5/session_storage.rb +44 -0
  52. data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +42 -0
  53. data/lib/selenium/webdriver/common/json_helper.rb +34 -0
  54. data/lib/selenium/webdriver/common/keyboard.rb +55 -0
  55. data/lib/selenium/webdriver/common/keys.rb +109 -0
  56. data/lib/selenium/webdriver/common/log_entry.rb +29 -0
  57. data/lib/selenium/webdriver/common/logs.rb +23 -0
  58. data/lib/selenium/webdriver/common/mouse.rb +72 -0
  59. data/lib/selenium/webdriver/common/navigation.rb +43 -0
  60. data/lib/selenium/webdriver/common/options.rb +136 -0
  61. data/lib/selenium/webdriver/common/platform.rb +218 -0
  62. data/lib/selenium/webdriver/common/port_prober.rb +42 -0
  63. data/lib/selenium/webdriver/common/profile_helper.rb +67 -0
  64. data/lib/selenium/webdriver/common/proxy.rb +149 -0
  65. data/lib/selenium/webdriver/common/search_context.rb +92 -0
  66. data/lib/selenium/webdriver/common/socket_poller.rb +105 -0
  67. data/lib/selenium/webdriver/common/target_locator.rb +81 -0
  68. data/lib/selenium/webdriver/common/timeouts.rb +38 -0
  69. data/lib/selenium/webdriver/common/touch_action_builder.rb +64 -0
  70. data/lib/selenium/webdriver/common/touch_screen.rb +105 -0
  71. data/lib/selenium/webdriver/common/wait.rb +63 -0
  72. data/lib/selenium/webdriver/common/window.rb +104 -0
  73. data/lib/selenium/webdriver/common/zipper.rb +82 -0
  74. data/lib/selenium/webdriver/firefox.rb +37 -0
  75. data/lib/selenium/webdriver/firefox/binary.rb +158 -0
  76. data/lib/selenium/webdriver/firefox/bridge.rb +70 -0
  77. data/lib/selenium/webdriver/firefox/extension.rb +52 -0
  78. data/lib/selenium/webdriver/firefox/launcher.rb +106 -0
  79. data/lib/selenium/webdriver/firefox/profile.rb +263 -0
  80. data/lib/selenium/webdriver/firefox/profiles_ini.rb +62 -0
  81. data/lib/selenium/webdriver/firefox/socket_lock.rb +61 -0
  82. data/lib/selenium/webdriver/firefox/util.rb +29 -0
  83. data/lib/selenium/webdriver/ie.rb +19 -0
  84. data/lib/selenium/webdriver/ie/bridge.rb +68 -0
  85. data/lib/selenium/webdriver/ie/server.rb +86 -0
  86. data/lib/selenium/webdriver/iphone.rb +9 -0
  87. data/lib/selenium/webdriver/iphone/bridge.rb +45 -0
  88. data/lib/selenium/webdriver/opera.rb +24 -0
  89. data/lib/selenium/webdriver/opera/bridge.rb +112 -0
  90. data/lib/selenium/webdriver/opera/service.rb +49 -0
  91. data/lib/selenium/webdriver/phantomjs.rb +22 -0
  92. data/lib/selenium/webdriver/phantomjs/bridge.rb +59 -0
  93. data/lib/selenium/webdriver/phantomjs/service.rb +90 -0
  94. data/lib/selenium/webdriver/remote.rb +22 -0
  95. data/lib/selenium/webdriver/remote/bridge.rb +644 -0
  96. data/lib/selenium/webdriver/remote/capabilities.rb +267 -0
  97. data/lib/selenium/webdriver/remote/commands.rb +193 -0
  98. data/lib/selenium/webdriver/remote/http/common.rb +74 -0
  99. data/lib/selenium/webdriver/remote/http/curb.rb +79 -0
  100. data/lib/selenium/webdriver/remote/http/default.rb +139 -0
  101. data/lib/selenium/webdriver/remote/http/persistent.rb +38 -0
  102. data/lib/selenium/webdriver/remote/response.rb +97 -0
  103. data/lib/selenium/webdriver/remote/server_error.rb +17 -0
  104. data/lib/selenium/webdriver/safari.rb +46 -0
  105. data/lib/selenium/webdriver/safari/bridge.rb +110 -0
  106. data/lib/selenium/webdriver/safari/browser.rb +20 -0
  107. data/lib/selenium/webdriver/safari/extension.rb +120 -0
  108. data/lib/selenium/webdriver/safari/server.rb +145 -0
  109. data/lib/selenium/webdriver/support.rb +5 -0
  110. data/lib/selenium/webdriver/support/abstract_event_listener.rb +28 -0
  111. data/lib/selenium/webdriver/support/block_event_listener.rb +17 -0
  112. data/lib/selenium/webdriver/support/color.rb +110 -0
  113. data/lib/selenium/webdriver/support/event_firing_bridge.rb +112 -0
  114. data/lib/selenium/webdriver/support/select.rb +293 -0
  115. data/ruby.iml +13 -0
  116. data/spec/integration/selenium/client/api/backward_compatible_api_spec.rb +22 -0
  117. data/spec/integration/selenium/client/api/browser_xpath_library_spec.rb +17 -0
  118. data/spec/integration/selenium/client/api/click_spec.rb +39 -0
  119. data/spec/integration/selenium/client/api/cookie_spec.rb +39 -0
  120. data/spec/integration/selenium/client/api/element_spec.rb +14 -0
  121. data/spec/integration/selenium/client/api/highlight_located_element_spec.rb +19 -0
  122. data/spec/integration/selenium/client/api/retrieve_last_remote_control_logs_spec.rb +33 -0
  123. data/spec/integration/selenium/client/api/screenshot_spec.rb +31 -0
  124. data/spec/integration/selenium/client/api/select_window_spec.rb +46 -0
  125. data/spec/integration/selenium/client/api/start_stop_spec.rb +9 -0
  126. data/spec/integration/selenium/client/api/wait_for_ajax_spec.rb +27 -0
  127. data/spec/integration/selenium/client/api/wait_for_element_spec.rb +56 -0
  128. data/spec/integration/selenium/client/api/wait_for_field_value_spec.rb +52 -0
  129. data/spec/integration/selenium/client/api/wait_for_text_spec.rb +98 -0
  130. data/spec/integration/selenium/client/api/webdriver_backed_spec.rb +21 -0
  131. data/spec/integration/selenium/client/sample-app/public/jquery-1.3.2.js +4376 -0
  132. data/spec/integration/selenium/client/sample-app/public/jquery.html +55 -0
  133. data/spec/integration/selenium/client/sample-app/public/prototype-1.6.0.3.js +4320 -0
  134. data/spec/integration/selenium/client/sample-app/public/prototype.html +59 -0
  135. data/spec/integration/selenium/client/sample-app/sample_app.rb +32 -0
  136. data/spec/integration/selenium/client/spec_helper.rb +139 -0
  137. data/spec/integration/selenium/webdriver/app_cache_spec.rb +47 -0
  138. data/spec/integration/selenium/webdriver/browser_connection_spec.rb +20 -0
  139. data/spec/integration/selenium/webdriver/chrome/driver_spec.rb +28 -0
  140. data/spec/integration/selenium/webdriver/chrome/profile_spec.rb +63 -0
  141. data/spec/integration/selenium/webdriver/driver_spec.rb +266 -0
  142. data/spec/integration/selenium/webdriver/element_spec.rb +191 -0
  143. data/spec/integration/selenium/webdriver/error_spec.rb +30 -0
  144. data/spec/integration/selenium/webdriver/firefox/driver_spec.rb +21 -0
  145. data/spec/integration/selenium/webdriver/firefox/profile_spec.rb +141 -0
  146. data/spec/integration/selenium/webdriver/keyboard_spec.rb +57 -0
  147. data/spec/integration/selenium/webdriver/location_spec.rb +29 -0
  148. data/spec/integration/selenium/webdriver/mouse_spec.rb +57 -0
  149. data/spec/integration/selenium/webdriver/navigation_spec.rb +46 -0
  150. data/spec/integration/selenium/webdriver/opera/driver_spec.rb +47 -0
  151. data/spec/integration/selenium/webdriver/options_spec.rb +77 -0
  152. data/spec/integration/selenium/webdriver/remote/driver_spec.rb +19 -0
  153. data/spec/integration/selenium/webdriver/remote/element_spec.rb +26 -0
  154. data/spec/integration/selenium/webdriver/spec_helper.rb +36 -0
  155. data/spec/integration/selenium/webdriver/spec_support.rb +12 -0
  156. data/spec/integration/selenium/webdriver/spec_support/guards.rb +110 -0
  157. data/spec/integration/selenium/webdriver/spec_support/helpers.rb +51 -0
  158. data/spec/integration/selenium/webdriver/spec_support/rack_server.rb +123 -0
  159. data/spec/integration/selenium/webdriver/spec_support/test_environment.rb +239 -0
  160. data/spec/integration/selenium/webdriver/sql_database_spec.rb +59 -0
  161. data/spec/integration/selenium/webdriver/storage_spec.rb +96 -0
  162. data/spec/integration/selenium/webdriver/target_locator_spec.rb +186 -0
  163. data/spec/integration/selenium/webdriver/timeout_spec.rb +69 -0
  164. data/spec/integration/selenium/webdriver/touch_spec.rb +176 -0
  165. data/spec/integration/selenium/webdriver/window_spec.rb +70 -0
  166. data/spec/integration/selenium/webdriver/zipper_spec.rb +66 -0
  167. data/spec/unit/selenium/client/base_spec.rb +239 -0
  168. data/spec/unit/selenium/client/extensions_spec.rb +174 -0
  169. data/spec/unit/selenium/client/idiomatic_spec.rb +500 -0
  170. data/spec/unit/selenium/client/javascript_expression_builder_spec.rb +79 -0
  171. data/spec/unit/selenium/client/javascript_frameworks/jquery_spec.rb +10 -0
  172. data/spec/unit/selenium/client/javascript_frameworks/prototype_spec.rb +10 -0
  173. data/spec/unit/selenium/client/protocol_spec.rb +124 -0
  174. data/spec/unit/selenium/client/selenium_helper_spec.rb +56 -0
  175. data/spec/unit/selenium/client/spec_helper.rb +24 -0
  176. data/spec/unit/selenium/rake/task_spec.rb +79 -0
  177. data/spec/unit/selenium/server_spec.rb +150 -0
  178. data/spec/unit/selenium/webdriver/action_builder_spec.rb +97 -0
  179. data/spec/unit/selenium/webdriver/android/bridge_spec.rb +43 -0
  180. data/spec/unit/selenium/webdriver/chrome/bridge_spec.rb +137 -0
  181. data/spec/unit/selenium/webdriver/chrome/profile_spec.rb +57 -0
  182. data/spec/unit/selenium/webdriver/chrome/service_spec.rb +44 -0
  183. data/spec/unit/selenium/webdriver/error_spec.rb +41 -0
  184. data/spec/unit/selenium/webdriver/firefox/bridge_spec.rb +47 -0
  185. data/spec/unit/selenium/webdriver/ie/bridge_spec.rb +91 -0
  186. data/spec/unit/selenium/webdriver/iphone/bridge_spec.rb +42 -0
  187. data/spec/unit/selenium/webdriver/log_entry_spec.rb +11 -0
  188. data/spec/unit/selenium/webdriver/opera/bridge_spec.rb +44 -0
  189. data/spec/unit/selenium/webdriver/phantomjs/bridge_spec.rb +55 -0
  190. data/spec/unit/selenium/webdriver/proxy_spec.rb +106 -0
  191. data/spec/unit/selenium/webdriver/remote/bridge_spec.rb +16 -0
  192. data/spec/unit/selenium/webdriver/remote/capabilities_spec.rb +115 -0
  193. data/spec/unit/selenium/webdriver/remote/http/common_spec.rb +24 -0
  194. data/spec/unit/selenium/webdriver/remote/http/default_spec.rb +124 -0
  195. data/spec/unit/selenium/webdriver/search_context_spec.rb +61 -0
  196. data/spec/unit/selenium/webdriver/socket_poller_spec.rb +68 -0
  197. data/spec/unit/selenium/webdriver/spec_helper.rb +27 -0
  198. data/spec/unit/selenium/webdriver/support/color_spec.rb +119 -0
  199. data/spec/unit/selenium/webdriver/support/event_firing_spec.rb +111 -0
  200. data/spec/unit/selenium/webdriver/support/select_spec.rb +290 -0
  201. data/spec/unit/selenium/webdriver/wait_spec.rb +49 -0
  202. metadata +370 -0
@@ -0,0 +1,82 @@
1
+ require 'zip'
2
+ require 'tempfile'
3
+ require 'find'
4
+
5
+ module Selenium
6
+ module WebDriver
7
+ #
8
+ # @api private
9
+ #
10
+
11
+ module Zipper
12
+
13
+ EXTENSIONS = %w[.zip .xpi]
14
+
15
+ class << self
16
+
17
+ def unzip(path)
18
+ destination = Dir.mktmpdir("webdriver-unzip")
19
+ FileReaper << destination
20
+
21
+ Zip::File.open(path) do |zip|
22
+ zip.each do |entry|
23
+ to = File.join(destination, entry.name)
24
+ dirname = File.dirname(to)
25
+
26
+ FileUtils.mkdir_p dirname unless File.exist? dirname
27
+ zip.extract(entry, to)
28
+ end
29
+ end
30
+
31
+ destination
32
+ end
33
+
34
+ def zip(path)
35
+ with_tmp_zip do |zip|
36
+ ::Find.find(path) do |file|
37
+ unless File.directory?(file)
38
+ add_zip_entry zip, file, file.sub("#{path}/", '')
39
+ end
40
+ end
41
+
42
+ zip.commit
43
+ File.open(zip.name, "rb") { |io| Base64.strict_encode64 io.read }
44
+ end
45
+ end
46
+
47
+ def zip_file(path)
48
+ with_tmp_zip do |zip|
49
+ add_zip_entry zip, path, File.basename(path)
50
+
51
+ zip.commit
52
+ File.open(zip.name, "rb") { |io| Base64.strict_encode64 io.read }
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def with_tmp_zip(&blk)
59
+ # can't use Tempfile here since it doesn't support File::BINARY mode on 1.8
60
+ # can't use Dir.mktmpdir(&blk) because of http://jira.codehaus.org/browse/JRUBY-4082
61
+ tmp_dir = Dir.mktmpdir
62
+ zip_path = File.join(tmp_dir, "webdriver-zip")
63
+
64
+ begin
65
+ Zip::File.open(zip_path, Zip::File::CREATE, &blk)
66
+ ensure
67
+ FileUtils.rm_rf tmp_dir
68
+ FileUtils.rm_rf zip_path
69
+ end
70
+ end
71
+
72
+ def add_zip_entry(zip, file, entry_name)
73
+ entry = Zip::Entry.new(zip.name, entry_name)
74
+ entry.follow_symlinks = true
75
+
76
+ zip.add entry, file
77
+ end
78
+
79
+ end
80
+ end # Zipper
81
+ end # WebDriver
82
+ end # Selenium
@@ -0,0 +1,37 @@
1
+ require 'timeout'
2
+ require 'socket'
3
+ require 'rexml/document'
4
+
5
+ require 'selenium/webdriver/firefox/util'
6
+ require 'selenium/webdriver/firefox/extension'
7
+ require 'selenium/webdriver/firefox/socket_lock'
8
+ require 'selenium/webdriver/firefox/binary'
9
+ require 'selenium/webdriver/firefox/profiles_ini'
10
+ require 'selenium/webdriver/firefox/profile'
11
+ require 'selenium/webdriver/firefox/launcher'
12
+ require 'selenium/webdriver/firefox/bridge'
13
+
14
+ module Selenium
15
+ module WebDriver
16
+ module Firefox
17
+
18
+ DEFAULT_PORT = 7055
19
+ DEFAULT_ENABLE_NATIVE_EVENTS = Platform.os == :windows
20
+ DEFAULT_SECURE_SSL = false
21
+ DEFAULT_ASSUME_UNTRUSTED_ISSUER = true
22
+ DEFAULT_LOAD_NO_FOCUS_LIB = false
23
+
24
+ def self.path=(path)
25
+ Binary.path = path
26
+ end
27
+
28
+ end
29
+ end
30
+ end
31
+
32
+
33
+ # SocketError was added in Ruby 1.8.7.
34
+ # If it's not defined, we add it here so it can be used in rescues.
35
+ unless defined? SocketError
36
+ class SocketError < IOError; end
37
+ end
@@ -0,0 +1,158 @@
1
+ module Selenium
2
+ module WebDriver
3
+ module Firefox
4
+
5
+ # @api private
6
+ class Binary
7
+
8
+ NO_FOCUS_LIBRARY_NAME = "x_ignore_nofocus.so"
9
+ NO_FOCUS_LIBRARIES = [
10
+ ["#{WebDriver.root}/selenium/webdriver/firefox/native/linux/amd64/#{NO_FOCUS_LIBRARY_NAME}", "amd64/#{NO_FOCUS_LIBRARY_NAME}"],
11
+ ["#{WebDriver.root}/selenium/webdriver/firefox/native/linux/x86/#{NO_FOCUS_LIBRARY_NAME}", "x86/#{NO_FOCUS_LIBRARY_NAME}"],
12
+ ]
13
+
14
+ WAIT_TIMEOUT = 90
15
+ QUIT_TIMEOUT = 5
16
+
17
+ def start_with(profile, profile_path, *args)
18
+ if Platform.cygwin?
19
+ profile_path = Platform.cygwin_path(profile_path, :windows => true)
20
+ elsif Platform.windows?
21
+ profile_path = profile_path.gsub("/", "\\")
22
+ end
23
+
24
+ ENV['XRE_CONSOLE_LOG'] = profile.log_file if profile.log_file
25
+ ENV['XRE_PROFILE_PATH'] = profile_path
26
+ ENV['MOZ_NO_REMOTE'] = '1' # able to launch multiple instances
27
+ ENV['MOZ_CRASHREPORTER_DISABLE'] = '1' # disable breakpad
28
+ ENV['NO_EM_RESTART'] = '1' # prevent the binary from detaching from the console
29
+
30
+ if Platform.linux? && (profile.native_events? || profile.load_no_focus_lib?)
31
+ modify_link_library_path profile_path
32
+ end
33
+
34
+ execute(*args)
35
+ cope_with_mac_strangeness(args) if Platform.mac?
36
+ end
37
+
38
+ def quit
39
+ return unless @process
40
+ @process.poll_for_exit QUIT_TIMEOUT
41
+ rescue ChildProcess::TimeoutError
42
+ # ok, force quit
43
+ @process.stop QUIT_TIMEOUT
44
+ end
45
+
46
+ def wait
47
+ @process.poll_for_exit(WAIT_TIMEOUT) if @process
48
+ end
49
+
50
+ private
51
+
52
+ def execute(*extra_args)
53
+ args = [self.class.path, "-no-remote"] + extra_args
54
+ @process = ChildProcess.build(*args)
55
+ @process.io.inherit! if $DEBUG
56
+ @process.start
57
+ end
58
+
59
+ def cope_with_mac_strangeness(args)
60
+ sleep 0.3
61
+
62
+ if @process.crashed?
63
+ # ok, trying a restart
64
+ sleep 7
65
+ execute(*args)
66
+ end
67
+
68
+ # ensure we're ok
69
+ sleep 0.3
70
+ if @process.crashed?
71
+ raise Error::WebDriverError, "unable to start Firefox cleanly, args: #{args.inspect}"
72
+ end
73
+ end
74
+
75
+ def modify_link_library_path(profile_path)
76
+ paths = []
77
+
78
+ NO_FOCUS_LIBRARIES.each do |from, to|
79
+ dest = File.join(profile_path, to)
80
+ FileUtils.mkdir_p File.dirname(dest)
81
+ FileUtils.cp from, dest
82
+
83
+ paths << File.expand_path(File.dirname(dest))
84
+ end
85
+
86
+ paths += ENV['LD_LIBRARY_PATH'].to_s.split(File::PATH_SEPARATOR)
87
+
88
+ ENV['LD_LIBRARY_PATH'] = paths.uniq.join(File::PATH_SEPARATOR)
89
+ ENV['LD_PRELOAD'] = NO_FOCUS_LIBRARY_NAME
90
+ end
91
+
92
+ class << self
93
+
94
+ #
95
+ # @api private
96
+ #
97
+ # @see Firefox.path=
98
+ #
99
+
100
+ def path=(path)
101
+ Platform.assert_executable(path)
102
+ @path = path
103
+ end
104
+
105
+ def path
106
+ @path ||= case Platform.os
107
+ when :macosx
108
+ macosx_path
109
+ when :windows
110
+ windows_path
111
+ when :linux, :unix
112
+ Platform.find_binary("firefox3", "firefox2", "firefox") || "/usr/bin/firefox"
113
+ else
114
+ raise Error::WebDriverError, "unknown platform: #{Platform.os}"
115
+ end
116
+
117
+ @path = Platform.cygwin_path(@path) if Platform.cygwin?
118
+
119
+ unless File.file?(@path.to_s)
120
+ raise Error::WebDriverError, "Could not find Firefox binary (os=#{Platform.os}). Make sure Firefox is installed or set the path manually with #{self}.path="
121
+ end
122
+
123
+ @path
124
+ end
125
+
126
+ private
127
+
128
+ def windows_path
129
+ windows_registry_path || Platform.find_in_program_files("\\Mozilla Firefox\\firefox.exe") || Platform.find_binary("firefox")
130
+ end
131
+
132
+ def macosx_path
133
+ path = "/Applications/Firefox.app/Contents/MacOS/firefox-bin"
134
+ path = Platform.find_binary("firefox-bin") unless File.exist?(path)
135
+
136
+ path
137
+ end
138
+
139
+ def windows_registry_path
140
+ require 'win32/registry'
141
+
142
+ lm = Win32::Registry::HKEY_LOCAL_MACHINE
143
+ lm.open("SOFTWARE\\Mozilla\\Mozilla Firefox") do |reg|
144
+ main = lm.open("SOFTWARE\\Mozilla\\Mozilla Firefox\\#{reg.keys[0]}\\Main")
145
+ if entry = main.find { |key, type, data| key =~ /pathtoexe/i }
146
+ return entry.last
147
+ end
148
+ end
149
+ rescue LoadError
150
+ # older JRuby or IronRuby does not have win32/registry
151
+ rescue Win32::Registry::Error
152
+ end
153
+ end # class << self
154
+
155
+ end # Binary
156
+ end # Firefox
157
+ end # WebDriver
158
+ end # Selenium
@@ -0,0 +1,70 @@
1
+ module Selenium
2
+ module WebDriver
3
+ module Firefox
4
+
5
+ # @api private
6
+ class Bridge < Remote::Bridge
7
+
8
+ def initialize(opts = {})
9
+ port = opts.delete(:port) || DEFAULT_PORT
10
+ profile = opts.delete(:profile)
11
+ http_client = opts.delete(:http_client)
12
+ proxy = opts.delete(:proxy)
13
+
14
+ caps = opts.delete(:desired_capabilities) do
15
+ Remote::Capabilities.firefox(:native_events => DEFAULT_ENABLE_NATIVE_EVENTS)
16
+ end
17
+
18
+ @launcher = create_launcher(port, profile)
19
+
20
+ unless opts.empty?
21
+ raise ArgumentError, "unknown option#{'s' if opts.size != 1}: #{opts.inspect}"
22
+ end
23
+
24
+ @launcher.launch
25
+
26
+ caps.proxy = proxy if proxy
27
+
28
+ remote_opts = {
29
+ :url => @launcher.url,
30
+ :desired_capabilities => caps
31
+ }
32
+
33
+ remote_opts.merge!(:http_client => http_client) if http_client
34
+
35
+ begin
36
+ super(remote_opts)
37
+ rescue
38
+ @launcher.quit
39
+ raise
40
+ end
41
+ end
42
+
43
+ def browser
44
+ :firefox
45
+ end
46
+
47
+ def driver_extensions
48
+ [
49
+ DriverExtensions::TakesScreenshot,
50
+ DriverExtensions::HasInputDevices
51
+ ]
52
+ end
53
+
54
+ def quit
55
+ super
56
+ nil
57
+ ensure
58
+ @launcher.quit
59
+ end
60
+
61
+ private
62
+
63
+ def create_launcher(port, profile)
64
+ Launcher.new Binary.new, port, profile
65
+ end
66
+
67
+ end # Bridge
68
+ end # Firefox
69
+ end # WebDriver
70
+ end # Selenium
@@ -0,0 +1,52 @@
1
+ module Selenium
2
+ module WebDriver
3
+ module Firefox
4
+
5
+ # @api private
6
+ class Extension
7
+ def initialize(path)
8
+ unless File.exist?(path)
9
+ raise Error::WebDriverError, "could not find extension at #{path.inspect}"
10
+ end
11
+
12
+ @path = path
13
+ @should_reap_root = false
14
+ end
15
+
16
+ def write_to(extensions_dir)
17
+ root_dir = create_root
18
+ ext_path = File.join extensions_dir, read_id_from_install_rdf(root_dir)
19
+
20
+ FileUtils.rm_rf ext_path
21
+ FileUtils.mkdir_p File.dirname(ext_path), :mode => 0700
22
+ FileUtils.cp_r root_dir, ext_path
23
+
24
+ FileReaper.reap(root_dir) if @should_reap_root
25
+ end
26
+
27
+ private
28
+
29
+ def create_root
30
+ if File.directory? @path
31
+ @path
32
+ else
33
+ unless Zipper::EXTENSIONS.include? File.extname(@path)
34
+ raise Error::WebDriverError, "expected #{Zipper::EXTENSIONS.join(" or ")}, got #{@path.inspect}"
35
+ end
36
+
37
+ @should_reap_root = true
38
+ Zipper.unzip(@path)
39
+ end
40
+ end
41
+
42
+ def read_id_from_install_rdf(directory)
43
+ rdf_path = File.join(directory, "install.rdf")
44
+ doc = REXML::Document.new(File.read(rdf_path))
45
+
46
+ REXML::XPath.first(doc, "//em:id").text
47
+ end
48
+
49
+ end # Extension
50
+ end # Firefox
51
+ end # WebDriver
52
+ end # Selenium
@@ -0,0 +1,106 @@
1
+ module Selenium
2
+ module WebDriver
3
+ module Firefox
4
+
5
+ # @api private
6
+ class Launcher
7
+
8
+ SOCKET_LOCK_TIMEOUT = 45
9
+ STABLE_CONNECTION_TIMEOUT = 60
10
+
11
+ def initialize(binary, port, profile = nil)
12
+ @binary = binary
13
+ @port = Integer(port)
14
+
15
+ raise Error::WebDriverError, "invalid port: #{@port}" if @port < 1
16
+
17
+ if profile.kind_of? Profile
18
+ @profile = profile
19
+ else
20
+ @profile_name = profile
21
+ @profile = nil
22
+ end
23
+
24
+ @host = "127.0.0.1"
25
+ end
26
+
27
+ def url
28
+ "http://#{@host}:#{@port}/hub"
29
+ end
30
+
31
+ def launch
32
+ socket_lock.locked do
33
+ find_free_port
34
+ create_profile
35
+ start_silent_and_wait
36
+ start
37
+ connect_until_stable
38
+ end
39
+
40
+ self
41
+ end
42
+
43
+ def quit
44
+ @binary.quit
45
+ FileReaper.reap(@profile_dir) if @profile_dir
46
+ end
47
+
48
+ def find_free_port
49
+ @port = PortProber.above @port
50
+ end
51
+
52
+ def create_profile
53
+ fetch_profile unless @profile
54
+
55
+ @profile.add_webdriver_extension
56
+ @profile.port = @port
57
+
58
+ @profile_dir = @profile.layout_on_disk
59
+ FileReaper << @profile_dir
60
+ end
61
+
62
+ def start
63
+ assert_profile
64
+ @binary.start_with @profile, @profile_dir, "-foreground"
65
+ end
66
+
67
+ def start_silent_and_wait
68
+ assert_profile
69
+
70
+ @binary.start_with @profile, @profile_dir, "-silent"
71
+ @binary.wait
72
+ end
73
+
74
+ def connect_until_stable
75
+ poller = SocketPoller.new(@host, @port, STABLE_CONNECTION_TIMEOUT)
76
+
77
+ unless poller.connected?
78
+ @binary.quit
79
+ raise Error::WebDriverError, "unable to obtain stable firefox connection in #{STABLE_CONNECTION_TIMEOUT} seconds (#{@host}:#{@port})"
80
+ end
81
+ end
82
+
83
+ def fetch_profile
84
+ if @profile_name
85
+ @profile = Profile.from_name @profile_name
86
+
87
+ unless @profile
88
+ raise Error::WebDriverError, "unable to find profile named: #{@profile_name.inspect}"
89
+ end
90
+ else
91
+ @profile = Profile.new
92
+ end
93
+ end
94
+
95
+ def assert_profile
96
+ raise Error::WebDriverError, "must create_profile first" unless @profile && @profile_dir
97
+ end
98
+
99
+ def socket_lock
100
+ @socket_lock ||= SocketLock.new(@port - 1, SOCKET_LOCK_TIMEOUT)
101
+ end
102
+
103
+ end # Launcher
104
+ end # Firefox
105
+ end # WebDriver
106
+ end # Selenium