selenium-webdriver 4.0.0.rc1 → 4.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.
- checksums.yaml +4 -4
 - data/CHANGES +60 -0
 - data/README.md +1 -1
 - data/lib/selenium/server.rb +62 -48
 - data/lib/selenium/webdriver/atoms/findElements.js +2 -2
 - data/lib/selenium/webdriver/atoms/getAttribute.js +25 -25
 - data/lib/selenium/webdriver/chrome/driver.rb +3 -0
 - data/lib/selenium/webdriver/chrome/features.rb +44 -4
 - data/lib/selenium/webdriver/chrome/options.rb +24 -1
 - data/lib/selenium/webdriver/common/driver.rb +2 -0
 - data/lib/selenium/webdriver/common/driver_extensions/has_apple_permissions.rb +51 -0
 - data/lib/selenium/webdriver/common/driver_extensions/has_casting.rb +77 -0
 - data/lib/selenium/webdriver/common/driver_extensions/has_context.rb +45 -0
 - data/lib/selenium/webdriver/common/driver_extensions/has_launching.rb +38 -0
 - data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +17 -0
 - data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +87 -18
 - data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +11 -11
 - data/lib/selenium/webdriver/common/driver_extensions/prints_page.rb +1 -1
 - data/lib/selenium/webdriver/common/log_entry.rb +2 -2
 - data/lib/selenium/webdriver/common/manager.rb +3 -13
 - data/lib/selenium/webdriver/common/options.rb +13 -5
 - data/lib/selenium/webdriver/common/profile_helper.rb +1 -7
 - data/lib/selenium/webdriver/common/socket_poller.rb +30 -19
 - data/lib/selenium/webdriver/common/target_locator.rb +28 -0
 - data/lib/selenium/webdriver/common/timeouts.rb +31 -4
 - data/lib/selenium/webdriver/common/window.rb +0 -4
 - data/lib/selenium/webdriver/common/zipper.rb +1 -9
 - data/lib/selenium/webdriver/common.rb +4 -0
 - data/lib/selenium/webdriver/devtools/request.rb +27 -17
 - data/lib/selenium/webdriver/devtools/response.rb +66 -0
 - data/lib/selenium/webdriver/devtools.rb +49 -12
 - data/lib/selenium/webdriver/edge/features.rb +5 -0
 - data/lib/selenium/webdriver/firefox/driver.rb +5 -0
 - data/lib/selenium/webdriver/firefox/features.rb +14 -0
 - data/lib/selenium/webdriver/firefox/options.rb +28 -1
 - data/lib/selenium/webdriver/firefox.rb +0 -1
 - data/lib/selenium/webdriver/remote/bridge.rb +9 -10
 - data/lib/selenium/webdriver/remote/capabilities.rb +1 -0
 - data/lib/selenium/webdriver/remote/commands.rb +1 -0
 - data/lib/selenium/webdriver/remote/driver.rb +2 -1
 - data/lib/selenium/webdriver/safari/driver.rb +1 -1
 - data/lib/selenium/webdriver/safari/options.rb +7 -0
 - data/lib/selenium/webdriver/version.rb +1 -1
 - data/lib/selenium/webdriver.rb +1 -0
 - data/selenium-webdriver.gemspec +2 -2
 - metadata +14 -3
 
| 
         @@ -0,0 +1,77 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            # Licensed to the Software Freedom Conservancy (SFC) under one
         
     | 
| 
      
 4 
     | 
    
         
            +
            # or more contributor license agreements.  See the NOTICE file
         
     | 
| 
      
 5 
     | 
    
         
            +
            # distributed with this work for additional information
         
     | 
| 
      
 6 
     | 
    
         
            +
            # regarding copyright ownership.  The SFC licenses this file
         
     | 
| 
      
 7 
     | 
    
         
            +
            # to you under the Apache License, Version 2.0 (the
         
     | 
| 
      
 8 
     | 
    
         
            +
            # "License"); you may not use this file except in compliance
         
     | 
| 
      
 9 
     | 
    
         
            +
            # with the License.  You may obtain a copy of the License at
         
     | 
| 
      
 10 
     | 
    
         
            +
            #
         
     | 
| 
      
 11 
     | 
    
         
            +
            #   http://www.apache.org/licenses/LICENSE-2.0
         
     | 
| 
      
 12 
     | 
    
         
            +
            #
         
     | 
| 
      
 13 
     | 
    
         
            +
            # Unless required by applicable law or agreed to in writing,
         
     | 
| 
      
 14 
     | 
    
         
            +
            # software distributed under the License is distributed on an
         
     | 
| 
      
 15 
     | 
    
         
            +
            # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
         
     | 
| 
      
 16 
     | 
    
         
            +
            # KIND, either express or implied.  See the License for the
         
     | 
| 
      
 17 
     | 
    
         
            +
            # specific language governing permissions and limitations
         
     | 
| 
      
 18 
     | 
    
         
            +
            # under the License.
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            module Selenium
         
     | 
| 
      
 21 
     | 
    
         
            +
              module WebDriver
         
     | 
| 
      
 22 
     | 
    
         
            +
                module DriverExtensions
         
     | 
| 
      
 23 
     | 
    
         
            +
                  module HasCasting
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                    #
         
     | 
| 
      
 26 
     | 
    
         
            +
                    # What devices ("sinks") are available to be cast to.
         
     | 
| 
      
 27 
     | 
    
         
            +
                    #
         
     | 
| 
      
 28 
     | 
    
         
            +
                    # @return [Array] list of sinks available for casting with id and name values
         
     | 
| 
      
 29 
     | 
    
         
            +
                    #
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                    def cast_sinks
         
     | 
| 
      
 32 
     | 
    
         
            +
                      @bridge.cast_sinks
         
     | 
| 
      
 33 
     | 
    
         
            +
                    end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                    #
         
     | 
| 
      
 36 
     | 
    
         
            +
                    # Sets a specific sink, using its name, as a Cast session receiver target.
         
     | 
| 
      
 37 
     | 
    
         
            +
                    #
         
     | 
| 
      
 38 
     | 
    
         
            +
                    # @param [String] name the sink to use as the target
         
     | 
| 
      
 39 
     | 
    
         
            +
                    #
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                    def cast_sink_to_use=(name)
         
     | 
| 
      
 42 
     | 
    
         
            +
                      @bridge.cast_sink_to_use = name
         
     | 
| 
      
 43 
     | 
    
         
            +
                    end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                    #
         
     | 
| 
      
 46 
     | 
    
         
            +
                    # Starts a tab mirroring session on a specific receiver target.
         
     | 
| 
      
 47 
     | 
    
         
            +
                    #
         
     | 
| 
      
 48 
     | 
    
         
            +
                    # @param [String] name the sink to use as the target
         
     | 
| 
      
 49 
     | 
    
         
            +
                    #
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                    def start_cast_tab_mirroring(name)
         
     | 
| 
      
 52 
     | 
    
         
            +
                      @bridge.start_cast_tab_mirroring(name)
         
     | 
