mirror of
https://github.com/servo/servo.git
synced 2025-08-30 09:38:19 +01:00
[webdriver] Move Webdriver to ServoShell (#36714)
Moving `webdriver` to `servoshell`: - Let `servoshell` manage lifecycle of `webdriver` - One by one, move the handling of webdriver commands from `constellation` to `embedder` Partially fix: https://github.com/servo/servo/issues/37370 Partially fix webdriver test timeout with `no_top_browsing_context` cc: @xiaochengh --------- Signed-off-by: batu_hoang <longvatrong111@gmail.com>
This commit is contained in:
parent
d55e2c4c90
commit
d0100797e8
9 changed files with 156 additions and 35 deletions
|
@ -12,13 +12,14 @@ use std::time::Instant;
|
|||
use std::{env, fs};
|
||||
|
||||
use ::servo::ServoBuilder;
|
||||
use crossbeam_channel::unbounded;
|
||||
use log::{info, trace, warn};
|
||||
use net::protocols::ProtocolRegistry;
|
||||
use servo::EventLoopWaker;
|
||||
use servo::config::opts::Opts;
|
||||
use servo::config::prefs::Preferences;
|
||||
use servo::servo_url::ServoUrl;
|
||||
use servo::user_content_manager::{UserContentManager, UserScript};
|
||||
use servo::{EventLoopWaker, WebDriverCommandMsg};
|
||||
use url::Url;
|
||||
use winit::application::ApplicationHandler;
|
||||
use winit::event::WindowEvent;
|
||||
|
@ -154,10 +155,28 @@ impl App {
|
|||
let servo = servo_builder.build();
|
||||
servo.setup_logging();
|
||||
|
||||
// Initialize WebDriver server here before `servo` is moved.
|
||||
let webdriver_receiver = self.opts.webdriver_port.map(|port| {
|
||||
let (embedder_sender, embedder_receiver) = unbounded();
|
||||
|
||||
// TODO: WebDriver will no longer need this channel once all WebDriver
|
||||
// commands are executed via the Servo API.
|
||||
let constellation_sender_deprecated = servo.constellation_sender();
|
||||
webdriver_server::start_server(
|
||||
port,
|
||||
constellation_sender_deprecated,
|
||||
embedder_sender,
|
||||
self.waker.clone(),
|
||||
);
|
||||
|
||||
embedder_receiver
|
||||
});
|
||||
|
||||
let running_state = Rc::new(RunningAppState::new(
|
||||
servo,
|
||||
window.clone(),
|
||||
self.servoshell_preferences.clone(),
|
||||
webdriver_receiver,
|
||||
));
|
||||
running_state.new_toplevel_webview(self.initial_url.clone().into_url());
|
||||
|
||||
|
@ -296,6 +315,49 @@ impl App {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_webdriver_messages(&mut self) {
|
||||
let AppState::Running(running_state) = &self.state else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(webdriver_receiver) = running_state.webdriver_receiver() else {
|
||||
return;
|
||||
};
|
||||
|
||||
while let Ok(msg) = webdriver_receiver.try_recv() {
|
||||
match msg {
|
||||
WebDriverCommandMsg::IsWebViewOpen(webview_id, sender) => {
|
||||
let context = running_state.webview_by_id(webview_id);
|
||||
sender.send(context.is_some()).unwrap();
|
||||
},
|
||||
webdriver_msg @ WebDriverCommandMsg::IsBrowsingContextOpen(..) => {
|
||||
running_state.forward_webdriver_command(webdriver_msg);
|
||||
},
|
||||
WebDriverCommandMsg::CloseWebView(webview_id) => {
|
||||
running_state.close_webview(webview_id);
|
||||
},
|
||||
WebDriverCommandMsg::GetWindowSize(..) |
|
||||
WebDriverCommandMsg::FocusWebView(..) |
|
||||
WebDriverCommandMsg::LoadUrl(..) |
|
||||
WebDriverCommandMsg::ScriptCommand(..) |
|
||||
WebDriverCommandMsg::SendKeys(..) |
|
||||
WebDriverCommandMsg::KeyboardAction(..) |
|
||||
WebDriverCommandMsg::MouseButtonAction(..) |
|
||||
WebDriverCommandMsg::MouseMoveAction(..) |
|
||||
WebDriverCommandMsg::WheelScrollAction(..) |
|
||||
WebDriverCommandMsg::SetWindowSize(..) |
|
||||
WebDriverCommandMsg::TakeScreenshot(..) |
|
||||
WebDriverCommandMsg::NewWebView(..) |
|
||||
WebDriverCommandMsg::Refresh(..) => {
|
||||
warn!(
|
||||
"WebDriverCommand {:?} is still not moved from constellation to embedder",
|
||||
msg
|
||||
);
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ApplicationHandler<WakerEvent> for App {
|
||||
|
@ -435,6 +497,9 @@ impl ApplicationHandler<WakerEvent> for App {
|
|||
// Consume and handle any events from the Minibrowser.
|
||||
self.handle_servoshell_ui_events();
|
||||
|
||||
// Consume and handle any events from the WebDriver.
|
||||
self.handle_webdriver_messages();
|
||||
|
||||
self.handle_events_with_winit(event_loop, window);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ use std::collections::HashMap;
|
|||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crossbeam_channel::Receiver;
|
||||
use euclid::Vector2D;
|
||||
use keyboard_types::{Key, Modifiers, ShortcutMatcher};
|
||||
use log::{error, info};
|
||||
|
@ -18,7 +19,7 @@ use servo::webrender_api::units::{DeviceIntPoint, DeviceIntSize};
|
|||
use servo::{
|
||||
AllowOrDenyRequest, AuthenticationRequest, FilterPattern, FormControl, GamepadHapticEffectType,
|
||||
KeyboardEvent, LoadStatus, PermissionRequest, Servo, ServoDelegate, ServoError, SimpleDialog,
|
||||
TouchEventType, WebView, WebViewBuilder, WebViewDelegate,
|
||||
TouchEventType, WebDriverCommandMsg, WebView, WebViewBuilder, WebViewDelegate,
|
||||
};
|
||||
use url::Url;
|
||||
|
||||
|
@ -44,6 +45,9 @@ pub(crate) struct RunningAppState {
|
|||
/// The preferences for this run of servoshell. This is not mutable, so doesn't need to
|
||||
/// be stored inside the [`RunningAppStateInner`].
|
||||
servoshell_preferences: ServoShellPreferences,
|
||||
/// A [`Receiver`] for receiving commands from a running WebDriver server, if WebDriver
|
||||
/// was enabled.
|
||||
webdriver_receiver: Option<Receiver<WebDriverCommandMsg>>,
|
||||
inner: RefCell<RunningAppStateInner>,
|
||||
}
|
||||
|
||||
|
@ -88,11 +92,13 @@ impl RunningAppState {
|
|||
servo: Servo,
|
||||
window: Rc<dyn WindowPortsMethods>,
|
||||
servoshell_preferences: ServoShellPreferences,
|
||||
webdriver_receiver: Option<Receiver<WebDriverCommandMsg>>,
|
||||
) -> RunningAppState {
|
||||
servo.set_delegate(Rc::new(ServoShellServoDelegate));
|
||||
RunningAppState {
|
||||
servo,
|
||||
servoshell_preferences,
|
||||
webdriver_receiver,
|
||||
inner: RefCell::new(RunningAppStateInner {
|
||||
webviews: HashMap::default(),
|
||||
creation_order: Default::default(),
|
||||
|
@ -132,6 +138,14 @@ impl RunningAppState {
|
|||
&self.servo
|
||||
}
|
||||
|
||||
pub(crate) fn webdriver_receiver(&self) -> Option<&Receiver<WebDriverCommandMsg>> {
|
||||
self.webdriver_receiver.as_ref()
|
||||
}
|
||||
|
||||
pub(crate) fn forward_webdriver_command(&self, command: WebDriverCommandMsg) {
|
||||
self.servo().execute_webdriver_command(command);
|
||||
}
|
||||
|
||||
pub(crate) fn hidpi_scale_factor_changed(&self) {
|
||||
let inner = self.inner();
|
||||
let new_scale_factor = inner.window.hidpi_scale_factor();
|
||||
|
@ -261,6 +275,10 @@ impl RunningAppState {
|
|||
.collect()
|
||||
}
|
||||
|
||||
pub fn webview_by_id(&self, id: WebViewId) -> Option<WebView> {
|
||||
self.inner().webviews.get(&id).cloned()
|
||||
}
|
||||
|
||||
pub fn handle_gamepad_events(&self) {
|
||||
let Some(active_webview) = self.focused_webview() else {
|
||||
return;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue