lib/browser/browser.rb
# frozen_string_literal: true require "set" require "yaml" require "pathname" require_relative "version" require_relative "detect_version" require_relative "accept_language" require_relative "base" require_relative "safari" require_relative "chrome" require_relative "internet_explorer" require_relative "firefox" require_relative "edge" require_relative "opera" require_relative "blackberry" require_relative "generic" require_relative "phantom_js" require_relative "uc_browser" require_relative "nokia" require_relative "micro_messenger" require_relative "weibo" require_relative "qq" require_relative "alipay" require_relative "electron" require_relative "facebook" require_relative "otter" require_relative "instagram" require_relative "yandex" require_relative "sputnik" require_relative "snapchat" require_relative "bot" require_relative "bot/empty_user_agent_matcher" require_relative "bot/keyword_matcher" require_relative "bot/known_bots_matcher" require_relative "middleware" require_relative "platform" require_relative "device" require_relative "meta" module Browser EMPTY_STRING = "" def self.root @root ||= Pathname.new(File.expand_path("../..", __dir__)) end # Hold the list of browser matchers. # Order is important. def self.matchers @matchers ||= [ Nokia, UCBrowser, PhantomJS, BlackBerry, Opera, Edge, InternetExplorer, Firefox, Otter, Facebook, # must be placed before Chrome and Safari Instagram, # must be placed before Chrome and Safari Snapchat, # must be placed before Chrome and Safari Weibo, # must be placed before Chrome and Safari QQ, # must be placed before Chrome and Safari Alipay, # must be placed before Chrome and Safari Electron, # must be placed before Chrome and Safari Yandex, # must be placed before Chrome and Safari Sputnik, # must be placed before Chrome and Safari Chrome, Safari, MicroMessenger, Generic ] end # Define the rules which define a modern browser. # A rule must be a proc/lambda or any object that implements the method # === and accepts the browser object. # # To redefine all rules, clear the existing rules before adding your own. # # # Only Chrome Canary is considered modern. # Browser.modern_rules.clear # Browser.modern_rules << -> b { b.chrome? && b.version >= "37" } # def self.modern_rules @modern_rules ||= [] end modern_rules.tap do |rules| rules << ->(b) { b.chrome? && b.version.to_i >= 65 } rules << ->(b) { b.safari? && b.version.to_i >= 10 } rules << ->(b) { b.firefox? && b.version.to_i >= 52 } rules << ->(b) { b.ie? && b.version.to_i >= 11 && !b.compatibility_view? } rules << ->(b) { b.edge? && b.version.to_i >= 39 && !b.compatibility_view? } rules << ->(b) { b.opera? && b.version.to_i >= 50 } end def self.new(user_agent, **kwargs) matchers .map {|klass| klass.new(user_agent || EMPTY_STRING, **kwargs) } .find(&:match?) end end