mirror of
https://github.com/servo/servo.git
synced 2025-08-13 17:35:36 +01:00
Basic webdriver support to servoshell on ohos (#38386)
Adding basic webdriver support to servoshell on ohos and basic communication between the ohos device and script. Testing: Manual testing and tracing logs Signed-off-by: abdelrahman1234567 <abdelrahman.hossameldin.awadalla@huawei.com>
This commit is contained in:
parent
f5b631e270
commit
2e2bfc6067
9 changed files with 113 additions and 17 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -7752,6 +7752,7 @@ dependencies = [
|
|||
"egui-file-dialog",
|
||||
"egui-winit",
|
||||
"egui_glow",
|
||||
"embedder_traits",
|
||||
"env_filter",
|
||||
"euclid",
|
||||
"getopts",
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
pub mod input_events;
|
||||
pub mod resources;
|
||||
pub mod user_content_manager;
|
||||
mod webdriver;
|
||||
pub mod webdriver;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::c_void;
|
||||
|
|
|
@ -23,7 +23,7 @@ use webdriver::common::{WebElement, WebFrame, WebWindow};
|
|||
use webdriver::error::ErrorStatus;
|
||||
use webrender_api::units::DevicePixel;
|
||||
|
||||
use crate::{MouseButton, MouseButtonAction};
|
||||
use crate::{FocusId, MouseButton, MouseButtonAction, TraversalId};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct WebDriverMessageId(pub usize);
|
||||
|
@ -301,3 +301,13 @@ pub enum WebDriverLoadStatus {
|
|||
// Navigation is blocked by a user prompt
|
||||
Blocked,
|
||||
}
|
||||
|
||||
/// A collection of [`IpcSender`]s that are used to asynchronously communicate
|
||||
/// to a WebDriver server with information about application state.
|
||||
#[derive(Clone, Default)]
|
||||
pub struct WebDriverSenders {
|
||||
pub load_status_senders: HashMap<WebViewId, IpcSender<WebDriverLoadStatus>>,
|
||||
pub script_evaluation_interrupt_sender: Option<IpcSender<WebDriverJSResult>>,
|
||||
pub pending_traversals: HashMap<TraversalId, IpcSender<WebDriverLoadStatus>>,
|
||||
pub pending_focus: HashMap<FocusId, IpcSender<bool>>,
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@ cfg-if = { workspace = true }
|
|||
constellation_traits = { workspace = true }
|
||||
crossbeam-channel = { workspace = true }
|
||||
dpi = { workspace = true }
|
||||
embedder_traits = { path = "../../components/shared/embedder" }
|
||||
euclid = { workspace = true }
|
||||
getopts = { workspace = true }
|
||||
hitrace = { workspace = true, optional = true }
|
||||
|
|
|
@ -9,6 +9,7 @@ use std::path::PathBuf;
|
|||
use std::rc::Rc;
|
||||
|
||||
use crossbeam_channel::Receiver;
|
||||
use embedder_traits::webdriver::WebDriverSenders;
|
||||
use euclid::Vector2D;
|
||||
use keyboard_types::{Key, Modifiers, NamedKey, ShortcutMatcher};
|
||||
use log::{error, info};
|
||||
|
@ -40,16 +41,6 @@ pub(crate) enum AppState {
|
|||
ShuttingDown,
|
||||
}
|
||||
|
||||
/// A collection of [`IpcSender`]s that are used to asynchronously communicate
|
||||
/// to a WebDriver server with information about application state.
|
||||
#[derive(Clone, Default)]
|
||||
struct WebDriverSenders {
|
||||
pub load_status_senders: HashMap<WebViewId, IpcSender<WebDriverLoadStatus>>,
|
||||
pub script_evaluation_interrupt_sender: Option<IpcSender<WebDriverJSResult>>,
|
||||
pub pending_traversals: HashMap<TraversalId, IpcSender<WebDriverLoadStatus>>,
|
||||
pub pending_focus: HashMap<FocusId, IpcSender<bool>>,
|
||||
}
|
||||
|
||||
pub(crate) struct RunningAppState {
|
||||
/// A handle to the Servo instance of the [`RunningAppState`]. This is not stored inside
|
||||
/// `inner` so that we can keep a reference to Servo in order to spin the event loop,
|
||||
|
|
|
@ -6,8 +6,11 @@ use std::cell::RefCell;
|
|||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
|
||||
use constellation_traits::EmbedderToConstellationMessage;
|
||||
use crossbeam_channel::unbounded;
|
||||
use dpi::PhysicalSize;
|
||||
use raw_window_handle::{DisplayHandle, RawDisplayHandle, RawWindowHandle, WindowHandle};
|
||||
use servo::ipc_channel::ipc;
|
||||
pub use servo::webrender_api::units::DeviceIntRect;
|
||||
use servo::{self, EventLoopWaker, ServoBuilder, resources};
|
||||
pub use servo::{InputMethodType, MediaSessionPlaybackState, WindowRenderingContext};
|
||||
|
@ -84,21 +87,43 @@ pub fn init(
|
|||
let servo_builder = ServoBuilder::new(rendering_context.clone())
|
||||
.opts(opts)
|
||||
.preferences(preferences)
|
||||
.event_loop_waker(waker);
|
||||
.event_loop_waker(waker.clone());
|
||||
|
||||
#[cfg(feature = "webxr")]
|
||||
let servo_builder = servo_builder.webxr_registry(Box::new(XrDiscoveryWebXrRegistry::new(
|
||||
init_opts.xr_discovery,
|
||||
)));
|
||||
|
||||
let servo = servo_builder.build();
|
||||
|
||||
// Initialize WebDriver server if port is specified
|
||||
let webdriver_receiver = servoshell_preferences.webdriver_port.map(|port| {
|
||||
let (embedder_sender, embedder_receiver) = unbounded();
|
||||
let (webdriver_response_sender, webdriver_response_receiver) = ipc::channel().unwrap();
|
||||
|
||||
// Set the WebDriver response sender to constellation
|
||||
servo
|
||||
.constellation_sender()
|
||||
.send(EmbedderToConstellationMessage::SetWebDriverResponseSender(
|
||||
webdriver_response_sender,
|
||||
))
|
||||
.expect("Failed to set WebDriver response sender in constellation");
|
||||
|
||||
webdriver_server::start_server(port, embedder_sender, waker, webdriver_response_receiver);
|
||||
|
||||
log::info!("WebDriver server started on port {}", port);
|
||||
embedder_receiver
|
||||
});
|
||||
|
||||
APP.with(|app| {
|
||||
let app_state = RunningAppState::new(
|
||||
init_opts.url,
|
||||
init_opts.density,
|
||||
rendering_context,
|
||||
servo_builder.build(),
|
||||
servo,
|
||||
window_callbacks,
|
||||
servoshell_preferences,
|
||||
webdriver_receiver,
|
||||
);
|
||||
*app.borrow_mut() = Some(app_state);
|
||||
});
|
||||
|
|
|
@ -5,7 +5,9 @@ use std::cell::{Cell, Ref, RefCell, RefMut};
|
|||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crossbeam_channel::Receiver;
|
||||
use dpi::PhysicalSize;
|
||||
use embedder_traits::webdriver::WebDriverSenders;
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
use log::{debug, error, info, warn};
|
||||
use raw_window_handle::{RawWindowHandle, WindowHandle};
|
||||
|
@ -19,8 +21,8 @@ use servo::{
|
|||
InputEvent, InputMethodType, Key, KeyState, KeyboardEvent, LoadStatus, MediaSessionActionType,
|
||||
MediaSessionEvent, MouseButton, MouseButtonAction, MouseButtonEvent, MouseMoveEvent, NamedKey,
|
||||
NavigationRequest, PermissionRequest, RenderingContext, ScreenGeometry, Servo, ServoDelegate,
|
||||
ServoError, SimpleDialog, TouchEvent, TouchEventType, TouchId, WebView, WebViewBuilder,
|
||||
WebViewDelegate, WindowRenderingContext,
|
||||
ServoError, SimpleDialog, TouchEvent, TouchEventType, TouchId, WebDriverCommandMsg, WebView,
|
||||
WebViewBuilder, WebViewDelegate, WindowRenderingContext,
|
||||
};
|
||||
use url::Url;
|
||||
|
||||
|
@ -73,6 +75,10 @@ pub struct RunningAppState {
|
|||
inner: RefCell<RunningAppStateInner>,
|
||||
/// servoshell specific preferences created during startup of the application.
|
||||
servoshell_preferences: ServoShellPreferences,
|
||||
/// A [`Receiver`] for receiving commands from a running WebDriver server, if WebDriver
|
||||
/// was enabled.
|
||||
webdriver_receiver: Option<Receiver<WebDriverCommandMsg>>,
|
||||
webdriver_senders: RefCell<WebDriverSenders>,
|
||||
}
|
||||
|
||||
struct RunningAppStateInner {
|
||||
|
@ -307,6 +313,7 @@ impl RunningAppState {
|
|||
servo: Servo,
|
||||
callbacks: Rc<ServoWindowCallbacks>,
|
||||
servoshell_preferences: ServoShellPreferences,
|
||||
webdriver_receiver: Option<Receiver<WebDriverCommandMsg>>,
|
||||
) -> Rc<Self> {
|
||||
let initial_url = initial_url.and_then(|string| Url::parse(&string).ok());
|
||||
let initial_url = initial_url
|
||||
|
@ -324,6 +331,8 @@ impl RunningAppState {
|
|||
servo,
|
||||
callbacks,
|
||||
servoshell_preferences,
|
||||
webdriver_receiver,
|
||||
webdriver_senders: RefCell::default(),
|
||||
inner: RefCell::new(RunningAppStateInner {
|
||||
need_present: false,
|
||||
context_menu_sender: None,
|
||||
|
@ -484,6 +493,35 @@ impl RunningAppState {
|
|||
self.perform_updates();
|
||||
}
|
||||
|
||||
/// WebDriver message handling methods
|
||||
pub(crate) fn webdriver_receiver(&self) -> Option<&Receiver<WebDriverCommandMsg>> {
|
||||
self.webdriver_receiver.as_ref()
|
||||
}
|
||||
|
||||
pub fn handle_webdriver_messages(self: &Rc<Self>) {
|
||||
if let Some(webdriver_receiver) = &self.webdriver_receiver {
|
||||
while let Ok(msg) = webdriver_receiver.try_recv() {
|
||||
match msg {
|
||||
WebDriverCommandMsg::LoadUrl(webview_id, url, load_status_sender) => {
|
||||
info!(
|
||||
"(Not Implemented) Loading URL in webview {}: {}",
|
||||
webview_id, url
|
||||
);
|
||||
},
|
||||
WebDriverCommandMsg::NewWebView(response_sender, load_status_sender) => {
|
||||
info!("(Not Implemented) Creating new webview");
|
||||
},
|
||||
WebDriverCommandMsg::FocusWebView(webview_id, response_sender) => {
|
||||
info!("(Not Implemented) Focusing webview {}", webview_id);
|
||||
},
|
||||
_ => {
|
||||
info!("(Not Implemented) Received WebDriver command: {:?}", msg);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Touch event: press down
|
||||
pub fn touch_down(&self, x: f32, y: f32, pointer_id: i32) {
|
||||
self.active_webview()
|
||||
|
|
|
@ -345,6 +345,8 @@ extern "C" fn on_surface_created_cb(xcomponent: *mut OH_NativeXComponent, window
|
|||
while let Ok(action) = rx.recv() {
|
||||
trace!("Wakeup message received!");
|
||||
action.do_action(&servo);
|
||||
// Also handle any pending WebDriver messages
|
||||
servo.handle_webdriver_messages();
|
||||
}
|
||||
|
||||
info!("Sender disconnected - Terminating main surface thread");
|
||||
|
|
|
@ -8,6 +8,8 @@ use std::path::PathBuf;
|
|||
use std::ptr::NonNull;
|
||||
use std::rc::Rc;
|
||||
|
||||
use constellation_traits::EmbedderToConstellationMessage;
|
||||
use crossbeam_channel::unbounded;
|
||||
use dpi::PhysicalSize;
|
||||
use log::{debug, info, warn};
|
||||
use ohos_abilitykit_sys::runtime::application_context;
|
||||
|
@ -16,6 +18,7 @@ use raw_window_handle::{
|
|||
DisplayHandle, OhosDisplayHandle, OhosNdkWindowHandle, RawDisplayHandle, RawWindowHandle,
|
||||
WindowHandle,
|
||||
};
|
||||
use servo::ipc_channel::ipc;
|
||||
use servo::{self, EventLoopWaker, ServoBuilder, WindowRenderingContext, resources};
|
||||
use xcomponent_sys::OH_NativeXComponent;
|
||||
|
||||
|
@ -191,9 +194,33 @@ pub fn init(
|
|||
let servo = ServoBuilder::new(rendering_context.clone())
|
||||
.opts(opts)
|
||||
.preferences(preferences)
|
||||
.event_loop_waker(waker)
|
||||
.event_loop_waker(waker.clone())
|
||||
.build();
|
||||
|
||||
// Initialize WebDriver server if port is specified
|
||||
let webdriver_receiver = servoshell_preferences.webdriver_port.map(|port| {
|
||||
let (embedder_sender, embedder_receiver) = unbounded();
|
||||
let (webdriver_response_sender, webdriver_response_receiver) = ipc::channel().unwrap();
|
||||
|
||||
// Set the WebDriver response sender to constellation
|
||||
servo
|
||||
.constellation_sender()
|
||||
.send(EmbedderToConstellationMessage::SetWebDriverResponseSender(
|
||||
webdriver_response_sender,
|
||||
))
|
||||
.expect("Failed to set WebDriver response sender in constellation when init Servo");
|
||||
|
||||
webdriver_server::start_server(
|
||||
port,
|
||||
embedder_sender,
|
||||
waker.clone(),
|
||||
webdriver_response_receiver,
|
||||
);
|
||||
|
||||
info!("WebDriver server started on port {}", port);
|
||||
embedder_receiver
|
||||
});
|
||||
|
||||
let app_state = RunningAppState::new(
|
||||
Some(options.url),
|
||||
native_values.display_density as f32,
|
||||
|
@ -201,6 +228,7 @@ pub fn init(
|
|||
servo,
|
||||
window_callbacks,
|
||||
servoshell_preferences,
|
||||
webdriver_receiver,
|
||||
);
|
||||
|
||||
Ok(app_state)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue