Skip to content

Commit 33c086d

Browse files
authored
servoshell: Extract duplicate WebDriver methods to common struct (servo#40186)
There are several code duplicates in servoshell. In this PR, we extract identical WebDriver support methods from the desktop and EGL implementations into a shared `RunningAppStateBase` trait in the new `running_app_state`. This eliminates duplicate code while maintaining the same functionality across all platforms. This is the first step in a larger refactoring effort to consolidate shared code between desktop and EGL implementations. Testing: No functional changes. Existing tests should test this. --------- Signed-off-by: atbrakhi <[email protected]>
1 parent 2e950df commit 33c086d

File tree

5 files changed

+106
-83
lines changed

5 files changed

+106
-83
lines changed

ports/servoshell/desktop/app.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ use crate::desktop::tracing::trace_winit_event;
4040
use crate::desktop::window_trait::WindowPortsMethods;
4141
use crate::parser::{get_default_url, location_bar_input_to_url};
4242
use crate::prefs::ServoShellPreferences;
43+
use crate::running_app_state::RunningAppStateTrait;
4344

4445
pub struct App {
4546
opts: Opts,

ports/servoshell/desktop/app_state.rs

Lines changed: 19 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ use servo::{
2020
AllowOrDenyRequest, AuthenticationRequest, EmbedderControl, EmbedderControlId,
2121
GamepadHapticEffectType, InputEvent, InputEventId, InputEventResult, JSValue, LoadStatus,
2222
PermissionRequest, Servo, ServoDelegate, ServoError, SimpleDialog, TraversalId,
23-
WebDriverCommandMsg, WebDriverJSResult, WebDriverLoadStatus, WebDriverSenders,
24-
WebDriverUserPrompt, WebView, WebViewBuilder, WebViewDelegate,
23+
WebDriverCommandMsg, WebDriverLoadStatus, WebDriverUserPrompt, WebView, WebViewBuilder,
24+
WebViewDelegate,
2525
};
2626
use url::Url;
2727

@@ -30,6 +30,7 @@ use super::dialog::Dialog;
3030
use super::gamepad::GamepadSupport;
3131
use super::window_trait::WindowPortsMethods;
3232
use crate::prefs::ServoShellPreferences;
33+
use crate::running_app_state::{RunningAppStateBase, RunningAppStateTrait};
3334

3435
pub(crate) enum AppState {
3536
Initializing,
@@ -38,6 +39,7 @@ pub(crate) enum AppState {
3839
}
3940

4041
pub(crate) struct RunningAppState {
42+
base: RunningAppStateBase,
4143
/// A handle to the Servo instance of the [`RunningAppState`]. This is not stored inside
4244
/// `inner` so that we can keep a reference to Servo in order to spin the event loop,
4345
/// which will in turn call delegates doing a mutable borrow on `inner`.
@@ -48,7 +50,6 @@ pub(crate) struct RunningAppState {
4850
/// A [`Receiver`] for receiving commands from a running WebDriver server, if WebDriver
4951
/// was enabled.
5052
webdriver_receiver: Option<Receiver<WebDriverCommandMsg>>,
51-
webdriver_senders: RefCell<WebDriverSenders>,
5253
inner: RefCell<RunningAppStateInner>,
5354
}
5455

@@ -108,6 +109,16 @@ impl Drop for RunningAppState {
108109
}
109110
}
110111

112+
impl RunningAppStateTrait for RunningAppState {
113+
fn base(&self) -> &RunningAppStateBase {
114+
&self.base
115+
}
116+
117+
fn base_mut(&mut self) -> &mut RunningAppStateBase {
118+
&mut self.base
119+
}
120+
}
121+
111122
impl RunningAppState {
112123
pub fn new(
113124
servo: Servo,
@@ -122,10 +133,10 @@ impl RunningAppState {
122133
None
123134
};
124135
RunningAppState {
136+
base: RunningAppStateBase::new(),
125137
servo,
126138
servoshell_preferences,
127139
webdriver_receiver,
128-
webdriver_senders: RefCell::default(),
129140
inner: RefCell::new(RunningAppStateInner {
130141
webviews: HashMap::default(),
131142
creation_order: Default::default(),
@@ -420,6 +431,7 @@ impl RunningAppState {
420431
// Dialogs block the page load, so need need to notify WebDriver
421432
let webview_id = webview.id();
422433
if let Some(sender) = self
434+
.base()
423435
.webdriver_senders
424436
.borrow_mut()
425437
.load_status_senders
@@ -457,37 +469,6 @@ impl RunningAppState {
457469
.position(|webview| webview.0 == focused_id)
458470
}
459471

460-
pub(crate) fn set_pending_traversal(
461-
&self,
462-
traversal_id: TraversalId,
463-
sender: GenericSender<WebDriverLoadStatus>,
464-
) {
465-
self.webdriver_senders
466-
.borrow_mut()
467-
.pending_traversals
468-
.insert(traversal_id, sender);
469-
}
470-
471-
pub(crate) fn set_load_status_sender(
472-
&self,
473-
webview_id: WebViewId,
474-
sender: GenericSender<WebDriverLoadStatus>,
475-
) {
476-
self.webdriver_senders
477-
.borrow_mut()
478-
.load_status_senders
479-
.insert(webview_id, sender);
480-
}
481-
482-
pub(crate) fn set_script_command_interrupt_sender(
483-
&self,
484-
sender: Option<IpcSender<WebDriverJSResult>>,
485-
) {
486-
self.webdriver_senders
487-
.borrow_mut()
488-
.script_evaluation_interrupt_sender = sender;
489-
}
490-
491472
/// Interrupt any ongoing WebDriver-based script evaluation.
492473
///
493474
/// From <https://w3c.github.io/webdriver/#dfn-execute-a-function-body>:
@@ -499,6 +480,7 @@ impl RunningAppState {
499480
/// > other steps of this algorithm in parallel.
500481
fn interrupt_webdriver_script_evaluation(&self) {
501482
if let Some(sender) = &self
483+
.base()
502484
.webdriver_senders
503485
.borrow()
504486
.script_evaluation_interrupt_sender
@@ -511,13 +493,6 @@ impl RunningAppState {
511493
}
512494
}
513495

514-
pub(crate) fn remove_load_status_sender(&self, webview_id: WebViewId) {
515-
self.webdriver_senders
516-
.borrow_mut()
517-
.load_status_senders
518-
.remove(&webview_id);
519-
}
520-
521496
/// Return a list of all webviews that have favicons that have not yet been loaded by egui.
522497
pub(crate) fn take_pending_favicon_loads(&self) -> Vec<WebViewId> {
523498
mem::take(&mut self.inner_mut().pending_favicon_loads)
@@ -619,7 +594,7 @@ impl WebViewDelegate for RunningAppState {
619594
}
620595

621596
fn notify_traversal_complete(&self, _webview: servo::WebView, traversal_id: TraversalId) {
622-
let mut webdriver_state = self.webdriver_senders.borrow_mut();
597+
let mut webdriver_state = self.base().webdriver_senders.borrow_mut();
623598
if let Entry::Occupied(entry) = webdriver_state.pending_traversals.entry(traversal_id) {
624599
let sender = entry.remove();
625600
let _ = sender.send(WebDriverLoadStatus::Complete);
@@ -713,6 +688,7 @@ impl WebViewDelegate for RunningAppState {
713688

714689
if status == LoadStatus::Complete {
715690
if let Some(sender) = self
691+
.base()
716692
.webdriver_senders
717693
.borrow_mut()
718694
.load_status_senders

ports/servoshell/egl/app_state.rs

Lines changed: 15 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use url::Url;
3232

3333
use crate::egl::host_trait::HostTrait;
3434
use crate::prefs::ServoShellPreferences;
35+
use crate::running_app_state::{RunningAppStateBase, RunningAppStateTrait};
3536

3637
#[derive(Clone, Debug)]
3738
pub struct Coordinates {
@@ -72,6 +73,7 @@ impl ServoWindowCallbacks {
7273
}
7374

7475
pub struct RunningAppState {
76+
base: RunningAppStateBase,
7577
servo: Servo,
7678
rendering_context: Rc<WindowRenderingContext>,
7779
callbacks: Rc<ServoWindowCallbacks>,
@@ -82,7 +84,6 @@ pub struct RunningAppState {
8284
/// A [`Receiver`] for receiving commands from a running WebDriver server, if WebDriver
8385
/// was enabled.
8486
webdriver_receiver: Option<Receiver<WebDriverCommandMsg>>,
85-
webdriver_senders: RefCell<WebDriverSenders>,
8687
}
8788

8889
struct RunningAppStateInner {
@@ -172,6 +173,7 @@ impl WebViewDelegate for RunningAppState {
172173

173174
if load_status == LoadStatus::Complete {
174175
if let Some(sender) = self
176+
.base()
175177
.webdriver_senders
176178
.borrow_mut()
177179
.load_status_senders
@@ -226,7 +228,7 @@ impl WebViewDelegate for RunningAppState {
226228
}
227229

228230
fn notify_traversal_complete(&self, _webview: servo::WebView, traversal_id: TraversalId) {
229-
let mut webdriver_state = self.webdriver_senders.borrow_mut();
231+
let mut webdriver_state = self.base().webdriver_senders.borrow_mut();
230232
if let std::collections::hash_map::Entry::Occupied(entry) =
231233
webdriver_state.pending_traversals.entry(traversal_id)
232234
{
@@ -367,6 +369,16 @@ impl RefreshDriver for VsyncRefreshDriver {
367369
}
368370
}
369371

372+
impl RunningAppStateTrait for RunningAppState {
373+
fn base(&self) -> &RunningAppStateBase {
374+
&self.base
375+
}
376+
377+
fn base_mut(&mut self) -> &mut RunningAppStateBase {
378+
&mut self.base
379+
}
380+
}
381+
370382
#[allow(unused)]
371383
impl RunningAppState {
372384
pub(super) fn new(
@@ -391,13 +403,13 @@ impl RunningAppState {
391403
}));
392404

393405
let app_state = Rc::new(Self {
406+
base: RunningAppStateBase::new(),
394407
rendering_context,
395408
servo,
396409
callbacks,
397410
refresh_driver,
398411
servoshell_preferences,
399412
webdriver_receiver,
400-
webdriver_senders: RefCell::default(),
401413
inner: RefCell::new(RunningAppStateInner {
402414
need_present: false,
403415
context_menu_sender: None,
@@ -415,26 +427,6 @@ impl RunningAppState {
415427
app_state
416428
}
417429

418-
pub(crate) fn set_script_command_interrupt_sender(
419-
&self,
420-
sender: Option<IpcSender<WebDriverJSResult>>,
421-
) {
422-
self.webdriver_senders
423-
.borrow_mut()
424-
.script_evaluation_interrupt_sender = sender;
425-
}
426-
427-
pub(crate) fn set_pending_traversal(
428-
&self,
429-
traversal_id: TraversalId,
430-
sender: GenericSender<WebDriverLoadStatus>,
431-
) {
432-
self.webdriver_senders
433-
.borrow_mut()
434-
.pending_traversals
435-
.insert(traversal_id, sender);
436-
}
437-
438430
pub fn webviews(&self) -> Vec<(WebViewId, WebView)> {
439431
let inner = self.inner();
440432
inner
@@ -772,23 +764,6 @@ impl RunningAppState {
772764
}
773765
}
774766

775-
pub(crate) fn set_load_status_sender(
776-
&self,
777-
webview_id: WebViewId,
778-
sender: GenericSender<WebDriverLoadStatus>,
779-
) {
780-
self.webdriver_senders
781-
.borrow_mut()
782-
.load_status_senders
783-
.insert(webview_id, sender);
784-
}
785-
786-
pub(crate) fn remove_load_status_sender(&self, webview_id: WebViewId) {
787-
self.webdriver_senders
788-
.borrow_mut()
789-
.load_status_senders
790-
.remove(&webview_id);
791-
}
792767
/// Touch event: press down
793768
pub fn touch_down(&self, x: f32, y: f32, pointer_id: i32) {
794769
self.active_webview()

ports/servoshell/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ mod parser;
2121
mod prefs;
2222
#[cfg(not(any(target_os = "android", target_env = "ohos")))]
2323
mod resources;
24+
mod running_app_state;
2425

2526
pub mod platform {
2627
#[cfg(target_os = "macos")]
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4+
5+
//! Shared state and methods for desktop and EGL implementations.
6+
7+
use std::cell::RefCell;
8+
9+
use servo::base::generic_channel::GenericSender;
10+
use servo::base::id::WebViewId;
11+
use servo::ipc_channel::ipc::IpcSender;
12+
use servo::{TraversalId, WebDriverJSResult, WebDriverLoadStatus, WebDriverSenders};
13+
14+
pub struct RunningAppStateBase {
15+
pub(crate) webdriver_senders: RefCell<WebDriverSenders>,
16+
}
17+
18+
impl RunningAppStateBase {
19+
pub fn new() -> Self {
20+
Self {
21+
webdriver_senders: RefCell::default(),
22+
}
23+
}
24+
}
25+
26+
pub trait RunningAppStateTrait {
27+
fn base(&self) -> &RunningAppStateBase;
28+
29+
#[allow(dead_code)]
30+
fn base_mut(&mut self) -> &mut RunningAppStateBase;
31+
32+
fn set_pending_traversal(
33+
&self,
34+
traversal_id: TraversalId,
35+
sender: GenericSender<WebDriverLoadStatus>,
36+
) {
37+
self.base()
38+
.webdriver_senders
39+
.borrow_mut()
40+
.pending_traversals
41+
.insert(traversal_id, sender);
42+
}
43+
44+
fn set_load_status_sender(
45+
&self,
46+
webview_id: WebViewId,
47+
sender: GenericSender<WebDriverLoadStatus>,
48+
) {
49+
self.base()
50+
.webdriver_senders
51+
.borrow_mut()
52+
.load_status_senders
53+
.insert(webview_id, sender);
54+
}
55+
56+
fn remove_load_status_sender(&self, webview_id: WebViewId) {
57+
self.base()
58+
.webdriver_senders
59+
.borrow_mut()
60+
.load_status_senders
61+
.remove(&webview_id);
62+
}
63+
64+
fn set_script_command_interrupt_sender(&self, sender: Option<IpcSender<WebDriverJSResult>>) {
65+
self.base()
66+
.webdriver_senders
67+
.borrow_mut()
68+
.script_evaluation_interrupt_sender = sender;
69+
}
70+
}

0 commit comments

Comments
 (0)