From 938364bcbadab2e1ab357eb9c8184a51f18cc10e Mon Sep 17 00:00:00 2001 From: John Coates Date: Tue, 22 Aug 2023 02:08:08 -0500 Subject: [PATCH 1/3] Draft of service worker support --- lib/ferrum/context.rb | 3 +- lib/ferrum/contexts.rb | 19 +++++++--- lib/ferrum/page.rb | 23 ++++++++---- lib/ferrum/target.rb | 32 +++++++++++++++-- spec/network_spec.rb | 13 +++++++ spec/support/application.rb | 5 +++ spec/support/public/one.png | Bin 0 -> 883 bytes spec/support/views/service_worker.erb | 49 ++++++++++++++++++++++++++ 8 files changed, 130 insertions(+), 14 deletions(-) create mode 100644 spec/support/public/one.png create mode 100644 spec/support/views/service_worker.erb diff --git a/lib/ferrum/context.rb b/lib/ferrum/context.rb index 875680c6..6cad5d9e 100644 --- a/lib/ferrum/context.rb +++ b/lib/ferrum/context.rb @@ -58,11 +58,12 @@ def create_target def add_target(params) target = Target.new(@browser, params) - if target.window? + if target.window? || target.worker? @targets.put_if_absent(target.id, target) else @pendings.put(target, @browser.timeout) end + target end def update_target(target_id, params) diff --git a/lib/ferrum/contexts.rb b/lib/ferrum/contexts.rb index 5e599252..0a48bd20 100644 --- a/lib/ferrum/contexts.rb +++ b/lib/ferrum/contexts.rb @@ -50,19 +50,30 @@ def size private + TARGET_TYPES = %w[page worker].freeze + def subscribe @browser.client.on("Target.targetCreated") do |params| info = params["targetInfo"] - next unless info["type"] == "page" + type = info["type"] + next unless TARGET_TYPES.include?(type) + + target_id = info["targetId"] + @browser.command( + "Target.autoAttachRelated", + targetId: target_id, + waitForDebuggerOnStart: true, # Needed to capture all network requests + filter: [{type: "worker"}]) context_id = info["browserContextId"] - @contexts[context_id]&.add_target(info) + target = @contexts[context_id]&.add_target(info) + target.build if type == "worker" end @browser.client.on("Target.targetInfoChanged") do |params| info = params["targetInfo"] - next unless info["type"] == "page" - + next unless TARGET_TYPES.include?(info["type"]) +q context_id, target_id = info.values_at("browserContextId", "targetId") @contexts[context_id]&.update_target(target_id, info) end diff --git a/lib/ferrum/page.rb b/lib/ferrum/page.rb index 2e83d4b2..38792923 100644 --- a/lib/ferrum/page.rb +++ b/lib/ferrum/page.rb @@ -71,11 +71,12 @@ def reset # @return [Cookies] attr_reader :cookies - def initialize(target_id, browser, proxy: nil) + def initialize(target_id, browser, proxy: nil, type: "page") @frames = Concurrent::Map.new @main_frame = Frame.new(nil, self) @browser = browser @target_id = target_id + @type = type @timeout = @browser.timeout @event = Event.new.tap(&:set) self.proxy = proxy @@ -355,13 +356,21 @@ def subscribe end def prepare_page - command("Page.enable") - command("Runtime.enable") - command("DOM.enable") - command("CSS.enable") - command("Log.enable") + if @type == "page" + command("Page.enable") + command("DOM.enable") + command("CSS.enable") + command("Runtime.enable") + command("Log.enable") + command("ServiceWorker.enable") + end + command("Network.enable") + if @type == "worker" + command("Runtime.runIfWaitingForDebugger") + end + if use_authorized_proxy? network.authorize(user: @proxy_user, password: @proxy_password, @@ -387,6 +396,8 @@ def prepare_page inject_extensions + return if @type == "worker" + width, height = @browser.window_size resize(width: width, height: height) diff --git a/lib/ferrum/target.rb b/lib/ferrum/target.rb index 23a33491..f6a46c32 100644 --- a/lib/ferrum/target.rb +++ b/lib/ferrum/target.rb @@ -7,6 +7,7 @@ class Target # You can create page yourself and assign it to target, used in cuprite # where we enhance page class and build page ourselves. attr_writer :page + attr_reader :connection def initialize(browser, params = nil) @page = nil @@ -23,12 +24,19 @@ def attached? end def page - @page ||= build_page + connection + end + + def network + connection.network + end + + def build(**options) + connection(**options) end def build_page(**options) - maybe_sleep_if_new_window - Page.new(id, @browser, **options) + connection(**options) end def id @@ -59,9 +67,27 @@ def window? !!opener_id end + def page? + @params["type"] == "page" + end + + def worker? + @params["type"] == "worker" + end + def maybe_sleep_if_new_window # Dirty hack because new window doesn't have events at all sleep(NEW_WINDOW_WAIT) if window? end + + def connection(**options) + @connection ||= begin + maybe_sleep_if_new_window if page? + + options.merge!(type: @params["type"]) + + Page.new(id, @browser, **options) + end + end end end diff --git a/spec/network_spec.rb b/spec/network_spec.rb index 5f65a8da..3248609f 100644 --- a/spec/network_spec.rb +++ b/spec/network_spec.rb @@ -30,6 +30,19 @@ browser.go_to("/ferrum/with_js") expect(browser.network.traffic.length).to eq(4) end + + it "keeps track of service workers" do + page.go_to("/ferrum/service_worker") + + browser.network.wait_for_idle + traffic = browser.targets.values.map { _1.network.traffic }.flatten + urls = traffic.map { |e| e.request.url } + + expect(urls.size).to eq(3) + expect(urls.grep(%r{/ferrum/service_worker$}).size).to eq(1) + expect(urls.grep(%r{/ferrum/one.png$}).size).to eq(1) + expect(urls.grep(%r{^blob:}).size).to eq(1) + end end it "#wait_for_idle" do diff --git a/spec/support/application.rb b/spec/support/application.rb index f6d86b00..13b19684 100644 --- a/spec/support/application.rb +++ b/spec/support/application.rb @@ -270,6 +270,11 @@ def authorized?(login, password) File.read("#{FERRUM_PUBLIC}/jquery-ui-1.11.4.min.js") end + get "/ferrum/one.png" do + content_type :png + File.read("#{FERRUM_PUBLIC}/one.png") + end + get "/ferrum/unexist.png" do halt 404 end diff --git a/spec/support/public/one.png b/spec/support/public/one.png new file mode 100644 index 0000000000000000000000000000000000000000..d442972ac4eae4d81058d7b8036806c1e9db706c GIT binary patch literal 883 zcmV-(1C0EMP)6wrcnurFaKl)#-MRzE+T4Z0cv5gmA(%o+|)(ybLLS&}|*rB9stv)=OO^pEhAbWl0hciS=+}*WyH^Mse?CGI`w(dtm`uMTfRK!_IdZ#=W& zFY7LD1o+B5UIun|JtLDw>q^N#&&Pvhd0t;#MJf=Y zTtXaw%wVq{8~{5zNExmG(ULZ=k0B8y$H&0=d9d*>FF>b*q=`-dUf!mKJkRhv5nf&* zX`&wj!?4%S&VZ{c@B0)Ci}(a!ueVxpZE`{ry#Va>lM~?P25BT(0eF&Qud@g#B{~5( z)Q^skcA{MdGe98#45ttPhEoUt!zl!S;S>VEa0&rnIE4T(oI(H?P9Xpcrw{;!!vZ)k z7e_*C2c|-{O9=4*Qz6@hwyZiS@f%6Ni4#FNLXVH}{5MIddOuB$lO#>Z5*IhP|7W!a0TF;S-O}cf<2inu2d78KALy5e(rmp83^DiGV~(12=RTm zl5AuvOfR^S;wSP;d$?MJ2`-wdR&7#h4|zgsTXehgi>4TA*q}>Zh65);p9UGvOg#-! zsI)RaG4g~59Fi@~X-&eF&T>UbwuS_I{hAzjIInazeDQSph0x^j9`)~n4FBWrZRQeM zfWdF!vjb40^8;6!RKVHhLX`17ELOPS9pxSOM61+ax?i|_{y*!E3E8dSIbr|+002ov JPDHLkV1iAmgZBUc literal 0 HcmV?d00001 diff --git a/spec/support/views/service_worker.erb b/spec/support/views/service_worker.erb new file mode 100644 index 00000000..a47ca900 --- /dev/null +++ b/spec/support/views/service_worker.erb @@ -0,0 +1,49 @@ + + + + + + + \ No newline at end of file From a65f7eb3f21bac1188bc5f4a23a0b6e37e0c4a83 Mon Sep 17 00:00:00 2001 From: John Coates Date: Tue, 22 Aug 2023 02:18:48 -0500 Subject: [PATCH 2/3] return for page only if page? --- lib/ferrum/target.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ferrum/target.rb b/lib/ferrum/target.rb index f6a46c32..8e63d90d 100644 --- a/lib/ferrum/target.rb +++ b/lib/ferrum/target.rb @@ -24,7 +24,7 @@ def attached? end def page - connection + connection if page? end def network From 2e002d1ab6da31b23c870a047799f1e0981e1c72 Mon Sep 17 00:00:00 2001 From: John Coates Date: Tue, 22 Aug 2023 02:25:01 -0500 Subject: [PATCH 3/3] use template literal for code --- spec/support/views/service_worker.erb | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/spec/support/views/service_worker.erb b/spec/support/views/service_worker.erb index a47ca900..ca9a3ec1 100644 --- a/spec/support/views/service_worker.erb +++ b/spec/support/views/service_worker.erb @@ -1,11 +1,12 @@ -