diff --git a/.gitignore b/.gitignore index 12179ea..d7cb11f 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ erl_crash.dump # Also ignore archive artifacts (built via "mix archive.build"). *.ez +test.exs diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000..e8107ee --- /dev/null +++ b/.tool-versions @@ -0,0 +1,3 @@ +elixir 1.15.7-otp-25 +erlang 25.3.2.8 +nodejs 18.16.0 diff --git a/lib/chrome_remote_interface.ex b/lib/chrome_remote_interface.ex index cc56ba7..a469564 100644 --- a/lib/chrome_remote_interface.ex +++ b/lib/chrome_remote_interface.ex @@ -10,7 +10,7 @@ defmodule ChromeRemoteInterface do @protocol_version (if (vsn = System.get_env(@protocol_env_key)) in @protocol_versions do vsn else - "1-3" + "tot" end) IO.puts( "Compiling ChromeRemoteInterface with Chrome DevTools Protocol version: '#{@protocol_version}'" diff --git a/lib/page_session.ex b/lib/page_session.ex index c39ad67..d0e329b 100644 --- a/lib/page_session.ex +++ b/lib/page_session.ex @@ -90,28 +90,29 @@ defmodule ChromeRemoteInterface.PageSession do """ def execute_command(pid, method, params, opts) do async = Keyword.get(opts, :async, false) + session_id = Keyword.get(opts, :session_id, nil) timeout = Keyword.get(opts, :timeout, 5_000) case async do - false -> call(pid, method, params, timeout) - true -> cast(pid, method, params, self()) - from when is_pid(from) -> cast(pid, method, params, from) + false -> call(pid, method, params, session_id, timeout) + true -> cast(pid, method, params, session_id, self()) + from when is_pid(from) -> cast(pid, method, params, session_id, from) end end @doc """ Executes a raw JSON RPC command through Websockets. """ - def call(pid, method, params, timeout) do - GenServer.call(pid, {:call_command, method, params}, timeout) + def call(pid, method, params, session_id, timeout) do + GenServer.call(pid, {:call_command, method, params, session_id}, timeout) end @doc """ Executes a raw JSON RPC command through Websockets, but sends the response as a message to the requesting process. """ - def cast(pid, method, params, from \\ self()) do - GenServer.cast(pid, {:cast_command, method, params, from}) + def cast(pid, method, params, session_id, from \\ self()) do + GenServer.cast(pid, {:cast_command, method, params, from, session_id}) end # --- @@ -129,8 +130,8 @@ defmodule ChromeRemoteInterface.PageSession do {:ok, state} end - def handle_cast({:cast_command, method, params, from}, state) do - send(self(), {:send_rpc_request, state.ref_id, state.socket, method, params}) + def handle_cast({:cast_command, method, params, from, session_id}, state) do + send(self(), {:send_rpc_request, state.ref_id, state.socket, method, params, session_id}) new_state = state @@ -140,8 +141,8 @@ defmodule ChromeRemoteInterface.PageSession do {:noreply, new_state} end - def handle_call({:call_command, method, params}, from, state) do - send(self(), {:send_rpc_request, state.ref_id, state.socket, method, params}) + def handle_call({:call_command, method, params, session_id}, from, state) do + send(self(), {:send_rpc_request, state.ref_id, state.socket, method, params, session_id}) new_state = state @@ -220,13 +221,20 @@ defmodule ChromeRemoteInterface.PageSession do {:noreply, %{state | callbacks: callbacks}} end - def handle_info({:send_rpc_request, ref_id, socket, method, params}, state) do + def handle_info({:send_rpc_request, ref_id, socket, method, params, session_id}, state) do message = %{ "id" => ref_id, "method" => method, "params" => params } + message = + if session_id != nil do + Map.merge(message, %{"sessionId" => session_id}) + else + message + end + json = Jason.encode!(message) WebSockex.send_frame(socket, {:text, json}) {:noreply, state} diff --git a/lib/websocket.ex b/lib/websocket.ex index dd089c1..6024f81 100644 --- a/lib/websocket.ex +++ b/lib/websocket.ex @@ -3,6 +3,7 @@ defmodule ChromeRemoteInterface.Websocket do use WebSockex + @spec start_link(binary() | WebSockex.Conn.t()) :: {:error, any()} | {:ok, pid()} def start_link(url) do WebSockex.start_link(url, __MODULE__, self()) end @@ -11,4 +12,8 @@ defmodule ChromeRemoteInterface.Websocket do send(state, {:message, frame_data}) {:ok, state} end + + def handle_info({:ssl_closed, _data}, _state) do + {:close, 0} + end end diff --git a/mix.lock b/mix.lock index 33836b2..f680ed3 100644 --- a/mix.lock +++ b/mix.lock @@ -1,19 +1,20 @@ %{ - "certifi": {:hex, :certifi, "2.0.0", "a0c0e475107135f76b8c1d5bc7efb33cd3815cb3cf3dea7aefdd174dabead064", [:rebar3], []}, - "earmark": {:hex, :earmark, "1.3.2", "b840562ea3d67795ffbb5bd88940b1bed0ed9fa32834915125ea7d02e35888a5", [:mix], [], "hexpm"}, - "ex_doc": {:hex, :ex_doc, "0.20.2", "1bd0dfb0304bade58beb77f20f21ee3558cc3c753743ae0ddbb0fd7ba2912331", [:mix], [{:earmark, "~> 1.3", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, - "hackney": {:hex, :hackney, "1.9.0", "51c506afc0a365868469dcfc79a9d0b94d896ec741cfd5bd338f49a5ec515bfe", [:rebar3], [{:certifi, "2.0.0", [hex: :certifi, optional: false]}, {:idna, "5.1.0", [hex: :idna, optional: false]}, {:metrics, "1.0.1", [hex: :metrics, optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, optional: false]}]}, + "certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"}, + "earmark": {:hex, :earmark, "1.3.2", "b840562ea3d67795ffbb5bd88940b1bed0ed9fa32834915125ea7d02e35888a5", [:mix], [], "hexpm", "e3be2bc3ae67781db529b80aa7e7c49904a988596e2dbff897425b48b3581161"}, + "ex_doc": {:hex, :ex_doc, "0.20.2", "1bd0dfb0304bade58beb77f20f21ee3558cc3c753743ae0ddbb0fd7ba2912331", [:mix], [{:earmark, "~> 1.3", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "8e24fc8ff9a50b9f557ff020d6c91a03cded7e59ac3e0eec8a27e771430c7d27"}, + "hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~> 2.12.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"}, "httpipe": {:hex, :httpipe, "0.9.0", "4db66493b0ec2a86d142ea959a62e221d6ddb23ab48a676b691be3a16c38a415", [:mix], []}, "httpipe_adapters_hackney": {:hex, :httpipe_adapters_hackney, "0.11.0", "35c31b96fd6fea117f9ba6ca70467ada111dffb9f2fa7fca0bfc7e12bb166e8e", [:mix], [{:hackney, "~> 1.8 or ~> 1.7 or ~> 1.6", [hex: :hackney, optional: false]}, {:httpipe, "~> 0.9.0", [hex: :httpipe, optional: false]}]}, - "idna": {:hex, :idna, "5.1.0", "d72b4effeb324ad5da3cab1767cb16b17939004e789d8c0ad5b70f3cea20c89a", [:rebar3], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, optional: false]}]}, - "jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"}, - "makeup": {:hex, :makeup, "0.8.0", "9cf32aea71c7fe0a4b2e9246c2c4978f9070257e5c9ce6d4a28ec450a839b55f", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"}, - "makeup_elixir": {:hex, :makeup_elixir, "0.13.0", "be7a477997dcac2e48a9d695ec730b2d22418292675c75aa2d34ba0909dcdeda", [:mix], [{:makeup, "~> 0.8", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"}, - "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], []}, - "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], []}, - "nimble_parsec": {:hex, :nimble_parsec, "0.5.0", "90e2eca3d0266e5c53f8fbe0079694740b9c91b6747f2b7e3c5d21966bba8300", [:mix], [], "hexpm"}, + "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, + "jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fdf843bca858203ae1de16da2ee206f53416bbda5dc8c9e78f43243de4bc3afe"}, + "makeup": {:hex, :makeup, "0.8.0", "9cf32aea71c7fe0a4b2e9246c2c4978f9070257e5c9ce6d4a28ec450a839b55f", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5fbc8e549aa9afeea2847c0769e3970537ed302f93a23ac612602e805d9d1e7f"}, + "makeup_elixir": {:hex, :makeup_elixir, "0.13.0", "be7a477997dcac2e48a9d695ec730b2d22418292675c75aa2d34ba0909dcdeda", [:mix], [{:makeup, "~> 0.8", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "adf0218695e22caeda2820eaba703fa46c91820d53813a2223413da3ef4ba515"}, + "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, + "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"}, + "nimble_parsec": {:hex, :nimble_parsec, "0.5.0", "90e2eca3d0266e5c53f8fbe0079694740b9c91b6747f2b7e3c5d21966bba8300", [:mix], [], "hexpm", "5c040b8469c1ff1b10093d3186e2e10dbe483cd73d79ec017993fb3985b8a9b3"}, + "parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"}, "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], []}, - "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], []}, - "unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [:rebar3], []}, - "websockex": {:hex, :websockex, "0.4.0", "72096b1257baffc52c5f15c7366fb468e373b3c6173a6fee45311bfdb8ee1256", [:mix], []}, + "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"}, + "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, + "websockex": {:hex, :websockex, "0.4.0", "72096b1257baffc52c5f15c7366fb468e373b3c6173a6fee45311bfdb8ee1256", [:mix], [], "hexpm", "d31c684394d75e19e90302b7975d23f27e42f345b1725d7a703da9e4bc8f1d1f"}, } diff --git a/priv/tot/protocol.json b/priv/tot/protocol.json index 68265d8..7ae7fec 100644 --- a/priv/tot/protocol.json +++ b/priv/tot/protocol.json @@ -1,1489 +1,1466 @@ { "domains": [ { - "domain": "Accessibility", - "experimental": true, + "domain": "Console", + "description": "This domain is deprecated - use Runtime or Log instead.", + "deprecated": true, "dependencies": [ - "DOM" + "Runtime" ], "types": [ { - "id": "AXNodeId", - "description": "Unique accessibility node identifier.", - "type": "string" - }, - { - "id": "AXValueType", - "description": "Enum of possible property types.", - "type": "string", - "enum": [ - "boolean", - "tristate", - "booleanOrUndefined", - "idref", - "idrefList", - "integer", - "node", - "nodeList", - "number", - "string", - "computedString", - "token", - "tokenList", - "domRelation", - "role", - "internalRole", - "valueUndefined" - ] - }, - { - "id": "AXValueSourceType", - "description": "Enum of possible property sources.", - "type": "string", - "enum": [ - "attribute", - "implicit", - "style", - "contents", - "placeholder", - "relatedElement" - ] - }, - { - "id": "AXValueNativeSourceType", - "description": "Enum of possible native property sources (as a subtype of a particular AXValueSourceType).", - "type": "string", - "enum": [ - "figcaption", - "label", - "labelfor", - "labelwrapped", - "legend", - "tablecaption", - "title", - "other" - ] - }, - { - "id": "AXValueSource", - "description": "A single source for a computed AX property.", + "id": "ConsoleMessage", + "description": "Console message.", "type": "object", "properties": [ { - "name": "type", - "description": "What type of source this is.", - "$ref": "AXValueSourceType" + "name": "source", + "description": "Message source.", + "type": "string", + "enum": [ + "xml", + "javascript", + "network", + "console-api", + "storage", + "appcache", + "rendering", + "security", + "other", + "deprecation", + "worker" + ] }, { - "name": "value", - "description": "The value of this property source.", - "optional": true, - "$ref": "AXValue" + "name": "level", + "description": "Message severity.", + "type": "string", + "enum": [ + "log", + "warning", + "error", + "debug", + "info" + ] }, { - "name": "attribute", - "description": "The name of the relevant attribute, if any.", - "optional": true, + "name": "text", + "description": "Message text.", "type": "string" }, { - "name": "attributeValue", - "description": "The value of the relevant attribute, if any.", - "optional": true, - "$ref": "AXValue" - }, - { - "name": "superseded", - "description": "Whether this source is superseded by a higher priority source.", - "optional": true, - "type": "boolean" - }, - { - "name": "nativeSource", - "description": "The native markup source for this value, e.g. a