Current section

Files

Jump to
chrobot src chrobot.erl
Raw

src/chrobot.erl

-module(chrobot).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([open/3, with_timeout/2, to_file/2, as_value/2, quit/1, defer_quit/2, page_caller/1, close/1, screenshot/1, pdf/1, down_key/3, up_key/3, press_key/2, insert_char/2, type_text/2, await_load_event/2, launch/0, launch_window/0, launch_with_config/1, launch_with_env/0, eval/2, eval_to_value/2, eval_async/2, get_all_html/1, select_all/2, select/2, call_custom_function_on/5, to_value/3, get_attribute/3, get_property/4, get_text/2, get_inner_html/2, get_outer_html/2, call_custom_function_on_raw/4, click/2, click_selector/2, focus/2, focus_selector/2, poll/2, await_selector/2, create_page/3]).
-export_type([page/0, encoded_file/0, call_argument/0]).
-type page() :: {page,
gleam@erlang@process:subject(chrome:message()),
integer(),
protocol@target:target_id(),
protocol@target:session_id()}.
-type encoded_file() :: {encoded_file, binary(), binary()}.
-type call_argument() :: {string_arg, binary()} |
{int_arg, integer()} |
{float_arg, float()} |
{bool_arg, boolean()} |
{array_arg, list(call_argument())}.
-spec open(gleam@erlang@process:subject(chrome:message()), binary(), integer()) -> {ok,
page()} |
{error, chrome:request_error()}.
open(Browser_subject, Url, Time_out) ->
gleam@result:'try'(
protocol@target:create_target(
fun(Method, Params) ->
chrome:call(Browser_subject, Method, Params, none, Time_out)
end,
Url,
{some, 1920},
{some, 1080},
none,
none
),
fun(Target_response) ->
gleam@result:'try'(
protocol@target:attach_to_target(
fun(Method@1, Params@1) ->
chrome:call(
Browser_subject,
Method@1,
Params@1,
none,
Time_out
)
end,
erlang:element(2, Target_response),
{some, true}
),
fun(Session_response) ->
{ok,
{page,
Browser_subject,
Time_out,
erlang:element(2, Target_response),
erlang:element(2, Session_response)}}
end
)
end
).
-spec with_timeout(page(), integer()) -> page().
with_timeout(Page, Time_out) ->
{page,
erlang:element(2, Page),
Time_out,
erlang:element(4, Page),
erlang:element(5, Page)}.
-spec to_file(encoded_file(), binary()) -> {ok, nil} |
{error, simplifile:file_error()}.
to_file(Input, Path) ->
Res = begin
_pipe = gleam@bit_array:base64_decode(erlang:element(2, Input)),
gleam@result:replace_error(_pipe, unknown)
end,
gleam@result:'try'(
Res,
fun(Binary) ->
simplifile:write_bits(
<<<<Path/binary, "."/utf8>>/binary,
(erlang:element(3, Input))/binary>>,
Binary
)
end
).
-spec as_value(
{ok, protocol@runtime:remote_object()} | {error, chrome:request_error()},
fun((gleam@dynamic:dynamic_()) -> {ok, AIRU} | {error, any()})
) -> {ok, AIRU} | {error, chrome:request_error()}.
as_value(Result, Decoder) ->
case Result of
{ok, {remote_object, _, _, _, {some, Value}, _, _, _}} ->
_pipe = Decoder(Value),
gleam@result:replace_error(_pipe, protocol_error);
{error, Something} ->
{error, Something};
_ ->
{error, not_found_error}
end.
-spec quit(gleam@erlang@process:subject(chrome:message())) -> {ok, nil} |
{error, gleam@erlang@process:call_error(nil)}.
quit(Browser) ->
chrome:quit(Browser).
-spec defer_quit(
gleam@erlang@process:subject(chrome:message()),
fun(() -> any())
) -> {ok, nil} | {error, gleam@erlang@process:call_error(nil)}.
defer_quit(Browser, Body) ->
Body(),
chrome:quit(Browser).
-spec pass_session(protocol@target:session_id()) -> gleam@option:option(binary()).
pass_session(Session_id) ->
case Session_id of
{session_id, Value} ->
{some, Value}
end.
-spec page_caller(page()) -> fun((binary(), gleam@option:option(gleam@json:json())) -> {ok,
gleam@dynamic:dynamic_()} |
{error, chrome:request_error()}).
page_caller(Page) ->
fun(Method, Params) ->
chrome:call(
erlang:element(2, Page),
Method,
Params,
pass_session(erlang:element(5, Page)),
erlang:element(3, Page)
)
end.
-spec close(page()) -> {ok, gleam@dynamic:dynamic_()} |
{error, chrome:request_error()}.
close(Page) ->
protocol@target:close_target(page_caller(Page), erlang:element(4, Page)).
-spec screenshot(page()) -> {ok, encoded_file()} |
{error, chrome:request_error()}.
screenshot(Page) ->
gleam@result:'try'(
protocol@page:capture_screenshot(
page_caller(Page),
{some, capture_screenshot_format_png},
none,
none
),
fun(Response) ->
{ok, {encoded_file, erlang:element(2, Response), <<"png"/utf8>>}}
end
).
-spec pdf(page()) -> {ok, encoded_file()} | {error, chrome:request_error()}.
pdf(Page) ->
gleam@result:'try'(
protocol@page:print_to_pdf(
page_caller(Page),
{some, false},
{some, false},
none,
none,
none,
none,
none,
none,
none,
none,
none,
none,
none,
none
),
fun(Response) ->
{ok, {encoded_file, erlang:element(2, Response), <<"pdf"/utf8>>}}
end
).
-spec down_key(page(), binary(), integer()) -> {ok, nil} |
{error, chrome:request_error()}.
down_key(Page, Key, Modifiers) ->
Key_data_result = chrobot@internal@keymap:get_key_data(Key),
case Key_data_result of
{ok, Key_data} ->
Text@1 = (case erlang:element(5, Key_data) of
{some, Text} ->
{some, Text};
none ->
{some, Key}
end),
_pipe = protocol@input:dispatch_key_event(
page_caller(Page),
(case Text@1 of
{some, _} ->
dispatch_key_event_type_key_down;
none ->
dispatch_key_event_type_raw_key_down
end),
{some, Modifiers},
none,
Text@1,
Text@1,
none,
erlang:element(3, Key_data),
erlang:element(4, Key_data),
erlang:element(2, Key_data),
none,
none,
(case erlang:element(6, Key_data) of
{some, 3} ->
{some, true};
_ ->
none
end),
none,
erlang:element(6, Key_data)
),
gleam@result:replace(_pipe, nil);
{error, nil} ->
chrobot@internal@utils:warn(
<<<<"You are attempting to trigger a key which is not supported
by the chrobot virtual keyboard.
The key to be pressed down is: '"/utf8,
Key/binary>>/binary,
"'.
Chrobot simulates a US keyboard layout,
it's best to stick to ASCII characters and DOM key names!"/utf8>>
),
{error, not_found_error}
end.
-spec up_key(page(), binary(), integer()) -> {ok, nil} |
{error, chrome:request_error()}.
up_key(Page, Key, Modifiers) ->
Key_data_result = chrobot@internal@keymap:get_key_data(Key),
case Key_data_result of
{ok, Key_data} ->
_pipe = protocol@input:dispatch_key_event(
page_caller(Page),
dispatch_key_event_type_key_up,
{some, Modifiers},
none,
erlang:element(5, Key_data),
erlang:element(5, Key_data),
none,
erlang:element(3, Key_data),
erlang:element(4, Key_data),
erlang:element(2, Key_data),
none,
none,
(case erlang:element(6, Key_data) of
{some, 3} ->
{some, true};
_ ->
none
end),
none,
erlang:element(6, Key_data)
),
gleam@result:replace(_pipe, nil);
{error, nil} ->
chrobot@internal@utils:warn(
<<<<"You are attempting to trigger a key which is not supported
by the chrobot virtual keyboard.
The key to be released is: '"/utf8,
Key/binary>>/binary,
"'.
Chrobot simulates a US keyboard layout,
it's best to stick to ASCII characters and DOM key names!"/utf8>>
),
{error, not_found_error}
end.
-spec press_key(page(), binary()) -> {ok, nil} | {error, chrome:request_error()}.
press_key(Page, Key) ->
gleam@result:'try'(
down_key(Page, Key, 0),
fun(_) -> up_key(Page, Key, 0) end
).
-spec insert_char(page(), binary()) -> {ok, nil} |
{error, chrome:request_error()}.
insert_char(Page, Key) ->
_pipe = protocol@input:dispatch_key_event(
page_caller(Page),
dispatch_key_event_type_char,
none,
none,
{some, Key},
none,
none,
none,
none,
none,
none,
none,
none,
none,
none
),
gleam@result:replace(_pipe, nil).
-spec type_text(page(), binary()) -> {ok, nil} | {error, chrome:request_error()}.
type_text(Page, Input) ->
_pipe = gleam@string:to_graphemes(Input),
_pipe@1 = gleam@list:map(
_pipe,
fun(Char) -> case chrobot@internal@keymap:get_key_data(Char) of
{ok, _} ->
press_key(Page, Char);
{error, _} ->
insert_char(Page, Char)
end end
),
_pipe@2 = gleam@result:all(_pipe@1),
gleam@result:replace(_pipe@2, nil).
-spec await_load_event(gleam@erlang@process:subject(chrome:message()), page()) -> {ok,
gleam@dynamic:dynamic_()} |
{error, chrome:request_error()}.
await_load_event(Browser, Page) ->
gleam@result:'try'(
protocol@page:enable(page_caller(Page)),
fun(_) ->
chrome:listen_once(
Browser,
<<"Page.loadEventFired"/utf8>>,
erlang:element(3, Page)
)
end
).
-spec validate_launch(
{ok, gleam@erlang@process:subject(chrome:message())} |
{error, chrome:launch_error()}
) -> {ok, gleam@erlang@process:subject(chrome:message())} |
{error, chrome:launch_error()}.
validate_launch(Launch_result) ->
gleam@result:'try'(
Launch_result,
fun(Instance) ->
{Major, Minor} = protocol:version(),
Target_protocol_version = <<<<Major/binary, "."/utf8>>/binary,
Minor/binary>>,
Version_response = begin
_pipe = chrome:get_version(Instance),
gleam@result:replace_error(_pipe, unresponsive_after_start)
end,
gleam@result:'try'(
Version_response,
fun(Actual_version) ->
case Target_protocol_version =:= erlang:element(
2,
Actual_version
) of
true ->
{ok, Instance};
false ->
{error,
{protocol_version_mismatch,
Target_protocol_version,
erlang:element(2, Actual_version)}}
end
end
)
end
).
-spec launch() -> {ok, gleam@erlang@process:subject(chrome:message())} |
{error, chrome:launch_error()}.
launch() ->
Launch_result = validate_launch(chrome:launch()),
case Launch_result of
{error, could_not_find_executable} ->
chrobot@internal@utils:err(
<<"Chrobot could not find a chrome executable to launch!\n"/utf8>>
),
chrobot@internal@utils:hint(
<<"You can install a local version of chrome for testing with this command:"/utf8>>
),
chrobot@internal@utils:show_cmd(
<<"gleam run -m browser_install"/utf8>>
),
Launch_result;
Other ->
Other
end.
-spec launch_window() -> {ok, gleam@erlang@process:subject(chrome:message())} |
{error, chrome:launch_error()}.
launch_window() ->
Launch_result = validate_launch(chrome:launch_window()),
case Launch_result of
{error, could_not_find_executable} ->
chrobot@internal@utils:err(
<<"Chrobot could not find a chrome executable to launch!\n"/utf8>>
),
chrobot@internal@utils:hint(
<<"You can install a local version of chrome for testing with this command:"/utf8>>
),
chrobot@internal@utils:show_cmd(
<<"gleam run -m browser_install"/utf8>>
),
Launch_result;
Other ->
Other
end.
-spec launch_with_config(chrome:browser_config()) -> {ok,
gleam@erlang@process:subject(chrome:message())} |
{error, chrome:launch_error()}.
launch_with_config(Config) ->
validate_launch(chrome:launch_with_config(Config)).
-spec launch_with_env() -> {ok, gleam@erlang@process:subject(chrome:message())} |
{error, chrome:launch_error()}.
launch_with_env() ->
validate_launch(chrome:launch_with_env()).
-spec handle_eval_response(
{ok, protocol@runtime:evaluate_response()} | {error, chrome:request_error()}
) -> {ok, protocol@runtime:remote_object()} | {error, chrome:request_error()}.
handle_eval_response(Eval_response) ->
case Eval_response of
{ok, {evaluate_response, _, {some, Exception}}} ->
{error,
{runtime_exception,
erlang:element(3, Exception),
erlang:element(4, Exception),
erlang:element(5, Exception)}};
{ok, {evaluate_response, Result_data, none}} ->
{ok, Result_data};
{error, Other} ->
{error, Other}
end.
-spec eval(page(), binary()) -> {ok, protocol@runtime:remote_object()} |
{error, chrome:request_error()}.
eval(Page, Expression) ->
_pipe = protocol@runtime:evaluate(
page_caller(Page),
Expression,
none,
none,
{some, false},
none,
{some, false},
{some, true},
{some, false}
),
handle_eval_response(_pipe).
-spec eval_to_value(page(), binary()) -> {ok, protocol@runtime:remote_object()} |
{error, chrome:request_error()}.
eval_to_value(Page, Expression) ->
_pipe = protocol@runtime:evaluate(
page_caller(Page),
Expression,
none,
none,
{some, false},
none,
{some, true},
{some, true},
{some, false}
),
handle_eval_response(_pipe).
-spec eval_async(page(), binary()) -> {ok, protocol@runtime:remote_object()} |
{error, chrome:request_error()}.
eval_async(Page, Expression) ->
_pipe = protocol@runtime:evaluate(
page_caller(Page),
Expression,
none,
none,
{some, false},
none,
{some, false},
{some, true},
{some, true}
),
handle_eval_response(_pipe).
-spec get_all_html(page()) -> {ok, binary()} | {error, chrome:request_error()}.
get_all_html(Page) ->
_pipe = eval(Page, <<"window.document.documentElement.outerHTML"/utf8>>),
as_value(_pipe, fun gleam@dynamic:string/1).
-spec select_all(page(), binary()) -> {ok,
list(protocol@runtime:remote_object_id())} |
{error, chrome:request_error()}.
select_all(Page, Selector) ->
Selector_code = <<<<"window.document.querySelectorAll(\""/utf8,
Selector/binary>>/binary,
"\")"/utf8>>,
Result = eval(Page, Selector_code),
case Result of
{ok, {remote_object, _, _, _, _, _, _, {some, Remote_object_id}}} ->
gleam@result:'try'(
protocol@runtime:get_properties(
page_caller(Page),
Remote_object_id,
{some, true}
),
fun(Result_properties) -> case Result_properties of
{get_properties_response, _, _, {some, Exception}} ->
{error,
{runtime_exception,
erlang:element(3, Exception),
erlang:element(4, Exception),
erlang:element(5, Exception)}};
{get_properties_response, Property_descriptors, _, none} ->
{ok,
gleam@list:filter_map(
Property_descriptors,
fun(Prop_descriptor) ->
case Prop_descriptor of
{property_descriptor,
_,
{some,
{remote_object,
_,
_,
_,
_,
_,
_,
{some, Object_id}}},
_,
_,
_,
_,
_,
_,
_,
_} ->
{ok, Object_id};
_ ->
{error, nil}
end
end
)}
end end
);
{ok, _} ->
{ok, []};
{error, Any} ->
{error, Any}
end.
-spec handle_object_id_response(
{ok, protocol@runtime:remote_object()} | {error, chrome:request_error()}
) -> {ok, protocol@runtime:remote_object_id()} | {error, chrome:request_error()}.
handle_object_id_response(Response) ->
case Response of
{ok, {remote_object, _, _, _, _, _, _, {some, Remote_object_id}}} ->
{ok, Remote_object_id};
{ok, _} ->
{error, not_found_error};
{error, Any} ->
{error, Any}
end.
-spec select(page(), binary()) -> {ok, protocol@runtime:remote_object_id()} |
{error, chrome:request_error()}.
select(Page, Selector) ->
Selector_code = <<<<"window.document.querySelector(\""/utf8,
Selector/binary>>/binary,
"\")"/utf8>>,
_pipe = eval(Page, Selector_code),
handle_object_id_response(_pipe).
-spec encode_custom_arg(call_argument()) -> gleam@json:json().
encode_custom_arg(Arg) ->
case Arg of
{string_arg, Value} ->
gleam@json:string(Value);
{int_arg, Value@1} ->
gleam@json:int(Value@1);
{float_arg, Value@2} ->
gleam@json:float(Value@2);
{bool_arg, Value@3} ->
gleam@json:bool(Value@3);
{array_arg, Value@4} ->
gleam@json:array(Value@4, fun encode_custom_arg/1)
end.
-spec encode_custom_arguments(list(call_argument())) -> gleam@json:json().
encode_custom_arguments(Input) ->
gleam@json:array(
Input,
fun(Arg) ->
gleam@json:object([{<<"value"/utf8>>, encode_custom_arg(Arg)}])
end
).
-spec call_custom_function_on(
fun((binary(), gleam@option:option(gleam@json:json())) -> {ok,
gleam@dynamic:dynamic_()} |
{error, chrome:request_error()}),
binary(),
protocol@runtime:remote_object_id(),
list(call_argument()),
fun((gleam@dynamic:dynamic_()) -> {ok, AJCD} | {error, any()})
) -> {ok, AJCD} | {error, chrome:request_error()}.
call_custom_function_on(
Callback,
Function_declaration,
Object_id,
Arguments,
Value_decoder
) ->
Encoded_arguments = encode_custom_arguments(Arguments),
Payload = {some,
gleam@json:object(
[{<<"functionDeclaration"/utf8>>,
gleam@json:string(Function_declaration)},
{<<"objectId"/utf8>>,
protocol@runtime:encode__remote_object_id(Object_id)},
{<<"arguments"/utf8>>, Encoded_arguments},
{<<"returnByValue"/utf8>>, gleam@json:bool(true)}]
)},
gleam@result:'try'(
Callback(<<"Runtime.callFunctionOn"/utf8>>, Payload),
fun(Result) ->
gleam@result:'try'(
begin
_pipe = protocol@runtime:decode__call_function_on_response(
Result
),
gleam@result:replace_error(_pipe, protocol_error)
end,
fun(Decoded_response) -> case Decoded_response of
{call_function_on_response, _, {some, Exception}} ->
{error,
{runtime_exception,
erlang:element(3, Exception),
erlang:element(4, Exception),
erlang:element(5, Exception)}};
{call_function_on_response,
{remote_object, _, _, _, {some, Value}, _, _, _},
none} ->
_pipe@1 = Value_decoder(Value),
gleam@result:replace_error(_pipe@1, protocol_error);
_ ->
{error, not_found_error}
end end
)
end
).
-spec to_value(
page(),
protocol@runtime:remote_object_id(),
fun((gleam@dynamic:dynamic_()) -> {ok, AJCE} | {error, any()})
) -> {ok, AJCE} | {error, chrome:request_error()}.
to_value(Page, Remote_object_id, Decoder) ->
Declaration = <<"function to_value(){
return JSON.stringify(this)
}"/utf8>>,
call_custom_function_on(
page_caller(Page),
Declaration,
Remote_object_id,
[],
Decoder
).
-spec get_attribute(page(), protocol@runtime:remote_object_id(), binary()) -> {ok,
binary()} |
{error, chrome:request_error()}.
get_attribute(Page, Item, Attribute_name) ->
Declaration = <<"function get_arg(attribute_name)
{
return this.getAttribute(attribute_name)
}
"/utf8>>,
call_custom_function_on(
page_caller(Page),
Declaration,
Item,
[{string_arg, Attribute_name}],
fun gleam@dynamic:string/1
).
-spec get_property(
page(),
protocol@runtime:remote_object_id(),
binary(),
fun((gleam@dynamic:dynamic_()) -> {ok, AJCK} | {error, any()})
) -> {ok, AJCK} | {error, chrome:request_error()}.
get_property(Page, Item, Property_name, Property_decoder) ->
Declaration = <<"function get_prop(property_name)
{
return this[property_name]
}
"/utf8>>,
call_custom_function_on(
page_caller(Page),
Declaration,
Item,
[{string_arg, Property_name}],
Property_decoder
).
-spec get_text(page(), protocol@runtime:remote_object_id()) -> {ok, binary()} |
{error, chrome:request_error()}.
get_text(Page, Item) ->
get_property(Page, Item, <<"innerText"/utf8>>, fun gleam@dynamic:string/1).
-spec get_inner_html(page(), protocol@runtime:remote_object_id()) -> {ok,
binary()} |
{error, chrome:request_error()}.
get_inner_html(Page, Item) ->
get_property(Page, Item, <<"innerHTML"/utf8>>, fun gleam@dynamic:string/1).
-spec get_outer_html(page(), protocol@runtime:remote_object_id()) -> {ok,
binary()} |
{error, chrome:request_error()}.
get_outer_html(Page, Item) ->
get_property(Page, Item, <<"outerHTML"/utf8>>, fun gleam@dynamic:string/1).
-spec call_custom_function_on_raw(
fun((binary(), gleam@option:option(gleam@json:json())) -> {ok,
gleam@dynamic:dynamic_()} |
{error, chrome:request_error()}),
binary(),
protocol@runtime:remote_object_id(),
list(call_argument())
) -> {ok, protocol@runtime:call_function_on_response()} |
{error, chrome:request_error()}.
call_custom_function_on_raw(
Callback,
Function_declaration,
Object_id,
Arguments
) ->
Encoded_arguments = encode_custom_arguments(Arguments),
Payload = {some,
gleam@json:object(
[{<<"functionDeclaration"/utf8>>,
gleam@json:string(Function_declaration)},
{<<"objectId"/utf8>>,
protocol@runtime:encode__remote_object_id(Object_id)},
{<<"arguments"/utf8>>, Encoded_arguments},
{<<"returnByValue"/utf8>>, gleam@json:bool(true)}]
)},
gleam@result:'try'(
Callback(<<"Runtime.callFunctionOn"/utf8>>, Payload),
fun(Result) ->
gleam@result:'try'(
begin
_pipe = protocol@runtime:decode__call_function_on_response(
Result
),
gleam@result:replace_error(_pipe, protocol_error)
end,
fun(Decoded_response) -> case Decoded_response of
{call_function_on_response, _, {some, Exception}} ->
{error,
{runtime_exception,
erlang:element(3, Exception),
erlang:element(4, Exception),
erlang:element(5, Exception)}};
_ ->
{ok, Decoded_response}
end end
)
end
).
-spec click(page(), protocol@runtime:remote_object_id()) -> {ok, nil} |
{error, chrome:request_error()}.
click(Page, Item) ->
Declaration = <<"function click_el(){
return this.click()
}"/utf8>>,
_pipe = call_custom_function_on_raw(
page_caller(Page),
Declaration,
Item,
[]
),
gleam@result:replace(_pipe, nil).
-spec click_selector(page(), binary()) -> {ok, nil} |
{error, chrome:request_error()}.
click_selector(Page, Selector) ->
gleam@result:'try'(
select(Page, Selector),
fun(Item) -> click(Page, Item) end
).
-spec focus(page(), protocol@runtime:remote_object_id()) -> {ok, nil} |
{error, chrome:request_error()}.
focus(Page, Item) ->
Declaration = <<"function focus_el(){
return this.focus()
}"/utf8>>,
_pipe = call_custom_function_on_raw(
page_caller(Page),
Declaration,
Item,
[]
),
gleam@result:replace(_pipe, nil).
-spec focus_selector(page(), binary()) -> {ok, nil} |
{error, chrome:request_error()}.
focus_selector(Page, Selector) ->
gleam@result:'try'(
select(Page, Selector),
fun(Item) -> focus(Page, Item) end
).
-spec do_poll(
fun(() -> {ok, AIPB} | {error, chrome:request_error()}),
integer(),
gleam@option:option(chrome:request_error())
) -> {ok, AIPB} | {error, chrome:request_error()}.
do_poll(Callback, Deadline, Previous_error) ->
Available_time = Deadline - chrobot_ffi:get_time_ms(),
Result = begin
_pipe = Callback,
_pipe@1 = gleam@otp@task:async(_pipe),
gleam@otp@task:try_await(_pipe@1, Available_time)
end,
Available_time@1 = (Deadline - chrobot_ffi:get_time_ms()) - 5,
case Result of
{error, timeout} ->
case Previous_error of
{some, Err} ->
{error, Err};
none ->
{error, chrome_agent_timeout}
end;
{error, {exit, _}} ->
case Previous_error of
{some, Err} ->
{error, Err};
none ->
{error, chrome_agent_timeout}
end;
{ok, {ok, Res}} ->
{ok, Res};
{ok, {error, Err@1}} when Available_time@1 > 0 ->
gleam_erlang_ffi:sleep(5),
do_poll(Callback, Deadline, {some, Err@1});
{ok, {error, Err@2}} ->
{error, Err@2}
end.
-spec poll(fun(() -> {ok, AIOW} | {error, chrome:request_error()}), integer()) -> {ok,
AIOW} |
{error, chrome:request_error()}.
poll(Callback, Timeout) ->
Deadline = chrobot_ffi:get_time_ms() + Timeout,
do_poll(Callback, Deadline, none).
-spec await_selector(page(), binary()) -> {ok,
protocol@runtime:remote_object_id()} |
{error, chrome:request_error()}.
await_selector(Page, Selector) ->
Polly = fun() ->
_pipe = eval(
Page,
<<<<"window.document.querySelector(\""/utf8, Selector/binary>>/binary,
"\")"/utf8>>
),
handle_object_id_response(_pipe)
end,
poll(Polly, erlang:element(3, Page)).
-spec create_page(
gleam@erlang@process:subject(chrome:message()),
binary(),
integer()
) -> {ok, page()} | {error, chrome:request_error()}.
create_page(Browser, Html, Time_out) ->
gleam@result:'try'(
open(Browser, <<"about:blank"/utf8>>, Time_out),
fun(Created_page) ->
gleam@result:'try'(
await_selector(Created_page, <<"body"/utf8>>),
fun(_) ->
Payload = <<<<"window.document.open();
window.document.write(`"/utf8,
Html/binary>>/binary,
"`);
window.document.close();
"/utf8>>,
gleam@result:'try'(
eval(Created_page, Payload),
fun(_) -> {ok, Created_page} end
)
end
)
end
).