| 
      
 53 
     | 
    
         
            +
                    end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                    #
         
     | 
| 
      
 56 
     | 
    
         
            +
                    # Gets error messages when there is any issue in a Cast session.
         
     | 
| 
      
 57 
     | 
    
         
            +
                    #
         
     | 
| 
      
 58 
     | 
    
         
            +
                    # @return [String] the error message
         
     | 
| 
      
 59 
     | 
    
         
            +
                    #
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                    def cast_issue_message
         
     | 
| 
      
 62 
     | 
    
         
            +
                      @bridge.cast_issue_message
         
     | 
| 
      
 63 
     | 
    
         
            +
                    end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                    #
         
     | 
| 
      
 66 
     | 
    
         
            +
                    # Stops the existing Cast session on a specific receiver target.
         
     | 
| 
      
 67 
     | 
    
         
            +
                    #
         
     | 
| 
      
 68 
     | 
    
         
            +
                    # @param [String] name the sink to stop the Cast session
         
     | 
| 
      
 69 
     | 
    
         
            +
                    #
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                    def stop_casting(name)
         
     | 
| 
      
 72 
     | 
    
         
            +
                      @bridge.stop_casting(name)
         
     | 
| 
      
 73 
     | 
    
         
            +
                    end
         
     | 
| 
      
 74 
     | 
    
         
            +
                  end # HasCasting
         
     | 
| 
      
 75 
     | 
    
         
            +
                end # DriverExtensions
         
     | 
| 
      
 76 
     | 
    
         
            +
              end # WebDriver
         
     | 
| 
      
 77 
     | 
    
         
            +
            end # Selenium
         
     | 
| 
         @@ -0,0 +1,45 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            # Licensed to the Software Freedom Conservancy (SFC) under one
         
     | 
| 
      
 4 
     | 
    
         
            +
            # or more contributor license agreements.  See the NOTICE file
         
     | 
| 
      
 5 
     | 
    
         
            +
            # distributed with this work for additional information
         
     | 
| 
      
 6 
     | 
    
         
            +
            # regarding copyright ownership.  The SFC licenses this file
         
     | 
| 
      
 7 
     | 
    
         
            +
            # to you under the Apache License, Version 2.0 (the
         
     | 
| 
      
 8 
     | 
    
         
            +
            # "License"); you may not use this file except in compliance
         
     | 
| 
      
 9 
     | 
    
         
            +
            # with the License.  You may obtain a copy of the License at
         
     | 
| 
      
 10 
     | 
    
         
            +
            #
         
     | 
| 
      
 11 
     | 
    
         
            +
            #   http://www.apache.org/licenses/LICENSE-2.0
         
     | 
| 
      
 12 
     | 
    
         
            +
            #
         
     | 
| 
      
 13 
     | 
    
         
            +
            # Unless required by applicable law or agreed to in writing,
         
     | 
| 
      
 14 
     | 
    
         
            +
            # software distributed under the License is distributed on an
         
     | 
| 
      
 15 
     | 
    
         
            +
            # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
         
     | 
| 
      
 16 
     | 
    
         
            +
            # KIND, either express or implied.  See the License for the
         
     | 
| 
      
 17 
     | 
    
         
            +
            # specific language governing permissions and limitations
         
     | 
| 
      
 18 
     | 
    
         
            +
            # under the License.
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            module Selenium
         
     | 
| 
      
 21 
     | 
    
         
            +
              module WebDriver
         
     | 
| 
      
 22 
     | 
    
         
            +
                module DriverExtensions
         
     | 
| 
      
 23 
     | 
    
         
            +
                  module HasContext
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                    #
         
     | 
| 
      
 26 
     | 
    
         
            +
                    # Sets the context that Selenium commands are running in using
         
     | 
| 
      
 27 
     | 
    
         
            +
                    #         a `with` statement. The state of the context on the server is
         
     | 
| 
      
 28 
     | 
    
         
            +
                    #         saved before entering the block, and restored upon exiting it.
         
     | 
| 
      
 29 
     | 
    
         
            +
                    #
         
     | 
| 
      
 30 
     | 
    
         
            +
                    # @param [String] name which permission to set
         
     | 
| 
      
 31 
     | 
    
         
            +
                    # @param [String] value what to set the permission to
         
     | 
| 
      
 32 
     | 
    
         
            +
                    #
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    def context=(value)
         
     | 
| 
      
 35 
     | 
    
         
            +
                      @bridge.context = value
         
     | 
| 
      
 36 
     | 
    
         
            +
                    end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                    def context
         
     | 
| 
      
 39 
     | 
    
         
            +
                      @bridge.context
         
     | 
| 
      
 40 
     | 
    
         
            +
                    end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                  end # HasContext
         
     | 
| 
      
 43 
     | 
    
         
            +
                end # DriverExtensions
         
     | 
| 
      
 44 
     | 
    
         
            +
              end # WebDriver
         
     | 
| 
      
 45 
     | 
    
         
            +
            end # Selenium
         
     | 
| 
         @@ -0,0 +1,38 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            # Licensed to the Software Freedom Conservancy (SFC) under one
         
     | 
| 
      
 4 
     | 
    
         
            +
            # or more contributor license agreements.  See the NOTICE file
         
     | 
| 
      
 5 
     | 
    
         
            +
            # distributed with this work for additional information
         
     | 
| 
      
 6 
     | 
    
         
            +
            # regarding copyright ownership.  The SFC licenses this file
         
     | 
| 
      
 7 
     | 
    
         
            +
            # to you under the Apache License, Version 2.0 (the
         
     | 
| 
      
 8 
     | 
    
         
            +
            # "License"); you may not use this file except in compliance
         
     | 
| 
      
 9 
     | 
    
         
            +
            # with the License.  You may obtain a copy of the License at
         
     | 
| 
      
 10 
     | 
    
         
            +
            #
         
     | 
| 
      
 11 
     | 
    
         
            +
            #   http://www.apache.org/licenses/LICENSE-2.0
         
     | 
| 
      
 12 
     | 
    
         
            +
            #
         
     | 
| 
      
 13 
     | 
    
         
            +
            # Unless required by applicable law or agreed to in writing,
         
     | 
| 
      
 14 
     | 
    
         
            +
            # software distributed under the License is distributed on an
         
     | 
| 
      
 15 
     | 
    
         
            +
            # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
         
     | 
| 
      
 16 
     | 
    
         
            +
            # KIND, either express or implied.  See the License for the
         
     | 
| 
      
 17 
     | 
    
         
            +
            # specific language governing permissions and limitations
         
     | 
| 
      
 18 
     | 
    
         
            +
            # under the License.
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            module Selenium
         
     | 
| 
      
 21 
     | 
    
         
            +
              module WebDriver
         
     | 
| 
      
 22 
     | 
    
         
            +
                module DriverExtensions
         
     | 
| 
      
 23 
     | 
    
         
            +
                  module HasLaunching
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                    #
         
     | 
