selenium-webdriver 2.48.1 → 2.49.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. data/CHANGES +34 -0
  2. data/lib/selenium/webdriver/chrome/bridge.rb +2 -2
  3. data/lib/selenium/webdriver/chrome/service.rb +6 -3
  4. data/lib/selenium/webdriver/common/driver.rb +6 -2
  5. data/lib/selenium/webdriver/common/element.rb +1 -1
  6. data/lib/selenium/webdriver/common/error.rb +7 -2
  7. data/lib/selenium/webdriver/common/options.rb +1 -2
  8. data/lib/selenium/webdriver/common/socket_lock.rb +5 -0
  9. data/lib/selenium/webdriver/common/window.rb +8 -0
  10. data/lib/selenium/webdriver/edge/bridge.rb +3 -2
  11. data/lib/selenium/webdriver/edge/legacy_support.rb +117 -0
  12. data/lib/selenium/webdriver/edge/service.rb +3 -2
  13. data/lib/selenium/webdriver/firefox/binary.rb +1 -0
  14. data/lib/selenium/webdriver/firefox/bridge.rb +2 -0
  15. data/lib/selenium/webdriver/firefox/extension/prefs.json +2 -0
  16. data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
  17. data/lib/selenium/webdriver/firefox/w3c_bridge.rb +10 -41
  18. data/lib/selenium/webdriver/ie/bridge.rb +1 -1
  19. data/lib/selenium/webdriver/ie/server.rb +36 -12
  20. data/lib/selenium/webdriver/phantomjs/service.rb +44 -25
  21. data/lib/selenium/webdriver/remote/bridge.rb +14 -33
  22. data/lib/selenium/webdriver/remote/capabilities.rb +8 -6
  23. data/lib/selenium/webdriver/remote/commands.rb +0 -5
  24. data/lib/selenium/webdriver/remote/w3c_bridge.rb +68 -86
  25. data/lib/selenium/webdriver/remote/w3c_capabilities.rb +35 -16
  26. data/lib/selenium/webdriver/remote/w3c_commands.rb +1 -2
  27. data/lib/selenium/webdriver/safari/bridge.rb +1 -1
  28. data/lib/selenium/webdriver/safari/browser.rb +2 -0
  29. data/lib/selenium/webdriver/safari/options.rb +6 -4
  30. data/lib/selenium/webdriver/safari/resources/client.js +65 -51
  31. data/lib/selenium/webdriver/safari/server.rb +23 -2
  32. data/selenium-webdriver.gemspec +1 -1
  33. metadata +3 -2
@@ -49,6 +49,7 @@ module Selenium
49
49
  end
50
50
 
51
51
  alias_method :version, :browser_version
52
+ alias_method :platform, :platform_name
52
53
 
53
54
  #
54
55
  # Convenience methods for the common choices.
@@ -64,19 +65,19 @@ module Selenium
64
65
  end
65
66
 
66
67
  def firefox(opts = {})
68
+ opts[:browser_version] = opts.delete :version
69
+ opts[:platform_name] = opts.delete :platform
70
+
67
71
  new({
68
- :browser_name => "firefox"
72
+ :browser_name => "firefox",
73
+ :marionette => true
69
74
  }.merge(opts))
70
75
  end
71
76
 
72
77
  alias_method :ff, :firefox
73
78
 
74
79
  def w3c?(opts = {})
75
- return false unless opts[:desired_capabilities].is_a?(W3CCapabilities) || opts.delete(:marionette)
76
- Firefox::Binary.path = ENV['MARIONETTE_PATH'] if ENV['MARIONETTE_PATH']
77
- firefox_version = Firefox::Binary.version
78
- raise ArgumentError, "Firefox Version #{firefox_version} does not support W3CCapabilities" if firefox_version < 43
79
- true
80
+ opts[:desired_capabilities].is_a?(W3CCapabilities) || opts[:marionette]
80
81
  end
81
82
 
82
83
  #
@@ -86,20 +87,38 @@ module Selenium
86
87
  def json_create(data)
