1 |
|
-module(chrme_cdp). |
2 |
|
-export([call/3, subscribe_event/3, unsubscribe_event/2]). |
3 |
|
|
4 |
|
%% Send a JSON-RPC method call over the Chrome DevTools WebSocket |
5 |
|
-spec call(Name :: chrme_session:name(), MethodBin :: klsn:binstr(), Params :: term()) -> {ok, map()} | {error, term()}. |
6 |
|
call(Name, MethodBin, Params) -> |
7 |
18 |
JsonParams = params_to_json(Params), |
8 |
18 |
Json = #{<<"method">> => MethodBin, <<"params">> => JsonParams}, |
9 |
18 |
Resp = chrme_ws_apic:await_send_response(Name, Json), |
10 |
18 |
case maps:get(<<"error">>, Resp, undefined) of |
11 |
|
undefined -> |
12 |
17 |
{ok, maps:get(<<"result">>, Resp, #{})}; |
13 |
|
Err -> |
14 |
1 |
{error, Err} |
15 |
|
end. |
16 |
|
|
17 |
|
%% Subscribe to a CDP event over the WebSocket |
18 |
|
-spec subscribe_event(Name :: chrme_session:name(), EventBin :: klsn:binstr(), Fun :: fun((map()) -> any())) -> reference(). |
19 |
|
subscribe_event(Name, EventBin, Fun) -> |
20 |
:-( |
Ref = make_ref(), |
21 |
:-( |
CallbackName = {chrme_cdp, subscribe_event, Name, Ref}, |
22 |
:-( |
CallbackFun = fun |
23 |
|
(stop) -> |
24 |
:-( |
false; |
25 |
|
(Msg = #{<<"method">> := EventBin}) -> |
26 |
:-( |
Fun(Msg), |
27 |
:-( |
true; |
28 |
|
(_) -> |
29 |
:-( |
false |
30 |
|
end, |
31 |
:-( |
chrme_ws_apic:add_callback(Name, {CallbackName, CallbackFun}), |
32 |
:-( |
Ref. |
33 |
|
|
34 |
|
-spec unsubscribe_event(Name :: chrme_session:name(), Ref :: reference()) -> ok. |
35 |
|
unsubscribe_event(Name, Ref) -> |
36 |
:-( |
CallbackName = {chrme_cdp, subscribe_event, Name, Ref}, |
37 |
:-( |
chrme_ws_apic:remove_callback(Name, CallbackName). |
38 |
|
|
39 |
|
%% Convert an Erlang-map with atom or binary keys into a JSON-friendly map (binary keys) |
40 |
|
-spec params_to_json(Params :: map()) -> map(); |
41 |
|
(Other :: term()) -> term(). |
42 |
|
params_to_json(Params) when is_map(Params) -> |
43 |
18 |
lists:foldl(fun({K, V}, Acc) -> |
44 |
13 |
KeyBin = key_to_binary(K), |
45 |
13 |
Value = val_to_json(V), |
46 |
13 |
maps:put(KeyBin, Value, Acc) |
47 |
|
end, #{}, maps:to_list(Params)); |
48 |
|
params_to_json(Other) -> |
49 |
:-( |
Other. |
50 |
|
|
51 |
|
-spec key_to_binary(K :: atom()) -> klsn:binstr(); |
52 |
|
(K :: binary()) -> klsn:binstr(); |
53 |
|
(K :: list()) -> klsn:binstr(). |
54 |
|
key_to_binary(K) when is_atom(K) -> |
55 |
13 |
atom_to_binary(K, utf8); |
56 |
|
key_to_binary(K) when is_binary(K) -> |
57 |
:-( |
K; |
58 |
|
key_to_binary(K) when is_list(K) -> |
59 |
:-( |
list_to_binary(K). |
60 |
|
|
61 |
|
-spec val_to_json(V :: map()) -> map(); |
62 |
|
(V :: list()) -> list(); |
63 |
|
(V :: term()) -> term(). |
64 |
|
val_to_json(V) when is_map(V) -> |
65 |
:-( |
params_to_json(V); |
66 |
|
val_to_json(V) when is_list(V) -> |
67 |
:-( |
[val_to_json(E) || E <- V]; |
68 |
|
val_to_json(V) -> |
69 |
13 |
V. |