| 
      
 26 
     | 
    
         
            +
                    # Launches Chromium app specified by id.
         
     | 
| 
      
 27 
     | 
    
         
            +
                    #
         
     | 
| 
      
 28 
     | 
    
         
            +
                    # @param [String] id
         
     | 
| 
      
 29 
     | 
    
         
            +
                    #
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                    def launch_app(id)
         
     | 
| 
      
 32 
     | 
    
         
            +
                      @bridge.launch_app(id)
         
     | 
| 
      
 33 
     | 
    
         
            +
                    end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  end # HasLaunching
         
     | 
| 
      
 36 
     | 
    
         
            +
                end # DriverExtensions
         
     | 
| 
      
 37 
     | 
    
         
            +
              end # WebDriver
         
     | 
| 
      
 38 
     | 
    
         
            +
            end # Selenium
         
     | 
| 
         @@ -38,13 +38,30 @@ module Selenium 
     | 
|
| 
       38 
38 
     | 
    
         
             
                    # @param [Hash] conditions
         
     | 
| 
       39 
39 
     | 
    
         
             
                    # @option conditions [Integer] :latency
         
     | 
| 
       40 
40 
     | 
    
         
             
                    # @option conditions [Integer] :throughput
         
     | 
| 
      
 41 
     | 
    
         
            +
                    # @option conditions [Integer] :upload_throughput
         
     | 
| 
      
 42 
     | 
    
         
            +
                    # @option conditions [Integer] :download_throughput
         
     | 
| 
       41 
43 
     | 
    
         
             
                    # @option conditions [Boolean] :offline
         
     | 
| 
       42 
44 
     | 
    
         
             
                    #
         
     | 
| 
       43 
45 
     | 
    
         | 
| 
       44 
46 
     | 
    
         
             
                    def network_conditions=(conditions)
         
     | 
| 
      
 47 
     | 
    
         
            +
                      conditions[:latency] ||= 0
         
     | 
| 
      
 48 
     | 
    
         
            +
                      unless conditions.key?(:throughput)
         
     | 
| 
      
 49 
     | 
    
         
            +
                        conditions[:download_throughput] ||= -1
         
     | 
| 
      
 50 
     | 
    
         
            +
                        conditions[:upload_throughput] ||= -1
         
     | 
| 
      
 51 
     | 
    
         
            +
                      end
         
     | 
| 
      
 52 
     | 
    
         
            +
                      conditions[:offline] = false unless conditions.key?(:offline)
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
       45 
54 
     | 
    
         
             
                      @bridge.network_conditions = conditions
         
     | 
| 
       46 
55 
     | 
    
         
             
                    end
         
     | 
| 
       47 
56 
     | 
    
         | 
| 
      
 57 
     | 
    
         
            +
                    #
         
     | 
| 
      
 58 
     | 
    
         
            +
                    # Resets Chromium network emulation settings.
         
     | 
| 
      
 59 
     | 
    
         
            +
                    #
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                    def delete_network_conditions
         
     | 
| 
      
 62 
     | 
    
         
            +
                      @bridge.delete_network_conditions
         
     | 
| 
      
 63 
     | 
    
         
            +
                    end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
       48 
65 
     | 
    
         
             
                  end # HasNetworkConditions
         
     | 
| 
       49 
66 
     | 
    
         
             
                end # DriverExtensions
         
     | 
| 
       50 
67 
     | 
    
         
             
              end # WebDriver
         
     | 
| 
         @@ -28,39 +28,108 @@ module Selenium 
     | 
|
| 
       28 
28 
     | 
    
         
             
                    # a stubbed response instead.
         
     | 
| 
       29 
29 
     | 
    
         
             
                    #
         
     | 
| 
       30 
30 
     | 
    
         
             
                    # @example Log requests and pass through
         
     | 
| 
       31 
     | 
    
         
            -
                    #   driver.intercept do |request|
         
     | 
| 
      
 31 
     | 
    
         
            +
                    #   driver.intercept do |request, &continue|
         
     | 
| 
       32 
32 
     | 
    
         
             
                    #     puts "#{request.method} #{request.url}"
         
     | 
| 
       33 
     | 
    
         
            -
                    #     request 
     | 
| 
      
 33 
     | 
    
         
            +
                    #     continue.call(request)
         
     | 
| 
       34 
34 
     | 
    
         
             
                    #   end
         
     | 
| 
       35 
35 
     | 
    
         
             
                    #
         
     | 
| 
       36 
     | 
    
         
            -
                    # @example Stub  
     | 
| 
       37 
     | 
    
         
            -
                    #   driver.intercept do |request|
         
     | 
| 
      
 36 
     | 
    
         
            +
                    # @example Stub requests for images
         
     | 
| 
      
 37 
     | 
    
         
            +
                    #   driver.intercept do |request, &continue|
         
     | 
| 
       38 
38 
     | 
    
         
             
                    #     if request.url.match?(/\.png$/)
         
     | 
| 
       39 
     | 
    
         
            -
                    #       request. 
     | 
| 
       40 
     | 
    
         
            -
                    #     else
         
     | 
| 
       41 
     | 
    
         
            -
                    #       request.continue
         
     | 
| 
      
 39 
     | 
    
         
            +
                    #       request.url = 'https://upload.wikimedia.org/wikipedia/commons/d/d5/Selenium_Logo.png'
         
     | 
| 
       42 
40 
     | 
    
         
             
                    #     end
         
     | 
| 
      
 41 
     | 
    
         
            +
                    #     continue.call(request)
         
     | 
| 
       43 
42 
     | 
    
         
             
                    #   end
         
     | 
| 
       44 
43 
     | 
    
         
             
                    #
         
     | 
| 
       45 
     | 
    
         
            -
                    # @ 
     | 
| 
       46 
     | 
    
         
            -
                    #  
     | 
| 
      
 44 
     | 
    
         
            +
                    # @example Log responses and pass through
         
     | 
| 
      
 45 
     | 
    
         
            +
                    #   driver.intercept do |request, &continue|
         
     | 
| 
      
 46 
     | 
    
         
            +
                    #     continue.call(request) do |response|
         
     | 
| 
      
 47 
     | 
    
         
            +
                    #       puts "#{response.code} #{response.body}"
         
     | 
| 
      
 48 
     | 
    
         
            +
                    #     end
         
     | 
| 
      
 49 
     | 
    
         
            +
                    #   end
         
     | 
| 
      
 50 
     | 
    
         
            +
                    #
         
     | 
| 
      
 51 
     | 
    
         
            +
                    # @example Mutate specific response
         
     | 
| 
      
 52 
     | 
    
         
            +
                    #   driver.intercept do |request, &continue|
         
     | 
| 
      
 53 
     | 
    
         
            +
                    #     continue.call(request) do |response|
         
     | 
| 
      
 54 
     | 
    
         
            +
                    #       response.body << 'Added by Selenium!' if request.url.include?('/myurl')
         
     | 