87
88
  data = data.dup
88
89
 
90
+ # Convert due to Remote Driver implementation
91
+ data["browserVersion"] = data.delete("version") if data["version"]
92
+ data["platformName"] = data.delete("platform") if data["platform"]
93
+
89
94
  caps = new
90
- caps.browser_name = data.delete("browserName")
91
- caps.browser_version = data.delete("browserVersion")
92
- caps.platform_name = data.delete("platformName").downcase.to_sym if data.has_key?('platform')
93
- caps.platform_version = data.delete("platformVersion")
94
- caps.accept_ssl_certs = data.delete("acceptSslCerts")
95
- caps.takes_screenshot = data.delete("takesScreenshot ")
96
- caps.takes_element_screenshot = data.delete("takesElementScreenshot")
97
- caps.page_load_strategy = data.delete("pageLoadStrategy")
98
- caps.proxy = Proxy.json_create(data['proxy']) if data.has_key?('proxy')
95
+ caps.browser_name = data.delete("browserName") if data["browserName"]
96
+ caps.browser_version = data.delete("browserVersion") if data["browserVersion"]
97
+ caps.platform_name = data.delete("platformName") if data["platformName"]
98
+ caps.platform_version = data.delete("platformVersion") if data["platformVersion"]
99
+ caps.accept_ssl_certs = data.delete("acceptSslCerts") if data["acceptSslCerts"]
100
+ caps.takes_screenshot = data.delete("takesScreenshot") if data["takesScreenshot"]
101
+ caps.takes_element_screenshot = data.delete("takesElementScreenshot") if data["takesElementScreenshot"]
102
+ caps.page_load_strategy = data.delete("pageLoadStrategy") if data["pageloadStrategy"]
103
+ caps.proxy = Proxy.json_create(data['proxy']) if data['proxy']
104
+
105
+ # Remote Server Specific
106
+ caps[:remote_session_id] = data.delete('webdriver.remote.sessionid')
107
+
108
+ # Obsolete capabilities returned by Remote Server
109
+ data.delete("javascriptEnabled")
110
+ data.delete('cssSelectorsEnabled')
111
+
112
+ # Marionette Specific
113
+ caps[:specification_level] = data.delete("specificaionLevel")
114
+ caps[:xul_app_id] = data.delete("XULappId")
115
+ caps[:raise_accessibility_exceptions] = data.delete('raisesAccessibilityExceptions')
116
+ caps[:rotatable] = data.delete('rotatable')
117
+ caps[:app_build_id] = data.delete('appBuildId')
118
+ caps[:device] = data.delete('device')
99
119
 
100
120
  # any remaining pairs will be added as is, with no conversion
101
121
  caps.merge!(data)
102
-
103
122
  caps
104
123
  end
105
124
  end
@@ -50,7 +50,7 @@ class Selenium::WebDriver::Remote::W3CBridge
50
50
  command :closeWindow, :delete, "session/:session_id/window"
51
51
  command :switchToWindow, :post, "session/:session_id/window"
52
52
  command :getWindowHandles, :get, "session/:session_id/window/handles"
53
- command :fullscreenWindow, :post, "session/:session_id/window/window/fullscreen"
53
+ command :fullscreenWindow, :post, "session/:session_id/window/fullscreen"
54
54
  command :maximizeWindow, :post, "session/:session_id/window/maximize"
55
55
  command :setWindowSize, :post, "session/:session_id/window/size"
56
56
  command :getWindowSize, :get, "session/:session_id/window/size"
@@ -66,7 +66,6 @@ class Selenium::WebDriver::Remote::W3CBridge
66
66
  command :findChildElement, :post, "session/:session_id/element/:id/element"
67
67
  command :findChildElements, :post, "session/:session_id/element/:id/elements"
68
68
  command :getActiveElement, :post, "session/:session_id/element/active"
69
- command :isElementDisplayed, :get, "session/:session_id/element/:id/displayed"
70
69
  command :isElementSelected, :get, "session/:session_id/element/:id/selected"
