11use std:: path:: PathBuf ;
2+ use std:: sync:: Arc ;
23
34use anyhow:: Result ;
45use serde:: { Deserialize , Serialize } ;
@@ -7,6 +8,7 @@ use url::Url;
78
89use crate :: bookmarks:: BookmarkStore ;
910use crate :: cli:: HeadlessAction ;
11+ use crate :: ipc_navigator:: IpcNavigator ;
1012use crate :: navigation:: { InProcessNavigator , NavigationService } ;
1113use crate :: tab:: { TabId , TabManager , TabState } ;
1214
@@ -15,20 +17,50 @@ pub fn run_headless(
1517 action : HeadlessAction ,
1618 allow_http : bool ,
1719 data_dir : Option < String > ,
20+ single_process : bool ,
1821) -> Result < ( ) > {
1922 let rt = tokio:: runtime:: Runtime :: new ( ) ?;
2023 rt. block_on ( async {
2124 match action {
22- HeadlessAction :: DumpSource => run_dump_source ( url. unwrap ( ) , allow_http) . await ,
23- HeadlessAction :: DumpStatus => run_dump_status ( url. unwrap ( ) , allow_http) . await ,
24- HeadlessAction :: Interactive => run_interactive ( allow_http, data_dir) . await ,
25+ HeadlessAction :: DumpSource => {
26+ run_dump_source ( url. unwrap ( ) , allow_http, single_process) . await
27+ }
28+ HeadlessAction :: DumpStatus => {
29+ run_dump_status ( url. unwrap ( ) , allow_http, single_process) . await
30+ }
31+ HeadlessAction :: Interactive => {
32+ run_interactive ( allow_http, data_dir, single_process) . await
33+ }
2534 }
2635 } )
2736}
2837
29- async fn run_dump_source ( url : Url , allow_http : bool ) -> Result < ( ) > {
30- let navigator = InProcessNavigator :: new ( ) ?. with_https_only ( !allow_http) ;
31- match navigator. navigate ( & url) . await {
38+ struct NavigatorHandle {
39+ navigator : Arc < dyn NavigationService + Send + Sync > ,
40+ _child : Option < ie_sandbox:: ChildHandle > ,
41+ }
42+
43+ async fn create_navigator ( allow_http : bool , single_process : bool ) -> Result < NavigatorHandle > {
44+ if single_process {
45+ let nav = InProcessNavigator :: new ( ) ?. with_https_only ( !allow_http) ;
46+ Ok ( NavigatorHandle {
47+ navigator : Arc :: new ( nav) ,
48+ _child : None ,
49+ } )
50+ } else {
51+ let mut child = ie_sandbox:: spawn_child ( ie_sandbox:: ProcessKind :: Network ) . await ?;
52+ let channel = child. take_channel ( ) ;
53+ let nav = IpcNavigator :: new ( channel, !allow_http) ;
54+ Ok ( NavigatorHandle {
55+ navigator : Arc :: new ( nav) ,
56+ _child : Some ( child) ,
57+ } )
58+ }
59+ }
60+
61+ async fn run_dump_source ( url : Url , allow_http : bool , single_process : bool ) -> Result < ( ) > {
62+ let handle = create_navigator ( allow_http, single_process) . await ?;
63+ match handle. navigator . navigate ( & url) . await {
3264 Ok ( result) => {
3365 let text = String :: from_utf8_lossy ( & result. body ) ;
3466 print ! ( "{text}" ) ;
@@ -41,9 +73,9 @@ async fn run_dump_source(url: Url, allow_http: bool) -> Result<()> {
4173 }
4274}
4375
44- async fn run_dump_status ( url : Url , allow_http : bool ) -> Result < ( ) > {
45- let navigator = InProcessNavigator :: new ( ) ? . with_https_only ( ! allow_http) ;
46- match navigator. navigate ( & url) . await {
76+ async fn run_dump_status ( url : Url , allow_http : bool , single_process : bool ) -> Result < ( ) > {
77+ let handle = create_navigator ( allow_http, single_process ) . await ? ;
78+ match handle . navigator . navigate ( & url) . await {
4779 Ok ( result) => {
4880 println ! ( "{}" , result. status) ;
4981 Ok ( ( ) )
@@ -122,20 +154,22 @@ impl Response {
122154struct HeadlessSession {
123155 tab_manager : TabManager ,
124156 bookmark_store : BookmarkStore ,
125- navigator : InProcessNavigator ,
157+ navigator : Arc < dyn NavigationService + Send + Sync > ,
158+ _child : Option < ie_sandbox:: ChildHandle > ,
126159}
127160
128161impl HeadlessSession {
129- fn new ( allow_http : bool , data_dir : Option < String > ) -> Result < Self > {
130- let navigator = InProcessNavigator :: new ( ) ? . with_https_only ( ! allow_http) ;
162+ async fn new ( allow_http : bool , data_dir : Option < String > , single_process : bool ) -> Result < Self > {
163+ let handle = create_navigator ( allow_http, single_process ) . await ? ;
131164 let bookmark_path = data_dir
132165 . map ( PathBuf :: from)
133166 . unwrap_or_else ( || std:: env:: temp_dir ( ) . join ( "ie-headless" ) ) ;
134167 let bookmark_store = BookmarkStore :: new ( & bookmark_path) ?;
135168 Ok ( Self {
136169 tab_manager : TabManager :: new ( ) ,
137170 bookmark_store,
138- navigator,
171+ navigator : handle. navigator ,
172+ _child : handle. _child ,
139173 } )
140174 }
141175
@@ -169,7 +203,6 @@ impl HeadlessSession {
169203 tab. url = Some ( url. clone ( ) ) ;
170204 }
171205
172- // Sequential: navigate blocks until complete
173206 match self . navigator . navigate ( & url) . await {
174207 Ok ( result) => {
175208 let source = String :: from_utf8 ( result. body ) . ok ( ) ;
@@ -303,10 +336,14 @@ impl HeadlessSession {
303336 }
304337}
305338
306- async fn run_interactive ( allow_http : bool , data_dir : Option < String > ) -> Result < ( ) > {
339+ async fn run_interactive (
340+ allow_http : bool ,
341+ data_dir : Option < String > ,
342+ single_process : bool ,
343+ ) -> Result < ( ) > {
307344 let stdin = BufReader :: new ( tokio:: io:: stdin ( ) ) ;
308345 let mut stdout = tokio:: io:: stdout ( ) ;
309- let mut session = HeadlessSession :: new ( allow_http, data_dir) ?;
346+ let mut session = HeadlessSession :: new ( allow_http, data_dir, single_process ) . await ?;
310347
311348 let mut lines = stdin. lines ( ) ;
312349 while let Ok ( Some ( line) ) = lines. next_line ( ) . await {
0 commit comments