| 
      
 55 
     | 
    
         
            +
                    #     end
         
     | 
| 
      
 56 
     | 
    
         
            +
                    #   end
         
     | 
| 
      
 57 
     | 
    
         
            +
                    #
         
     | 
| 
      
 58 
     | 
    
         
            +
                    # @param [Proc] block which is called when request is intercepted
         
     | 
| 
      
 59 
     | 
    
         
            +
                    # @yieldparam [DevTools::Request] request
         
     | 
| 
      
 60 
     | 
    
         
            +
                    # @yieldparam [Proc] continue block which proceeds with the request and optionally yields response
         
     | 
| 
       47 
61 
     | 
    
         
             
                    #
         
     | 
| 
       48 
62 
     | 
    
         | 
| 
       49 
     | 
    
         
            -
                    def intercept
         
     | 
| 
      
 63 
     | 
    
         
            +
                    def intercept(&block)
         
     | 
| 
       50 
64 
     | 
    
         
             
                      devtools.network.set_cache_disabled(cache_disabled: true)
         
     | 
| 
       51 
65 
     | 
    
         
             
                      devtools.fetch.on(:request_paused) do |params|
         
     | 
| 
       52 
     | 
    
         
            -
                         
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
                          id 
     | 
| 
       55 
     | 
    
         
            -
             
     | 
| 
       56 
     | 
    
         
            -
                           
     | 
| 
       57 
     | 
    
         
            -
             
     | 
| 
      
 66 
     | 
    
         
            +
                        id = params['requestId']
         
     | 
| 
      
 67 
     | 
    
         
            +
                        if params.key?('responseStatusCode') || params.key?('responseErrorReason')
         
     | 
| 
      
 68 
     | 
    
         
            +
                          intercept_response(id, params, &pending_response_requests.delete(id))
         
     | 
| 
      
 69 
     | 
    
         
            +
                        else
         
     | 
| 
      
 70 
     | 
    
         
            +
                          intercept_request(id, params, &block)
         
     | 
| 
      
 71 
     | 
    
         
            +
                        end
         
     | 
| 
      
 72 
     | 
    
         
            +
                      end
         
     | 
| 
      
 73 
     | 
    
         
            +
                      devtools.fetch.enable(patterns: [{requestStage: 'Request'}, {requestStage: 'Response'}])
         
     | 
| 
      
 74 
     | 
    
         
            +
                    end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                    private
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                    def pending_response_requests
         
     | 
| 
      
 79 
     | 
    
         
            +
                      @pending_response_requests ||= {}
         
     | 
| 
      
 80 
     | 
    
         
            +
                    end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                    def intercept_request(id, params, &block)
         
     | 
| 
      
 83 
     | 
    
         
            +
                      original = DevTools::Request.from(id, params)
         
     | 
| 
      
 84 
     | 
    
         
            +
                      mutable = DevTools::Request.from(id, params)
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                      block.call(mutable) do |&continue| # rubocop:disable Performance/RedundantBlockCall
         
     | 
| 
      
 87 
     | 
    
         
            +
                        pending_response_requests[id] = continue
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                        if original == mutable
         
     | 
| 
      
 90 
     | 
    
         
            +
                          devtools.fetch.continue_request(request_id: id)
         
     | 
| 
      
 91 
     | 
    
         
            +
                        else
         
     | 
| 
      
 92 
     | 
    
         
            +
                          devtools.fetch.continue_request(
         
     | 
| 
      
 93 
     | 
    
         
            +
                            request_id: id,
         
     | 
| 
      
 94 
     | 
    
         
            +
                            url: mutable.url,
         
     | 
| 
      
 95 
     | 
    
         
            +
                            method: mutable.method,
         
     | 
| 
      
 96 
     | 
    
         
            +
                            post_data: mutable.post_data,
         
     | 
| 
      
 97 
     | 
    
         
            +
                            headers: mutable.headers.map do |k, v|
         
     | 
| 
      
 98 
     | 
    
         
            +
                              {name: k, value: v}
         
     | 
| 
      
 99 
     | 
    
         
            +
                            end
         
     | 
| 
      
 100 
     | 
    
         
            +
                          )
         
     | 
| 
      
 101 
     | 
    
         
            +
                        end
         
     | 
| 
      
 102 
     | 
    
         
            +
                      end
         
     | 
| 
      
 103 
     | 
    
         
            +
                    end
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                    def intercept_response(id, params)
         
     | 
| 
      
 106 
     | 
    
         
            +
                      return devtools.fetch.continue_request(request_id: id) unless block_given?
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                      body = fetch_response_body(id)
         
     | 
| 
      
 109 
     | 
    
         
            +
                      original = DevTools::Response.from(id, body, params)
         
     | 
| 
      
 110 
     | 
    
         
            +
                      mutable = DevTools::Response.from(id, body, params)
         
     | 
| 
      
 111 
     | 
    
         
            +
                      yield mutable
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
                      if original == mutable
         
     | 
| 
      
 114 
     | 
    
         
            +
                        devtools.fetch.continue_request(request_id: id)
         
     | 
| 
      
 115 
     | 
    
         
            +
                      else
         
     | 
| 
      
 116 
     | 
    
         
            +
                        devtools.fetch.fulfill_request(
         
     | 
| 
      
 117 
     | 
    
         
            +
                          request_id: id,
         
     | 
| 
      
 118 
     | 
    
         
            +
                          body: (Base64.strict_encode64(mutable.body) if mutable.body),
         
     | 
| 
      
 119 
     | 
    
         
            +
                          response_code: mutable.code,
         
     | 
| 
      
 120 
     | 
    
         
            +
                          response_headers: mutable.headers.map do |k, v|
         
     | 
| 
      
 121 
     | 
    
         
            +
                            {name: k, value: v}
         
     | 
| 
      
 122 
     | 
    
         
            +
                          end
         
     | 
| 
       58 
123 
     | 
    
         
             
                        )
         
     | 
| 
       59 
     | 
    
         
            -
                        yield request
         
     | 
| 
       60 
124 
     | 
    
         
             
                      end
         
     | 
| 
       61 
     | 
    
         
            -
                      devtools.fetch.enable
         
     | 
| 
       62 
125 
     | 
    
         
             
                    end
         
     | 
| 
       63 
126 
     | 
    
         | 
| 
      
 127 
     | 
    
         
            +
                    def fetch_response_body(id)
         
     | 
| 
      
 128 
     | 
    
         
            +
                      devtools.fetch.get_response_body(request_id: id).dig('result', 'body')
         
     | 
| 
      
 129 
     | 
    
         
            +
                    rescue Error::WebDriverError
         
     | 
| 
      
 130 
     | 
    
         
            +
                      # CDP fails to get body on certain responses (301) and raises:
         
     | 
| 
      
 131 
     | 
    
         
            +
                      # Can only get response body on requests captured after headers received.
         
     | 
| 
      
 132 
     | 
    
         
            +
                    end
         
     | 