71
70
  command :getElementAttribute, :get, "session/:session_id/element/:id/attribute/:name"
72
71
  command :getElementProperty, :get, "session/:session_id/element/:id/property/:name"
@@ -104,7 +104,7 @@ module Selenium
104
104
 
105
105
  def prepare_connect_file
106
106
  # TODO: use tempfile?
107
- path = File.join(Dir.tmpdir, "safaridriver-#{Time.now.to_i}.html")
107
+ path = File.join(Dir.tmpdir, "safaridriver-#{Time.now.usec}.html")
108
108
 
109
109
  File.open(path, 'w') do |io|
110
110
  io << "<!DOCTYPE html><script>window.location = '#{@server.uri}';</script>"
@@ -23,6 +23,8 @@ module Selenium
23
23
 
24
24
  class Browser
25
25
  def start(*args)
26
+ Platform.exit_hook { stop } # make sure we don't leave the browser running
27
+
26
28
  @process = ChildProcess.new(Safari.path, *args)
27
29
  @process.io.inherit! if $DEBUG
28
30
  @process.start
@@ -21,6 +21,8 @@ module Selenium
21
21
  module WebDriver
22
22
  module Safari
23
23
  class Options
24
+ DEFAULT_PORT = 56485
25
+
24
26
  attr_accessor :port, :data_dir, :skip_extension_installation
25
27
 
26
28
  def initialize(opts = {})
@@ -40,16 +42,16 @@ module Selenium
40
42
 
41
43
  def as_json
42
44
  {
43
- 'port' => port,
44
- 'dataDir' => data_dir,
45
- 'cleanSession' => clean_session?,
45
+ 'port' => port,
46
+ 'dataDir' => data_dir,
47
+ 'cleanSession' => clean_session?,
46
48
  }
47
49
  end
48
50
 
49
51
  private
50
52
 
51
53
  def extract_options(opts)
52
- @port = Integer(opts[:port] || PortProber.random)
54
+ @port = Integer(opts[:port] || DEFAULT_PORT)
53
55
  @data_dir = opts[:custom_data_dir] || opts[:data_dir]
54
56
  @clean_session = opts[:clean_session]
55
57
  end
@@ -1,4 +1,4 @@
1
- var COMPILED = !0, goog = goog || {};
1
+ 'use strict';var COMPILED = !0, goog = goog || {};
2
2
  goog.global = this;
