From 8c199ac526e515c4e5441dd0957d1154566fd160 Mon Sep 17 00:00:00 2001 From: chanxuehong Date: Fri, 3 Apr 2026 10:17:09 +0800 Subject: [PATCH] Fix a logic bug in Browser::create_browser_context. Browser::start_incognito_context creates a new BrowserContext and sends a HandlerMessage::InsertContext message, whereas Browser::create_browser_context does not perform this step. This commit fixes the inconsistency and also improves the code structure. --- src/browser/mod.rs | 29 +++++++------ src/handler/mod.rs | 106 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 116 insertions(+), 19 deletions(-) diff --git a/src/browser/mod.rs b/src/browser/mod.rs index 3891cb30..7e49c81a 100644 --- a/src/browser/mod.rs +++ b/src/browser/mod.rs @@ -330,10 +330,6 @@ impl Browser { .create_browser_context(CreateBrowserContextParams::default()) .await?; self.browser_context = BrowserContext::from(browser_context_id); - self.sender - .clone() - .send(HandlerMessage::InsertContext(self.browser_context.clone())) - .await?; } Ok(self) @@ -346,11 +342,7 @@ impl Browser { /// incognito context. pub async fn quit_incognito_context(&mut self) -> Result<&mut Self> { if let Some(id) = self.browser_context.take() { - self.dispose_browser_context(id.clone()).await?; - self.sender - .clone() - .send(HandlerMessage::DisposeContext(BrowserContext::from(id))) - .await?; + self.dispose_browser_context(id).await?; } Ok(self) } @@ -458,8 +450,14 @@ impl Browser { &self, params: CreateBrowserContextParams, ) -> Result { - let response = self.execute(params).await?; - Ok(response.result.browser_context_id) + let (tx, rx) = oneshot_channel(); + + self.sender + .clone() + .send(HandlerMessage::CreateBrowserContext(params, tx)) + .await?; + + rx.await? } /// Deletes a browser context. @@ -467,10 +465,15 @@ impl Browser { &self, browser_context_id: impl Into, ) -> Result<()> { - self.execute(DisposeBrowserContextParams::new(browser_context_id)) + let (tx, rx) = oneshot_channel(); + + let params = DisposeBrowserContextParams::new(browser_context_id); + self.sender + .clone() + .send(HandlerMessage::DisposeBrowserContext(params, tx)) .await?; - Ok(()) + rx.await? } /// Clears cookies. diff --git a/src/handler/mod.rs b/src/handler/mod.rs index 6b5b16d1..3b4214a4 100644 --- a/src/handler/mod.rs +++ b/src/handler/mod.rs @@ -237,6 +237,30 @@ impl Handler { } } } + PendingRequest::CreateBrowserContext(tx) => { + match to_command_response::(resp, method) { + Ok(resp) => { + self.browser_contexts + .insert(BrowserContext::from(resp.browser_context_id.clone())); + let _ = tx.send(Ok(resp.browser_context_id.clone())).ok(); + } + Err(err) => { + let _ = tx.send(Err(err)).ok(); + } + } + } + PendingRequest::DisposeBrowserContext(browser_context_id, tx) => { + match to_command_response::(resp, method) { + Ok(_resp) => { + self.browser_contexts + .remove(&BrowserContext::from(browser_context_id)); + let _ = tx.send(Ok(())).ok(); + } + Err(err) => { + let _ = tx.send(Err(err)).ok(); + } + } + } PendingRequest::Navigate(id) => { self.on_navigation_response(id, resp); } @@ -395,6 +419,63 @@ impl Handler { } } + fn create_browser_context( + &mut self, + params: CreateBrowserContextParams, + tx: OneshotSender>, + ) { + let method = params.identifier(); + match serde_json::to_value(params) { + Ok(params) => match self.conn.submit_command(method.clone(), None, params) { + Ok(call_id) => { + self.pending_commands.insert( + call_id, + ( + PendingRequest::CreateBrowserContext(tx), + method, + Instant::now(), + ), + ); + } + Err(err) => { + let _ = tx.send(Err(err.into())).ok(); + } + }, + Err(err) => { + let _ = tx.send(Err(err.into())).ok(); + } + } + } + + fn dispose_browser_context( + &mut self, + params: DisposeBrowserContextParams, + tx: OneshotSender>, + ) { + let method = params.identifier(); + let browser_context_id = params.browser_context_id.clone(); + match serde_json::to_value(params) { + Ok(params) => match self.conn.submit_command(method.clone(), None, params) { + Ok(call_id) => { + self.pending_commands.insert( + call_id, + ( + PendingRequest::DisposeBrowserContext(browser_context_id, tx), + method, + Instant::now(), + ), + ); + } + Err(err) => { + let _ = tx.send(Err(err.into())).ok(); + } + }, + Err(err) => { + let _ = tx.send(Err(err.into())).ok(); + } + } + } + /// Process an incoming event read from the websocket fn on_event(&mut self, event: CdpEventMessage) { if let Some(ref session_id) = event.session_id { @@ -495,6 +576,12 @@ impl Handler { PendingRequest::GetTargets(tx) => { let _ = tx.send(Err(CdpError::Timeout)); } + PendingRequest::CreateBrowserContext(tx) => { + let _ = tx.send(Err(CdpError::Timeout)); + } + PendingRequest::DisposeBrowserContext(_browser_context_id, tx) => { + let _ = tx.send(Err(CdpError::Timeout)); + } PendingRequest::Navigate(nav) => { if let Some(nav) = self.navigations.remove(&nav) { match nav { @@ -556,11 +643,11 @@ impl Stream for Handler { .collect(); let _ = tx.send(pages); } - HandlerMessage::InsertContext(ctx) => { - pin.browser_contexts.insert(ctx); + HandlerMessage::CreateBrowserContext(params, tx) => { + pin.create_browser_context(params, tx); } - HandlerMessage::DisposeContext(ctx) => { - pin.browser_contexts.remove(&ctx); + HandlerMessage::DisposeBrowserContext(params, tx) => { + pin.dispose_browser_context(params, tx); } HandlerMessage::GetPage(target_id, tx) => { let page = pin @@ -733,6 +820,10 @@ enum PendingRequest { CreateTarget(OneshotSender>), /// A Request to fetch old `Target`s created before connection GetTargets(OneshotSender>>), + /// A Request to create a new `BrowserContext`. + CreateBrowserContext(OneshotSender>), + /// A Request to dispose an old `BrowserContext`. + DisposeBrowserContext(BrowserContextId, OneshotSender>), /// A Request to navigate a specific `Target`. /// /// Navigation requests are not automatically completed once the response to @@ -756,8 +847,11 @@ enum PendingRequest { pub(crate) enum HandlerMessage { CreatePage(CreateTargetParams, OneshotSender>), FetchTargets(OneshotSender>>), - InsertContext(BrowserContext), - DisposeContext(BrowserContext), + CreateBrowserContext( + CreateBrowserContextParams, + OneshotSender>, + ), + DisposeBrowserContext(DisposeBrowserContextParams, OneshotSender>), GetPages(OneshotSender>), Command(CommandMessage), GetPage(TargetId, OneshotSender>),