| 
       64 
133 
     | 
    
         
             
                  end # HasNetworkInterception
         
     | 
| 
       65 
134 
     | 
    
         
             
                end # DriverExtensions
         
     | 
| 
       66 
135 
     | 
    
         
             
              end # WebDriver
         
     | 
| 
         @@ -23,26 +23,26 @@ module Selenium 
     | 
|
| 
       23 
23 
     | 
    
         
             
                  module HasPermissions
         
     | 
| 
       24 
24 
     | 
    
         | 
| 
       25 
25 
     | 
    
         
             
                    #
         
     | 
| 
       26 
     | 
    
         
            -
                    #  
     | 
| 
      
 26 
     | 
    
         
            +
                    # Set one permission.
         
     | 
| 
       27 
27 
     | 
    
         
             
                    #
         
     | 
| 
       28 
     | 
    
         
            -
                    # @ 
     | 
| 
      
 28 
     | 
    
         
            +
                    # @param [String] name which permission to set
         
     | 
| 
      
 29 
     | 
    
         
            +
                    # @param [String] value what to set the permission to
         
     | 
| 
       29 
30 
     | 
    
         
             
                    #
         
     | 
| 
       30 
31 
     | 
    
         | 
| 
       31 
     | 
    
         
            -
                    def  
     | 
| 
       32 
     | 
    
         
            -
                      @bridge. 
     | 
| 
      
 32 
     | 
    
         
            +
                    def add_permission(name, value)
         
     | 
| 
      
 33 
     | 
    
         
            +
                      @bridge.set_permission(name, value)
         
     | 
| 
       33 
34 
     | 
    
         
             
                    end
         
     | 
| 
       34 
35 
     | 
    
         | 
| 
       35 
36 
     | 
    
         
             
                    #
         
     | 
| 
       36 
     | 
    
         
            -
                    #  
     | 
| 
      
 37 
     | 
    
         
            +
                    # Set multiple permissions.
         
     | 
| 
       37 
38 
     | 
    
         
             
                    #
         
     | 
| 
       38 
     | 
    
         
            -
                    # @ 
     | 
| 
       39 
     | 
    
         
            -
                    #   driver.permissions = {'getUserMedia' => true}
         
     | 
| 
       40 
     | 
    
         
            -
                    #
         
     | 
| 
       41 
     | 
    
         
            -
                    # @param [Hash<Symbol, Boolean>] permissions
         
     | 
| 
      
 39 
     | 
    
         
            +
                    # @param [Hash] opt key/value pairs to set permissions
         
     | 
| 
       42 
40 
     | 
    
         
             
                    #
         
     | 
| 
       43 
41 
     | 
    
         | 
| 
       44 
     | 
    
         
            -
                    def  
     | 
| 
       45 
     | 
    
         
            -
                       
     | 
| 
      
 42 
     | 
    
         
            +
                    def add_permissions(opt)
         
     | 
| 
      
 43 
     | 
    
         
            +
                      opt.each do |key, value|
         
     | 
| 
      
 44 
     | 
    
         
            +
                        @bridge.set_permission(key, value)
         
     | 
| 
      
 45 
     | 
    
         
            +
                      end
         
     | 
| 
       46 
46 
     | 
    
         
             
                    end
         
     | 
| 
       47 
47 
     | 
    
         | 
| 
       48 
48 
     | 
    
         
             
                  end # HasPermissions
         
     | 
| 
         @@ -30,14 +30,14 @@ module Selenium 
     | 
|
| 
       30 
30 
     | 
    
         | 
| 
       31 
31 
     | 
    
         
             
                  def as_json(*)
         
     | 
| 
       32 
32 
     | 
    
         
             
                    {
         
     | 
| 
       33 
     | 
    
         
            -
                      'level' => level,
         
     | 
| 
       34 
33 
     | 
    
         
             
                      'timestamp' => timestamp,
         
     | 
| 
      
 34 
     | 
    
         
            +
                      'level' => level,
         
     | 
| 
       35 
35 
     | 
    
         
             
                      'message' => message
         
     | 
| 
       36 
36 
     | 
    
         
             
                    }
         
     | 
| 
       37 
37 
     | 
    
         
             
                  end
         
     | 
| 
       38 
38 
     | 
    
         | 
| 
       39 
39 
     | 
    
         
             
                  def to_s
         
     | 
| 
       40 
     | 
    
         
            -
                    "#{ 
     | 
| 
      
 40 
     | 
    
         
            +
                    "#{time} #{level}: #{message}"
         
     | 
| 
       41 
41 
     | 
    
         
             
                  end
         
     | 
| 
       42 
42 
     | 
    
         | 
| 
       43 
43 
     | 
    
         
             
                  def time
         
     | 
| 
         @@ -104,25 +104,19 @@ module Selenium 
     | 
|
| 
       104 
104 
     | 
    
         
             
                    @timeouts ||= Timeouts.new(@bridge)
         
     | 
| 
       105 
105 
     | 
    
         
             
                  end
         
     | 
| 
       106 
106 
     | 
    
         | 
| 
       107 
     | 
    
         
            -
                  #
         
     | 
| 
       108 
     | 
    
         
            -
                  # @api beta This API may be changed or removed in a future release.
         
     | 
| 
       109 
     | 
    
         
            -
                  #
         
     | 
| 
       110 
     | 
    
         
            -
             
     | 
| 
       111 
107 
     | 
    
         
             
                  def logs
         
     | 
| 
       112 
108 
     | 
    
         
             
                    WebDriver.logger.deprecate('Manager#logs', 'Chrome::Driver#logs')
         
     | 
| 
       113 
109 
     | 
    
         
             
                    @logs ||= Logs.new(@bridge)
         
     | 
| 
       114 
110 
     | 
    
         
             
                  end
         
     | 
| 
       115 
111 
     | 
    
         | 
| 
       116 
112 
     | 
    
         
             
                  #
         
     | 
| 
       117 
     | 
    
         
            -
                  # Create a new top-level browsing context
         
     | 
| 
       118 
     | 
    
         
            -
                  # https://w3c.github.io/webdriver/#new-window
         
     | 
| 
       119 
113 
     | 
    
         
             
                  # @param type [Symbol] Supports two values: :tab and :window.
         
     | 
| 
       120 
     | 
    
         
            -
                  #  Use :tab if you'd like the new window to share an OS-level window
         
     | 
| 
       121 
     | 
    
         
            -
                  #  with the current browsing context.
         
     | 
| 
       122 
     | 
    
         
            -
                  #  Use :window otherwise
         
     | 
| 
       123 
114 
     | 
    
         
             
                  # @return [String] The value of the window handle
         
     | 
| 
       124 
115 
     | 
    
         
             
                  #
         
     | 
| 
       125 
116 
     | 
    
         
             
                  def new_window(type = :tab)
         
     | 
| 
      
 117 
     | 
    
         
            +
                    WebDriver.logger.deprecate('Manager#new_window', 'TargetLocator#new_window', id: :new_window) do
         
     | 