3
3
  goog.isDef = function(a) {
4
4
  return void 0 !== a;
@@ -158,7 +158,7 @@ goog.loadedModules_ = {};
158
158
  goog.DEPENDENCIES_ENABLED = !COMPILED && goog.ENABLE_DEBUG_LOADER;
159
159
  goog.DEPENDENCIES_ENABLED && (goog.dependencies_ = {pathIsModule:{}, nameToPath:{}, requires:{}, visited:{}, written:{}, deferred:{}}, goog.inHtmlDocument_ = function() {
160
160
  var a = goog.global.document;
161
- return "undefined" != typeof a && "write" in a;
161
+ return null != a && "write" in a;
162
162
  }, goog.findBasePath_ = function() {
163
163
  if (goog.isDef(goog.global.CLOSURE_BASE_PATH)) {
164
164
  goog.basePath = goog.global.CLOSURE_BASE_PATH;
@@ -207,10 +207,12 @@ goog.DEPENDENCIES_ENABLED && (goog.dependencies_ = {pathIsModule:{}, nameToPath:
207
207
  delete goog.dependencies_.deferred[a];
208
208
  goog.globalEval(b);
209
209
  }
210
+ }, goog.loadModuleFromUrl = function(a) {
211
+ goog.retrieveAndExecModule_(a);
210
212
  }, goog.loadModule = function(a) {
211
213
  var b = goog.moduleLoaderState_;
212
214
  try {
213
- goog.moduleLoaderState_ = {moduleName:void 0};
215
+ goog.moduleLoaderState_ = {moduleName:void 0, declareLegacyNamespace:!1};
214
216
  var c;
215
217
  if (goog.isFunction(a)) {
216
218
  c = a.call(goog.global, {});
@@ -509,7 +511,7 @@ goog.setCssNameMapping = function(a, b) {
509
511
  !COMPILED && goog.global.CLOSURE_CSS_NAME_MAPPING && (goog.cssNameMapping_ = goog.global.CLOSURE_CSS_NAME_MAPPING);
510
512
  goog.getMsg = function(a, b) {
511
513
  b && (a = a.replace(/\{\$([^}]+)}/g, function(a, d) {
512
- return d in b ? b[d] : a;
514
+ return null != b && d in b ? b[d] : a;
513
515
  }));
514
516
  return a;
515
517
  };
@@ -714,8 +716,7 @@ goog.string.caseInsensitiveCompare = function(a, b) {
714
716
  var c = String(a).toLowerCase(), d = String(b).toLowerCase();
715
717
  return c < d ? -1 : c == d ? 0 : 1;
716
718
  };
717
- goog.string.numerateCompareRegExp_ = /(\.\d+)|(\d+)|(\D+)/g;
718
- goog.string.numerateCompare = function(a, b) {
719
+ goog.string.numberAwareCompare_ = function(a, b, c) {
719
720
  if (a == b) {
720
721
  return 0;
721
722
  }
@@ -725,14 +726,22 @@ goog.string.numerateCompare = function(a, b) {
725
726
  if (!b) {
726
727
  return 1;
727
728
  }
728
- for (var c = a.toLowerCase().match(goog.string.numerateCompareRegExp_), d = b.toLowerCase().match(goog.string.numerateCompareRegExp_), e = Math.min(c.length, d.length), f = 0;f < e;f++) {
729
- var g = c[f], h = d[f];
730
- if (g != h) {
731
- return c = parseInt(g, 10), !isNaN(c) && (d = parseInt(h, 10), !isNaN(d) && c - d) ? c - d : g < h ? -1 : 1;
729
+ for (var d = a.toLowerCase().match(c), e = b.toLowerCase().match(c), f = Math.min(d.length, e.length), g = 0;g < f;g++) {
730
+ c = d[g];
731
+ var h = e[g];
732
+ if (c != h) {
733
+ return a = parseInt(c, 10), !isNaN(a) && (b = parseInt(h, 10), !isNaN(b) && a - b) ? a - b : c < h ? -1 : 1;
732
734
  }
733
735
  }
734
- return c.length != d.length ? c.length - d.length : a < b ? -1 : 1;
736
+ return d.length != e.length ? d.length - e.length : a < b ? -1 : 1;
735
737
  };
738
+ goog.string.intAwareCompare = function(a, b) {
739
+ return goog.string.numberAwareCompare_(a, b, /\d+|\D+/g);
740
+ };
741
+ goog.string.floatAwareCompare = function(a, b) {
742
+ return goog.string.numberAwareCompare_(a, b, /\d+|\.\d+|\D+/g);
743
+ };
744
+ goog.string.numerateCompare = goog.string.floatAwareCompare;
736
745
  goog.string.urlEncode = function(a) {
737
746
  return encodeURIComponent(String(a));
738
747
  };
@@ -845,13 +854,10 @@ goog.string.truncateMiddle = function(a, b, c, d) {
845
854
  c && (a = goog.string.htmlEscape(a));
846
855
  return a;
847
856
  };
848
- goog.string.specialEscapeChars_ = {"\x00":"\\0", "\b":"\\b", "\f":"\\f", "\n":"\\n", "\r":"\\r", "\t":"\\t", "\x0B":"\\x0B", '"':'\\"', "\\":"\\\\"};
857
+ goog.string.specialEscapeChars_ = {"\x00":"\\0", "\b":"\\b", "\f":"\\f", "\n":"\\n", "\r":"\\r", "\t":"\\t", "\x0B":"\\x0B", '"':'\\"', "\\":"\\\\", "<":"<"};
849
858
  goog.string.jsEscapeCache_ = {"'":"\\'"};
850
859
  goog.string.quote = function(a) {
851
860
  a = String(a);
852
- if (a.quote) {
853
- return a.quote();
854
- }
855
861
  for (var b = ['"'], c = 0;c < a.length;c++) {
856
862
  var d = a.charAt(c), e = d.charCodeAt(0);
857
863
  b[c + 1] = goog.string.specialEscapeChars_[d] || (31 < e && 127 > e ? d : goog.string.escapeChar(d));
@@ -934,7 +940,7 @@ goog.string.getRandomString = function() {
934
940
  };
935
941
  goog.string.compareVersions = function(a, b) {
936
942
  for (var c = 0, d = goog.string.trim(String(a)).split("."), e = goog.string.trim(String(b)).split("."), f = Math.max(d.length, e.length), g = 0;0 == c && g < f;g++) {
937
- var h = d[g] || "", k = e[g] || "", l = RegExp("(\\d*)(\\D*)", "g"), p = RegExp("(\\d*)(\\D*)", "g");
943
+ var h = d[g] || "", k = e[g] || "", l = /(\d*)(\D*)/g, p = /(\d*)(\D*)/g;
938
944
  do {
939
945
  var m = l.exec(h) || ["", "", ""], n = p.exec(k) || ["", "", ""];
940
946
  if (0 == m[0].length && 0 == n[0].length) {
@@ -1497,16 +1503,16 @@ goog.array.zip = function(a) {
1497
1503
  if (!arguments.length) {
1498
1504
  return [];
1499
1505
  }
1500
- for (var b = [], c = 0;;c++) {
1501
- for (var d = [], e = 0;e < arguments.length;e++) {
1502
- var f = arguments[e];
1503
- if (c >= f.length) {
1504
- return b;
1505
- }
1506
- d.push(f[c]);
1506
+ for (var b = [], c = arguments[0].length, d = 1;d < arguments.length;d++) {
1507
+ arguments[d].length < c && (c = arguments[d].length);
1508
+ }
1509
+ for (d = 0;d < c;d++) {
1510
+ for (var e = [], f = 0;f < arguments.length;f++) {
1511
+ e.push(arguments[f][d]);
1507
1512
  }
1508
- b.push(d);
1513
+ b.push(e);
1509
1514
  }
1515
+ return b;
1510
1516
  };
1511
1517
  goog.array.shuffle = function(a, b) {
1512
1518
  for (var c = b || Math.random, d = a.length - 1;0 < d;d--) {
@@ -1598,7 +1604,7 @@ goog.object.getValueByKeys = function(a, b) {
1598
1604
  return a;
1599
1605
  };
1600
1606
  goog.object.containsKey = function(a, b) {
1601
- return b in a;
1607
+ return null !== a && b in a;
1602
1608
  };
1603
1609
  goog.object.containsValue = function(a, b) {
1604
1610
  for (var c in a) {
@@ -1635,13 +1641,13 @@ goog.object.remove = function(a, b) {
1635
1641
  return c;
1636
1642
  };
1637
1643
  goog.object.add = function(a, b, c) {
1638
- if (b in a) {
1644
+ if (null !== a && b in a) {
1639
1645
  throw Error('The object already contains the key "' + b + '"');
1640
1646
  }
1641
1647
  goog.object.set(a, b, c);
1642
1648
  };
1643
1649
  goog.object.get = function(a, b, c) {
1644
- return b in a ? a[b] : c;
1650
+ return null !== a && b in a ? a[b] : c;
1645
1651
  };
1646
1652
  goog.object.set = function(a, b, c) {
1647
1653
  a[b] = c;
@@ -1742,10 +1748,10 @@ goog.object.isImmutableView = function(a) {
1742
1748
  };
1743
1749
  goog.structs = {};
1744
1750
  goog.structs.getCount = function(a) {
1745
- return "function" == typeof a.getCount ? a.getCount() : goog.isArrayLike(a) || goog.isString(a) ? a.length : goog.object.getCount(a);
1751
+ return a.getCount && "function" == typeof a.getCount ? a.getCount() : goog.isArrayLike(a) || goog.isString(a) ? a.length : goog.object.getCount(a);
1746
1752
  };
1747
1753
  goog.structs.getValues = function(a) {
1748
- if ("function" == typeof a.getValues) {
1754
+ if (a.getValues && "function" == typeof a.getValues) {
1749
1755
  return a.getValues();
1750
1756
  }
1751
1757
  if (goog.isString(a)) {
@@ -1760,10 +1766,10 @@ goog.structs.getValues = function(a) {
1760
1766
  return goog.object.getValues(a);
1761
1767
  };
1762
1768
  goog.structs.getKeys = function(a) {
1763
- if ("function" == typeof a.getKeys) {
1769
+ if (a.getKeys && "function" == typeof a.getKeys) {
1764
1770
  return a.getKeys();
1765
1771
  }
1766
- if ("function" != typeof a.getValues) {
1772
+ if (!a.getValues || "function" != typeof a.getValues) {
1767
1773
  if (goog.isArrayLike(a) || goog.isString(a)) {
1768
1774
  var b = [];
1769
1775
  a = a.length;
@@ -1776,16 +1782,16 @@ goog.structs.getKeys = function(a) {
1776
1782
  }
1777
1783
  };
1778
1784
  goog.structs.contains = function(a, b) {
1779
- return "function" == typeof a.contains ? a.contains(b) : "function" == typeof a.containsValue ? a.containsValue(b) : goog.isArrayLike(a) || goog.isString(a) ? goog.array.contains(a, b) : goog.object.containsValue(a, b);
1785
+ return a.contains && "function" == typeof a.contains ? a.contains(b) : a.containsValue && "function" == typeof a.containsValue ? a.containsValue(b) : goog.isArrayLike(a) || goog.isString(a) ? goog.array.contains(a, b) : goog.object.containsValue(a, b);
1780
1786
  };
1781
1787
  goog.structs.isEmpty = function(a) {
1782
- return "function" == typeof a.isEmpty ? a.isEmpty() : goog.isArrayLike(a) || goog.isString(a) ? goog.array.isEmpty(a) : goog.object.isEmpty(a);
1788
+ return a.isEmpty && "function" == typeof a.isEmpty ? a.isEmpty() : goog.isArrayLike(a) || goog.isString(a) ? goog.array.isEmpty(a) : goog.object.isEmpty(a);
1783
1789
  };
1784
1790
  goog.structs.clear = function(a) {
1785
- "function" == typeof a.clear ? a.clear() : goog.isArrayLike(a) ? goog.array.clear(a) : goog.object.clear(a);
1791
+ a.clear && "function" == typeof a.clear ? a.clear() : goog.isArrayLike(a) ? goog.array.clear(a) : goog.object.clear(a);
1786
1792
  };
1787
1793
  goog.structs.forEach = function(a, b, c) {
1788
- if ("function" == typeof a.forEach) {
1794
+ if (a.forEach && "function" == typeof a.forEach) {
1789
1795
  a.forEach(b, c);
1790
1796
  } else {
1791
1797
  if (goog.isArrayLike(a) || goog.isString(a)) {
@@ -1985,19 +1991,26 @@ goog.functions.once = function(a) {
1985
1991
  goog.functions.debounce = function(a, b, c) {
1986
1992
  c && (a = goog.bind(a, c));
1987
1993
  var d = null;
1988
- return function() {
1994
+ return function(c) {
1989
1995
  goog.global.clearTimeout(d);
1990
- d = goog.global.setTimeout(a, b);
1996
+ var f = arguments;
1997
+ d = goog.global.setTimeout(function() {
1998
+ a.apply(null, f);
1999
+ }, b);
1991
2000
  };
1992
2001
  };
1993
2002
  goog.functions.throttle = function(a, b, c) {
1994
2003
  c && (a = goog.bind(a, c));
1995
- var d = null, e = !1, f = function() {
2004
+ var d = null, e = !1, f = [], g = function() {
1996
2005
  d = null;
1997
- e && (e = !1, d = goog.global.setTimeout(f, b), a());
2006
+ e && (e = !1, h());
2007
+ }, h = function() {
2008
+ d = goog.global.setTimeout(g, b);
2009
+ a.apply(null, f);
1998
2010
  };
1999
- return function() {
2000
- d ? e = !0 : (d = goog.global.setTimeout(f, b), a());
2011
+ return function(a) {
2012
+ f = arguments;
2013
+ d ? e = !0 : h();
2001
2014
  };
2002
2015
  };
2003
2016
  goog.math = {};
@@ -2105,7 +2118,7 @@ goog.math.isNegativeZero = function(a) {
2105
2118
  goog.math.log10Floor = function(a) {
2106
2119
  if (0 < a) {
2107
2120
  var b = Math.round(Math.log(a) * Math.LOG10E);
2108
- return b - (parseFloat("1e" + b) > a);
2121
+ return b - (parseFloat("1e" + b) > a ? 1 : 0);
2109
2122
  }
2110
2123
  return 0 == a ? -Infinity : NaN;
2111
2124
  };
@@ -2166,9 +2179,9 @@ goog.iter.forEach = function(a, b, c) {
2166
2179
  for (;;) {
2167
2180
  b.call(c, a.next(), void 0, a);
2168
2181
  }
2169
- } catch (d) {
2170
- if (d !== goog.iter.StopIteration) {
2171
- throw d;
2182
+ } catch (e) {
2183
+ if (e !== goog.iter.StopIteration) {
2184
+ throw e;
2172
2185
  }
2173
2186
  }
2174
2187
  }
@@ -4087,7 +4100,7 @@ goog.labs.userAgent.util.matchUserAgentIgnoreCase = function(a) {
4087
4100
  return goog.string.caseInsensitiveContains(b, a);
4088
4101
  };
4089
4102
  goog.labs.userAgent.util.extractVersionTuples = function(a) {
4090
- for (var b = RegExp("(\\w[\\w ]+)/([^\\s]+)\\s*(?:\\((.*?)\\))?", "g"), c = [], d;d = b.exec(a);) {
4103
+ for (var b = /(\w[\w ]+)\/([^\s]+)\s*(?:\((.*?)\))?/g, c = [], d;d = b.exec(a);) {
4091
4104
  c.push([d[1], d[2], d[3] || void 0]);
4092
4105
  }
4093
4106
  return c;
@@ -4489,7 +4502,7 @@ goog.debug.normalizeErrorObject = function(a) {
4489
4502
  }
4490
4503
  try {
4491
4504
  d = a.fileName || a.filename || a.sourceURL || goog.global.$googDebugFname || b;
4492
- } catch (f) {
4505
+ } catch (g) {
4493
4506
  d = "Not available", e = !0;
4494
4507
  }
4495
4508
  return !e && a.lineNumber && a.fileName && a.stack && a.message && a.name ? a : {message:a.message || "Not available", name:a.name || "UnknownError", lineNumber:c, fileName:d, stack:a.stack || "Not available"};
@@ -6824,9 +6837,10 @@ goog.userAgent.product.ASSUME_IPAD = !1;
6824
6837
  goog.userAgent.product.ASSUME_ANDROID = !1;
6825
6838
  goog.userAgent.product.ASSUME_CHROME = !1;
6826
6839
  goog.userAgent.product.ASSUME_SAFARI = !0;
6827
- goog.userAgent.product.PRODUCT_KNOWN_ = goog.userAgent.ASSUME_IE || goog.userAgent.ASSUME_OPERA || goog.userAgent.product.ASSUME_FIREFOX || goog.userAgent.product.ASSUME_IPHONE || goog.userAgent.product.ASSUME_IPAD || goog.userAgent.product.ASSUME_ANDROID || goog.userAgent.product.ASSUME_CHROME || goog.userAgent.product.ASSUME_SAFARI;
6840
+ goog.userAgent.product.PRODUCT_KNOWN_ = goog.userAgent.ASSUME_IE || goog.userAgent.ASSUME_EDGE || goog.userAgent.ASSUME_OPERA || goog.userAgent.product.ASSUME_FIREFOX || goog.userAgent.product.ASSUME_IPHONE || goog.userAgent.product.ASSUME_IPAD || goog.userAgent.product.ASSUME_ANDROID || goog.userAgent.product.ASSUME_CHROME || goog.userAgent.product.ASSUME_SAFARI;
6828
6841
  goog.userAgent.product.OPERA = goog.userAgent.OPERA;
6829
6842
  goog.userAgent.product.IE = goog.userAgent.IE;
6843
+ goog.userAgent.product.EDGE = goog.userAgent.EDGE;
6830
6844
  goog.userAgent.product.FIREFOX = goog.userAgent.product.PRODUCT_KNOWN_ ? goog.userAgent.product.ASSUME_FIREFOX : goog.labs.userAgent.browser.isFirefox();
6831
6845
  goog.userAgent.product.isIphoneOrIpod_ = function() {
6832
6846
  return goog.labs.userAgent.platform.isIphone() || goog.labs.userAgent.platform.isIpod();
@@ -6843,7 +6857,7 @@ goog.userAgent.product.determineVersion_ = function() {
6843
6857
  if (goog.userAgent.product.FIREFOX) {
6844
6858
  return goog.userAgent.product.getFirstRegExpGroup_(/Firefox\/([0-9.]+)/);
6845
6859
  }
6846
- if (goog.userAgent.product.IE || goog.userAgent.product.OPERA) {
6860
+ if (goog.userAgent.product.IE || goog.userAgent.product.EDGE || goog.userAgent.product.OPERA) {
6847
6861
  return goog.userAgent.VERSION;
6848
6862
  }
6849
6863
  if (goog.userAgent.product.CHROME) {
@@ -6976,7 +6990,7 @@ goog.json.Serializer.prototype.serializeInternal = function(a, b) {
6976
6990
  this.serializeNumber_(a, b);
6977
6991
  break;
6978
6992
  case "boolean":
6979
- b.push(a);
6993
+ b.push(String(a));
6980
6994
  break;
6981
6995
  case "function":
6982
6996
  b.push("null");
@@ -6996,7 +7010,7 @@ goog.json.Serializer.prototype.serializeString_ = function(a, b) {
6996
7010
  }), '"');
6997
7011
  };
6998
7012
  goog.json.Serializer.prototype.serializeNumber_ = function(a, b) {
6999
- b.push(isFinite(a) && !isNaN(a) ? a : "null");
7013
+ b.push(isFinite(a) && !isNaN(a) ? String(a) : "null");
7000
7014
  };
7001
7015
  goog.json.Serializer.prototype.serializeArray = function(a, b) {
7002
7016
  var c = a.length;
@@ -22,13 +22,20 @@ module Selenium
22
22
  module Safari
23
23
 
24
24
  class Server
25
+ SOCKET_LOCK_TIMEOUT = 45
26
+
25
27
  def initialize(port, command_timeout)
26
- @port = port
28
+ @port = port
27
29
  @command_timeout = command_timeout
28
30
  end
29
31
 
30
32
  def start
31
- @server = TCPServer.new(Platform.localhost, @port)
33
+ Platform.exit_hook { stop } # make sure we don't leave the server running
34
+
35
+ socket_lock.locked do
36
+ find_free_port
37
+ start_server
38
+ end
32
39
  end
33
40
 
34
41
  def stop
@@ -158,6 +165,20 @@ Server: safaridriver-ruby
158
165
  end
159
166
  end
160
167
 
168
+ private
169
+
170
+ def start_server
171
+ @server = TCPServer.new(Platform.localhost, @port)
172
+ end
173
+
174
+ def find_free_port
175
+ @port = PortProber.above @port
176
+ end
177
+
178
+ def socket_lock
179
+ @socket_lock ||= SocketLock.new(@port - 1, SOCKET_LOCK_TIMEOUT)
180
+ end
181
+
161
182
  end # Server
162
183
  end # Safari
163
184
  end # WebDriver