| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| -module(hk_api_browser_h). |
|
|
| -export([init/2]). |
|
|
| init(Req0 = #{method := <<"POST">>}, collection) -> |
| RequestId = hk_api_util:request_id(Req0), |
| {ok, Body, Req1} = hk_api_util:read_json_body(Req0), |
| OwnerAgentId = maps:get(<<"owner_agent_id">>, Body, undefined), |
| Profile = maps:get(<<"profile">>, Body, <<"manual">>), |
| Req = hk_api_util:run_operation(browser_create_session, RequestId, fun() -> |
| SessionId = hk_id:new(<<"sess">>), |
| case hk_browser_session_sup:start_session(#{session_id => SessionId, |
| owner_agent_id => OwnerAgentId, profile => Profile}) of |
| {ok, _Pid} -> {ok, {browser_session, SessionId}, #{session_id => SessionId}}; |
| {error, Reason} -> {error, Reason} |
| end |
| end, Req1), |
| {ok, Req, collection}; |
|
|
| init(Req0 = #{method := <<"GET">>}, collection) -> |
| Sessions = [describe_or_skip(Id) || {Id, _Pid} <- hk_browser_registry:list_sessions()], |
| Req = hk_api_util:reply_json(200, #{sessions => [M || {true, M} <- Sessions]}, Req0), |
| {ok, Req, collection}; |
|
|
| init(Req0 = #{method := <<"GET">>}, item) -> |
| SessionId = cowboy_req:binding(id, Req0), |
| Req = case hk_browser_registry:lookup(SessionId) of |
| {ok, Pid} -> |
| {ok, Session} = hk_browser_session:describe(Pid), |
| hk_api_util:reply_json(200, hk_schema:to_map(Session), Req0); |
| {error, not_found} -> |
| hk_api_util:reply_error(404, session_not_found, Req0) |
| end, |
| {ok, Req, item}; |
|
|
| init(Req0 = #{method := <<"POST">>}, close) -> |
| SessionId = cowboy_req:binding(id, Req0), |
| RequestId = hk_api_util:request_id(Req0), |
| Req = hk_api_util:run_operation(browser_close_session, RequestId, fun() -> |
| with_session(SessionId, fun(Pid) -> |
| hk_browser_session:close_session(Pid), |
| {ok, {browser_session, SessionId}, #{}} |
| end) |
| end, Req0), |
| {ok, Req, close}; |
|
|
| init(Req0 = #{method := <<"POST">>}, tabs) -> |
| SessionId = cowboy_req:binding(id, Req0), |
| RequestId = hk_api_util:request_id(Req0), |
| {ok, Body, Req1} = hk_api_util:read_json_body(Req0), |
| Url = maps:get(<<"url">>, Body, <<"about:blank">>), |
| Req = hk_api_util:run_operation(browser_open_tab, RequestId, fun() -> |
| with_session(SessionId, fun(Pid) -> |
| case hk_browser_session:open_tab(Pid, Url) of |
| {ok, TabId} -> {ok, {browser_tab, TabId}, #{tab_id => TabId}}; |
| {error, Reason} -> {error, Reason} |
| end |
| end) |
| end, Req1), |
| {ok, Req, tabs}; |
|
|
| init(Req0 = #{method := <<"POST">>}, navigate) -> |
| SessionId = cowboy_req:binding(id, Req0), |
| TabId = cowboy_req:binding(tab_id, Req0), |
| RequestId = hk_api_util:request_id(Req0), |
| {ok, Body, Req1} = hk_api_util:read_json_body(Req0), |
| Url = maps:get(<<"url">>, Body, <<>>), |
| Req = hk_api_util:run_operation(browser_navigate, RequestId, fun() -> |
| with_session(SessionId, fun(Pid) -> |
| case hk_browser_session:navigate(Pid, TabId, Url) of |
| ok -> {ok, {browser_tab, TabId}, #{}}; |
| {error, Reason} -> {error, Reason} |
| end |
| end) |
| end, Req1), |
| {ok, Req, navigate}; |
|
|
| init(Req0 = #{method := <<"POST">>}, actions) -> |
| SessionId = cowboy_req:binding(id, Req0), |
| TabId = cowboy_req:binding(tab_id, Req0), |
| RequestId = hk_api_util:request_id(Req0), |
| {ok, Body, Req1} = hk_api_util:read_json_body(Req0), |
| Op = binary_to_atom(maps:get(<<"op">>, Body, <<"read_page">>), utf8), |
| Args = maps:get(<<"args">>, Body, #{}), |
| Req = hk_api_util:run_operation(browser_tab_action, RequestId, fun() -> |
| with_session(SessionId, fun(Pid) -> dispatch(Pid, Op, TabId, Args) end) |
| end, Req1), |
| {ok, Req, actions}; |
|
|
| init(Req0, State) -> |
| Req = hk_api_util:reply_error(405, method_not_allowed, Req0), |
| {ok, Req, State}. |
|
|
| |
|
|
| with_session(undefined, _Fun) -> {error, missing_session_id}; |
| with_session(SessionId, Fun) -> |
| case hk_browser_registry:lookup(SessionId) of |
| {ok, Pid} -> Fun(Pid); |
| {error, not_found} -> {error, session_not_found} |
| end. |
|
|
| dispatch(Pid, back, TabId, _Args) -> as_op(hk_browser_session:back(Pid, TabId), TabId); |
| dispatch(Pid, forward, TabId, _Args) -> as_op(hk_browser_session:forward(Pid, TabId), TabId); |
| dispatch(Pid, reload, TabId, _Args) -> as_op(hk_browser_session:reload(Pid, TabId), TabId); |
| dispatch(Pid, close, TabId, _Args) -> as_op(hk_browser_session:close_tab(Pid, TabId), TabId); |
| dispatch(Pid, read_page, TabId, _Args) -> |
| as_result(hk_browser_session:read_page(Pid, TabId), TabId, text); |
| dispatch(Pid, query_element, TabId, Args) -> |
| Selector = maps:get(<<"selector">>, Args, <<>>), |
| as_result(hk_browser_session:query_element(Pid, TabId, Selector), TabId, element); |
| dispatch(Pid, click, TabId, Args) -> |
| Selector = maps:get(<<"selector">>, Args, <<>>), |
| as_result(hk_browser_session:click(Pid, TabId, Selector), TabId, click); |
| dispatch(Pid, type, TabId, Args) -> |
| Selector = maps:get(<<"selector">>, Args, <<>>), |
| Text = maps:get(<<"text">>, Args, <<>>), |
| as_result(hk_browser_session:type(Pid, TabId, Selector, Text), TabId, type); |
| dispatch(Pid, scroll, TabId, Args) -> |
| Dy = maps:get(<<"delta_y">>, Args, 0), |
| as_result(hk_browser_session:scroll(Pid, TabId, Dy), TabId, scroll); |
| dispatch(Pid, screenshot, TabId, _Args) -> |
| as_result(hk_browser_session:screenshot(Pid, TabId), TabId, screenshot_base64); |
| dispatch(Pid, extract_links, TabId, _Args) -> |
| as_result(hk_browser_session:extract_links(Pid, TabId), TabId, links); |
| dispatch(_Pid, Op, _TabId, _Args) -> |
| {error, {unsupported_op, Op}}. |
|
|
| as_op(ok, TabId) -> {ok, {browser_tab, TabId}, #{}}; |
| as_op({error, Reason}, _TabId) -> {error, Reason}. |
|
|
| as_result({ok, Value}, TabId, Key) -> {ok, {browser_tab, TabId}, #{Key => Value}}; |
| as_result({error, Reason}, _TabId, _Key) -> {error, Reason}. |
|
|
| describe_or_skip(SessionId) -> |
| case hk_browser_registry:lookup(SessionId) of |
| {ok, Pid} -> |
| case catch hk_browser_session:describe(Pid) of |
| {ok, Session} -> {true, hk_schema:to_map(Session)}; |
| _ -> false |
| end; |
| _ -> false |
| end. |
|
|