| 
      
 118 
     | 
    
         
            +
                      'e.g., `driver.switch_to.new_window(:tab)`'
         
     | 
| 
      
 119 
     | 
    
         
            +
                    end
         
     | 
| 
       126 
120 
     | 
    
         
             
                    case type
         
     | 
| 
       127 
121 
     | 
    
         
             
                    when :tab, :window
         
     | 
| 
       128 
122 
     | 
    
         
             
                      result = @bridge.new_window(type)
         
     | 
| 
         @@ -137,10 +131,6 @@ module Selenium 
     | 
|
| 
       137 
131 
     | 
    
         
             
                    end
         
     | 
| 
       138 
132 
     | 
    
         
             
                  end
         
     | 
| 
       139 
133 
     | 
    
         | 
| 
       140 
     | 
    
         
            -
                  #
         
     | 
| 
       141 
     | 
    
         
            -
                  # @api beta This API may be changed or removed in a future release.
         
     | 
| 
       142 
     | 
    
         
            -
                  #
         
     | 
| 
       143 
     | 
    
         
            -
             
     | 
| 
       144 
134 
     | 
    
         
             
                  def window
         
     | 
| 
       145 
135 
     | 
    
         
             
                    @window ||= Window.new(@bridge)
         
     | 
| 
       146 
136 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -21,7 +21,8 @@ module Selenium 
     | 
|
| 
       21 
21 
     | 
    
         
             
              module WebDriver
         
     | 
| 
       22 
22 
     | 
    
         
             
                class Options
         
     | 
| 
       23 
23 
     | 
    
         
             
                  W3C_OPTIONS = %i[browser_name browser_version platform_name accept_insecure_certs page_load_strategy proxy
         
     | 
| 
       24 
     | 
    
         
            -
                                   set_window_rect timeouts unhandled_prompt_behavior strict_file_interactability 
     | 
| 
      
 24 
     | 
    
         
            +
                                   set_window_rect timeouts unhandled_prompt_behavior strict_file_interactability
         
     | 
| 
      
 25 
     | 
    
         
            +
                                   web_socket_url].freeze
         
     | 
| 
       25 
26 
     | 
    
         | 
| 
       26 
27 
     | 
    
         
             
                  class << self
         
     | 
| 
       27 
28 
     | 
    
         
             
                    attr_reader :driver_path
         
     | 
| 
         @@ -90,7 +91,8 @@ module Selenium 
     | 
|
| 
       90 
91 
     | 
    
         
             
                  # @param [Boolean, String, Integer] value Value of the option
         
     | 
| 
       91 
92 
     | 
    
         
             
                  #
         
     | 
| 
       92 
93 
     | 
    
         | 
| 
       93 
     | 
    
         
            -
                  def add_option(name, value)
         
     | 
| 
      
 94 
     | 
    
         
            +
                  def add_option(name, value = nil)
         
     | 
| 
      
 95 
     | 
    
         
            +
                    @options[name.keys.first] = name.values.first if value.nil? && name.is_a?(Hash)
         
     | 
| 
       94 
96 
     | 
    
         
             
                    @options[name] = value
         
     | 
| 
       95 
97 
     | 
    
         
             
                  end
         
     | 
| 
       96 
98 
     | 
    
         | 
| 
         @@ -123,10 +125,14 @@ module Selenium 
     | 
|
| 
       123 
125 
     | 
    
         | 
| 
       124 
126 
     | 
    
         
             
                  private
         
     | 
| 
       125 
127 
     | 
    
         | 
| 
      
 128 
     | 
    
         
            +
                  def w3c?(key)
         
     | 
| 
      
 129 
     | 
    
         
            +
                    W3C_OPTIONS.include?(key) || key.to_s.include?(':')
         
     | 
| 
      
 130 
     | 
    
         
            +
                  end
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
       126 
132 
     | 
    
         
             
                  def process_w3c_options(options)
         
     | 
| 
       127 
     | 
    
         
            -
                    w3c_options = options.select { |key, _val|  
     | 
| 
      
 133 
     | 
    
         
            +
                    w3c_options = options.select { |key, _val| w3c?(key) }
         
     | 
| 
       128 
134 
     | 
    
         
             
                    w3c_options[:unhandled_prompt_behavior] &&= w3c_options[:unhandled_prompt_behavior]&.to_s&.tr('_', ' ')
         
     | 
| 
       129 
     | 
    
         
            -
                    options.delete_if { |key, _val|  
     | 
| 
      
 135 
     | 
    
         
            +
                    options.delete_if { |key, _val| w3c?(key) }
         
     | 
| 
       130 
136 
     | 
    
         
             
                    w3c_options
         
     | 
| 
       131 
137 
     | 
    
         
             
                  end
         
     | 
| 
       132 
138 
     | 
    
         | 
| 
         @@ -173,6 +179,8 @@ module Selenium 
     | 
|
| 
       173 
179 
     | 
    
         
             
                  def camel_case(str)
         
     | 
| 
       174 
180 
     | 
    
         
             
                    str.gsub(/_([a-z])/) { Regexp.last_match(1).upcase }
         
     | 
| 
       175 
181 
     | 
    
         
             
                  end
         
     | 
| 
       176 
     | 
    
         
            -
                end 
     | 
| 
      
 182 
     | 
    
         
            +
                end
         
     | 
| 
      
 183 
     | 
    
         
            +
             
     | 
| 
      
 184 
     | 
    
         
            +
                # Options
         
     | 
| 
       177 
185 
     | 
    
         
             
              end # WebDriver
         
     | 
| 
       178 
186 
     | 
    
         
             
            end # Selenium
         
     | 
| 
         @@ -73,16 +73,10 @@ module Selenium 
     | 
|
| 
       73 
73 
     | 
    
         
             
                    def from_json(json)
         
     | 
| 
       74 
74 
     | 
    
         
             
                      data = decoded(json)
         
     | 
| 
       75 
75 
     | 
    
         | 
| 
       76 
     | 
    
         
            -
                       
     | 
| 
       77 
     | 
    
         
            -
                      # can't use Dir.mktmpdir(&blk) because of http://jira.codehaus.org/browse/JRUBY-4082
         
     | 
| 
       78 
     | 
    
         
            -
                      tmp_dir = Dir.mktmpdir
         
     | 
| 
       79 
     | 
    
         
            -
                      begin
         
     | 
| 
       80 
     | 
    
         
            -
                        zip_path = File.join(tmp_dir, "webdriver-profile-duplicate-#{json.hash}.zip")
         
     | 
| 
      
 76 
     | 
    
         
            +
                      Tempfile.create do |zip_path|
         
     | 
| 
       81 
77 
     | 
    
         
             
                        File.open(zip_path, 'wb') { |zip_file| zip_file << Base64.decode64(data) }
         
     | 
| 
       82 
78 
     | 
    
         | 
| 
       83 
79 
     | 
    
         
             
                        new Zipper.unzip(zip_path)
         
     | 
| 
       84 
     | 
    
         
            -
                      ensure
         
     | 
| 
       85 
     | 
    
         
            -
                        FileUtils.rm_rf tmp_dir
         
     | 
| 
       86 
80 
     | 
    
         
             
                      end
         
     | 
| 
       87 
81 
     | 
    
         
             
                    end
         
     | 
| 
       88 
82 
     | 
    
         
             
                  end # ClassMethods
         
     | 
| 
         @@ -65,26 +65,37 @@ module Selenium 
     | 
|
| 
       65 
65 
     | 
    
         
             
                    arr << Errno::EALREADY if Platform.wsl?
         
     | 
| 
       66 
66 
     | 
    
         
             
                  }.freeze
         
     | 
| 
       67 
67 
     | 
    
         | 
| 
       68 
     | 
    
         
            -
                   
     | 
| 
       69 
     | 
    
         
            -
                     
     | 
| 
       70 
     | 
    
         
            -
                     
     | 
| 
       71 
     | 
    
         
            -
                     
     | 
| 
       72 
     | 
    
         
            -
             
     | 
| 
       73 
     | 
    
         
            -
             
     | 
| 
       74 
     | 
    
         
            -
             
     | 
| 
       75 
     | 
    
         
            -
             
     | 
| 
       76 
     | 
    
         
            -
             
     | 
| 
       77 
     | 
    
         
            -
             
     | 
| 
       78 
     | 
    
         
            -
                     
     | 
| 
       79 
     | 
    
         
            -
                       
     | 
| 
      
 68 
     | 
    
         
            +
                  if Platform.jruby?
         
     | 
| 
      
 69 
     | 
    
         
            +
                    # we use a plain TCPSocket here since JRuby has issues closing socket
         
     | 
| 
      
 70 
     | 
    
         
            +
                    # see https://github.com/jruby/jruby/issues/5709
         
     | 
| 
      
 71 
     | 
    
         
            +
                    def listening?
         
     | 
| 
      
 72 
     | 
    
         
            +
                      TCPSocket.new(@host, @port).close
         
     | 
| 
      
 73 
     | 
    
         
            +
                      true
         
     | 
| 
      
 74 
     | 
    
         
            +
                    rescue *NOT_CONNECTED_ERRORS
         
     | 
| 
      
 75 
     | 
    
         
            +
                      false
         
     | 
| 
      
 76 
     | 
    
         
            +
                    end
         
     | 
| 
      
 77 
     | 
    
         
            +
                  else
         
     | 
| 
      
 78 
     | 
    
         
            +
                    def listening?
         
     | 
| 
      
 79 
     | 
    
         
            +
                      addr     = Socket.getaddrinfo(@host, @port, Socket::AF_INET, Socket::SOCK_STREAM)
         
     | 
| 
      
 80 
     | 
    
         
            +
                      sock     = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
         
     | 
| 
      
 81 
     | 
    
         
            +
                      sockaddr = Socket.pack_sockaddr_in(@port, addr[0][3])
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 84 
     | 
    
         
            +
                        sock.connect_nonblock sockaddr
         
     | 
| 
      
 85 
     | 
    
         
            +
                      rescue Errno::EINPROGRESS
         
     | 
| 
      
 86 
     | 
    
         
            +
                        retry if socket_writable?(sock) && conn_completed?(sock)
         
     | 
| 
      
 87 
     | 
    
         
            +
                        raise Errno::ECONNREFUSED
         
     | 
| 
      
 88 
     | 
    
         
            +
                      rescue *CONNECTED_ERRORS
         
     | 
| 
      
 89 
     | 
    
         
            +
                        # yay!
         
     | 
| 
      
 90 
     | 
    
         
            +
                      end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                      sock.close
         
     | 
| 
      
 93 
     | 
    
         
            +
                      true
         
     | 
| 
      
 94 
     | 
    
         
            +
                    rescue *NOT_CONNECTED_ERRORS
         
     | 
| 
      
 95 
     | 
    
         
            +
                      sock&.close
         
     | 
| 
      
 96 
     | 
    
         
            +
                      WebDriver.logger.debug("polling for socket on #{[@host, @port].inspect}")
         
     | 
| 
      
 97 
     | 
    
         
            +
                      false
         
     | 
| 
       80 
98 
     | 
    
         
             
                    end
         
     | 
| 
       81 
     | 
    
         
            -
             
     | 
| 
       82 
     | 
    
         
            -
                    sock.close
         
     | 
| 
       83 
     | 
    
         
            -
                    true
         
     | 
| 
       84 
     | 
    
         
            -
                  rescue *NOT_CONNECTED_ERRORS
         
     | 
| 
       85 
     | 
    
         
            -
                    sock&.close
         
     | 
| 
       86 
     | 
    
         
            -
                    WebDriver.logger.debug("polling for socket on #{[@host, @port].inspect}")
         
     | 
| 
       87 
     | 
    
         
            -
                    false
         
     | 
| 
       88 
99 
     | 
    
         
             
                  end
         
     | 
| 
       89 
100 
     | 
    
         | 
| 
       90 
101 
     | 
    
         
             
                  def socket_writable?(sock)
         
     | 
| 
         @@ -44,6 +44,34 @@ module Selenium 
     | 
|
| 
       44 
44 
     | 
    
         
             
                    @bridge.switch_to_parent_frame
         
     | 
| 
       45 
45 
     | 
    
         
             
                  end
         
     | 
| 
       46 
46 
     | 
    
         | 
| 
      
 47 
     | 
    
         
            +
                  #
         
     | 
| 
      
 48 
     | 
    
         
            +
                  # Switch to a new top-level browsing context
         
     | 
| 
      
 49 
     | 
    
         
            +
                  #
         
     | 
| 
      
 50 
     | 
    
         
            +
                  # @param type either :tab or :window
         
     | 
| 
      
 51 
     | 
    
         
            +
                  #
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                  def new_window(type = :window)
         
     | 
| 
      
 54 
     | 
    
         
            +
                    unless %i[window tab].include?(type)
         
     | 
| 
      
 55 
     | 
    
         
            +
                      raise ArgumentError, "Valid types are :tab and :window, received: #{type.inspect}"
         
     | 
| 
      
 56 
     | 
    
         
            +
                    end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                    handle = @bridge.new_window(type)['handle']
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                    if block_given?
         
     | 
| 
      
 61 
     | 
    
         
            +
                      execute_and_close = proc do
         
     | 
| 
      
 62 
     | 
    
         
            +
                        yield(self)
         
     | 
| 
      
 63 
     | 
    
         
            +
                        begin
         
     | 
| 
      
 64 
     | 
    
         
            +
                          @bridge.close
         
     | 
| 
      
 65 
     | 
    
         
            +
                        rescue Error::NoSuchWindowError
         
     | 
| 
      
 66 
     | 
    
         
            +
                          # window already closed
         
     | 
| 
      
 67 
     | 
    
         
            +
                        end
         
     | 
| 
      
 68 
     | 
    
         
            +
                      end
         
     | 
| 
      
 69 
     | 
    
         
            +
                      window(handle, &execute_and_close)
         
     | 
| 
      
 70 
     | 
    
         
            +
                    else
         
     | 
| 
      
 71 
     | 
    
         
            +
                      window(handle)
         
     | 
| 
      
 72 
     | 
    
         
            +
                    end
         
     | 
| 
      
 73 
     | 
    
         
            +
                  end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
       47 
75 
     | 
    
         
             
                  #
         
     | 
| 
       48 
76 
     | 
    
         
             
                  # switch to the given window handle
         
     | 
| 
       49 
77 
     | 
    
         
             
                  #
         
     | 
| 
         @@ -24,22 +24,49 @@ module Selenium 
     | 
|
| 
       24 
24 
     | 
    
         
             
                    @bridge = bridge
         
     | 
| 
       25 
25 
     | 
    
         
             
                  end
         
     | 
| 
       26 
26 
     | 
    
         | 
| 
      
 27 
     | 
    
         
            +
                  #
         
     | 
| 
      
 28 
     | 
    
         
            +
                  # Gets the amount of time the driver should wait when searching for elements.
         
     | 
| 
      
 29 
     | 
    
         
            +
                  #
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  def implicit_wait
         
     | 
| 
      
 32 
     | 
    
         
            +
                    Float(@bridge.timeouts['implicit']) / 1000
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
       27 
35 
     | 
    
         
             
                  #
         
     | 
| 
       28 
36 
     | 
    
         
             
                  # Set the amount of time the driver should wait when searching for elements.
         
     | 
| 
       29 
37 
     | 
    
         
             
                  #
         
     | 
| 
       30 
38 
     | 
    
         | 
| 
       31 
39 
     | 
    
         
             
                  def implicit_wait=(seconds)
         
     | 
| 
       32 
     | 
    
         
            -
                    @bridge. 
     | 
| 
      
 40 
     | 
    
         
            +
                    @bridge.timeouts = {'implicit' => Integer(seconds * 1000)}
         
     | 
| 
       33 
41 
     | 
    
         
             
                  end
         
     | 
| 
       34 
42 
     | 
    
         | 
| 
      
 43 
     | 
    
         
            +
                  #
         
     | 
| 
      
 44 
     | 
    
         
            +
                  # Gets the amount of time to wait for an asynchronous script to finish
         
     | 
| 
      
 45 
     | 
    
         
            +
                  # execution before throwing an error.
         
     | 
| 
      
 46 
     | 
    
         
            +
                  #
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                  def script
         
     | 
| 
      
 49 
     | 
    
         
            +
                    Float(@bridge.timeouts['script']) / 1000
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
                  alias_method :script_timeout, :script
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
       35 
53 
     | 
    
         
             
                  #
         
     | 
| 
       36 
54 
     | 
    
         
             
                  # Sets the amount of time to wait for an asynchronous script to finish
         
     | 
| 
       37 
55 
     | 
    
         
             
                  # execution before throwing an error. If the timeout is negative, then the
         
     | 
| 
       38 
56 
     | 
    
         
             
                  # script will be allowed to run indefinitely.
         
     | 
| 
       39 
57 
     | 
    
         
             
                  #
         
     | 
| 
       40 
58 
     | 
    
         | 
| 
       41 
     | 
    
         
            -
                  def  
     | 
| 
       42 
     | 
    
         
            -
                    @bridge. 
     | 
| 
      
 59 
     | 
    
         
            +
                  def script=(seconds)
         
     | 
| 
      
 60 
     | 
    
         
            +
                    @bridge.timeouts = {'script' => Integer(seconds * 1000)}
         
     | 
| 
      
 61 
     | 
    
         
            +
                  end
         
     | 
| 
      
 62 
     | 
    
         
            +
                  alias_method :script_timeout=, :script=
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                  #
         
     | 
| 
      
 65 
     | 
    
         
            +
                  # Gets the amount of time to wait for a page load to complete before throwing an error.
         
     | 
| 
      
 66 
     | 
    
         
            +
                  #
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                  def page_load
         
     | 
| 
      
 69 
     | 
    
         
            +
                    Float(@bridge.timeouts['pageLoad']) / 1000
         
     | 
| 
       43 
70 
     | 
    
         
             
                  end
         
     | 
| 
       44 
71 
     | 
    
         | 
| 
       45 
72 
     | 
    
         
             
                  #
         
     | 
| 
         @@ -48,7 +75,7 @@ module Selenium 
     | 
|
| 
       48 
75 
     | 
    
         
             
                  #
         
     | 
| 
       49 
76 
     | 
    
         | 
| 
       50 
77 
     | 
    
         
             
                  def page_load=(seconds)
         
     | 
| 
       51 
     | 
    
         
            -
                    @bridge. 
     | 
| 
      
 78 
     | 
    
         
            +
                    @bridge.timeouts = {'pageLoad' => Integer(seconds * 1000)}
         
     | 
| 
       52 
79 
     | 
    
         
             
                  end
         
     | 
| 
       53 
80 
     | 
    
         
             
                end # Timeouts
         
     | 
| 
       54 
81 
     | 
    
         
             
              end # WebDriver
         
     | 
| 
         @@ -72,16 +72,8 @@ module Selenium 
     | 
|
| 
       72 
72 
     | 
    
         
             
                    private
         
     | 
| 
       73 
73 
     | 
    
         | 
| 
       74 
74 
     | 
    
         
             
                    def with_tmp_zip(&blk)
         
     | 
| 
       75 
     | 
    
         
            -
                       
     | 
| 
       76 
     | 
    
         
            -
                      # can't use Dir.mktmpdir(&blk) because of http://jira.codehaus.org/browse/JRUBY-4082
         
     | 
| 
       77 
     | 
    
         
            -
                      tmp_dir = Dir.mktmpdir
         
     | 
| 
       78 
     | 
    
         
            -
                      zip_path = File.join(tmp_dir, 'webdriver-zip')
         
     | 
| 
       79 
     | 
    
         
            -
             
     | 
| 
       80 
     | 
    
         
            -
                      begin
         
     | 
| 
      
 75 
     | 
    
         
            +
                      Tempfile.create do |zip_path|
         
     | 
| 
       81 
76 
     | 
    
         
             
                        Zip::File.open(zip_path, Zip::File::CREATE, &blk)
         
     | 
| 
       82 
     | 
    
         
            -
                      ensure
         
     | 
| 
       83 
     | 
    
         
            -
                        FileUtils.rm_rf tmp_dir
         
     | 
| 
       84 
     | 
    
         
            -
                        FileUtils.rm_rf zip_path
         
     | 
| 
       85 
77 
     | 
    
         
             
                      end
         
     | 
| 
       86 
78 
     | 
    
         
             
                    end
         
     | 
| 
       87 
79 
     | 
    
         |