libservo: Combine LoadStart, HeadParsed, and LoadComplete` messages (#35260)

These will be a single method in the upcoming `WebView` delegate, so it
makes sense to also combine the internal message to match this. In
addition, since `LoadStatus` is now exposed to the API if there is ever
the need to add more statuses or to move to an event-based version, the
API is already set up for this.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
Martin Robinson 2025-02-03 23:31:17 +01:00 committed by GitHub
parent b8ab820e3c
commit fdfaf7b15c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 97 additions and 92 deletions

View file

@ -24,14 +24,14 @@ use servo::servo_geometry::DeviceIndependentPixel;
use servo::servo_url::ServoUrl;
use servo::webrender_api::units::DevicePixel;
use servo::webrender_traits::SurfmanRenderingContext;
use servo::Servo;
use servo::{LoadStatus, Servo};
use winit::event::{ElementState, MouseButton, WindowEvent};
use winit::event_loop::ActiveEventLoop;
use winit::window::Window;
use super::egui_glue::EguiGlow;
use super::geometry::winit_position_to_euclid_point;
use super::webview::{LoadStatus, WebView, WebViewManager};
use super::webview::{WebView, WebViewManager};
pub struct Minibrowser {
pub context: EguiGlow,
@ -108,7 +108,7 @@ impl Minibrowser {
last_mouse_position: None,
location: RefCell::new(initial_url.to_string()),
location_dirty: false.into(),
load_status: LoadStatus::LoadComplete,
load_status: LoadStatus::Complete,
status_text: None,
}
}
@ -300,12 +300,12 @@ impl Minibrowser {
}
match self.load_status {
LoadStatus::LoadStart | LoadStatus::HeadParsed => {
LoadStatus::Started | LoadStatus::HeadParsed => {
if ui.add(Minibrowser::toolbar_button("X")).clicked() {
warn!("Do not support stop yet.");
}
},
LoadStatus::LoadComplete => {
LoadStatus::Complete => {
if ui.add(Minibrowser::toolbar_button("")).clicked() {
event_queue.borrow_mut().push(MinibrowserEvent::Reload);
}

View file

@ -148,11 +148,9 @@ mod from_servo {
Self::SetClipboardContents(..) => target!("SetClipboardContents"),
Self::SetCursor(..) => target!("SetCursor"),
Self::NewFavicon(..) => target!("NewFavicon"),
Self::HeadParsed(..) => target!("HeadParsed"),
Self::HistoryChanged(..) => target!("HistoryChanged"),
Self::SetFullscreenState(..) => target!("SetFullscreenState"),
Self::LoadStart(..) => target!("LoadStart"),
Self::LoadComplete(..) => target!("LoadComplete"),
Self::NotifyLoadStatusChanged(..) => target!("NotifyLoadStatusChanged"),
Self::Panic(..) => target!("Panic"),
Self::GetSelectedBluetoothDevice(..) => target!("GetSelectedBluetoothDevice"),
Self::SelectFiles(..) => target!("SelectFiles"),

View file

@ -23,8 +23,9 @@ use servo::webrender_api::ScrollLocation;
use servo::{
CompositorEventVariant, ContextMenuResult, DualRumbleEffectParams, EmbedderMsg, FilterPattern,
GamepadEvent, GamepadHapticEffectType, GamepadIndex, GamepadInputBounds,
GamepadSupportedHapticEffects, GamepadUpdateType, PermissionPrompt, PermissionRequest,
PromptCredentialsInput, PromptDefinition, PromptOrigin, PromptResult, Servo, TouchEventType,
GamepadSupportedHapticEffects, GamepadUpdateType, LoadStatus, PermissionPrompt,
PermissionRequest, PromptCredentialsInput, PromptDefinition, PromptOrigin, PromptResult, Servo,
TouchEventType,
};
use tinyfiledialogs::{self, MessageBoxIcon, OkCancel, YesNo};
@ -53,13 +54,6 @@ pub struct WebViewManager {
shutdown_requested: bool,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum LoadStatus {
HeadParsed,
LoadStart,
LoadComplete,
}
// The state of each Tab/WebView
pub struct WebView {
pub rect: DeviceRect,
@ -77,7 +71,7 @@ impl WebView {
title: None,
url: None,
focused: false,
load_status: LoadStatus::LoadComplete,
load_status: LoadStatus::Complete,
servo_webview,
}
}
@ -171,7 +165,7 @@ impl WebViewManager {
pub fn load_status(&self) -> LoadStatus {
match self.focused_webview() {
Some(webview) => webview.load_status,
None => LoadStatus::LoadComplete,
None => LoadStatus::Complete,
}
}
@ -423,7 +417,7 @@ impl WebViewManager {
opts: &Opts,
messages: Vec<EmbedderMsg>,
) -> ServoEventResponse {
let mut need_present = self.load_status() != LoadStatus::LoadComplete;
let mut need_present = self.load_status() != LoadStatus::Complete;
let mut need_update = false;
for message in messages {
trace_embedder_msg!(message, "{message:?}");
@ -638,9 +632,9 @@ impl WebViewManager {
EmbedderMsg::NewFavicon(_, _url) => {
// FIXME: show favicons in the UI somehow
},
EmbedderMsg::HeadParsed(webview_id) => {
EmbedderMsg::NotifyLoadStatusChanged(webview_id, load_status) => {
if let Some(webview) = self.get_mut(webview_id) {
webview.load_status = LoadStatus::HeadParsed;
webview.load_status = load_status;
need_update = true;
};
},
@ -653,18 +647,6 @@ impl WebViewManager {
EmbedderMsg::SetFullscreenState(_, state) => {
self.window.set_fullscreen(state);
},
EmbedderMsg::LoadStart(webview_id) => {
if let Some(webview) = self.get_mut(webview_id) {
webview.load_status = LoadStatus::LoadStart;
need_update = true;
};
},
EmbedderMsg::LoadComplete(webview_id) => {
if let Some(webview) = self.get_mut(webview_id) {
webview.load_status = LoadStatus::LoadComplete;
need_update = true;
};
},
EmbedderMsg::WebResourceRequested(_, _web_resource_request, _response_sender) => {},
EmbedderMsg::Shutdown => {
self.shutdown_requested = true;

View file

@ -15,7 +15,7 @@ use jni::objects::{GlobalRef, JClass, JObject, JString, JValue, JValueOwned};
use jni::sys::{jboolean, jfloat, jint, jobject};
use jni::{JNIEnv, JavaVM};
use log::{debug, error, info, warn};
use servo::MediaSessionActionType;
use servo::{LoadStatus, MediaSessionActionType};
use simpleservo::{
DeviceIntRect, EventLoopWaker, InitOptions, InputMethodType, MediaSessionPlaybackState,
PromptResult, SERVO,
@ -496,18 +496,20 @@ impl HostTrait for HostCallbacks {
Some(default)
}
fn on_load_started(&self) {
debug!("on_load_started");
fn notify_load_status_changed(&self, load_status: LoadStatus) {
debug!("notify_load_status_changed: {load_status:?}");
let mut env = self.jvm.get_env().unwrap();
env.call_method(self.callbacks.as_obj(), "onLoadStarted", "()V", &[])
.unwrap();
}
fn on_load_ended(&self) {
debug!("on_load_ended");
let mut env = self.jvm.get_env().unwrap();
env.call_method(self.callbacks.as_obj(), "onLoadEnded", "()V", &[])
.unwrap();
match load_status {
LoadStatus::Started => {
env.call_method(self.callbacks.as_obj(), "onLoadStarted", "()V", &[])
.unwrap();
},
LoadStatus::HeadParsed => {},
LoadStatus::Complete => {
env.call_method(self.callbacks.as_obj(), "onLoadEnded", "()V", &[])
.unwrap();
},
};
}
fn on_shutdown_complete(&self) {

View file

@ -3,7 +3,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use servo::webrender_api::units::DeviceIntRect;
use servo::{InputMethodType, MediaSessionPlaybackState, PromptResult};
use servo::{InputMethodType, LoadStatus, MediaSessionPlaybackState, PromptResult};
/// Callbacks. Implemented by embedder. Called by Servo.
pub trait HostTrait {
@ -17,16 +17,16 @@ pub trait HostTrait {
fn prompt_input(&self, msg: String, default: String, trusted: bool) -> Option<String>;
/// Show context menu
fn show_context_menu(&self, title: Option<String>, items: Vec<String>);
/// Page starts loading.
/// "Reload button" should be disabled.
/// "Stop button" should be enabled.
/// Throbber starts spinning.
fn on_load_started(&self);
/// Page has loaded.
/// "Reload button" should be enabled.
/// "Stop button" should be disabled.
/// Throbber stops spinning.
fn on_load_ended(&self);
/// Notify that the load status of the page has changed.
/// Started:
/// - "Reload button" should be disabled.
/// - "Stop button" should be enabled.
/// - Throbber starts spinning.
/// Complete:
/// - "Reload button" should be enabled.
/// - "Stop button" should be disabled.
/// - Throbber stops spinning.
fn notify_load_status_changed(&self, load_status: LoadStatus);
/// Page title has changed.
fn on_title_changed(&self, title: Option<String>);
/// Allow Navigation.

View file

@ -21,7 +21,7 @@ use napi_ohos::{Env, JsObject, JsString, NapiRaw};
use ohos_ime::{AttachOptions, Ime, ImeProxy, RawTextEditorProxy};
use ohos_ime_sys::types::InputMethod_EnterKeyType;
use servo::style::Zero;
use servo::{InputMethodType, MediaSessionPlaybackState, PromptResult};
use servo::{InputMethodType, LoadStatus, MediaSessionPlaybackState, PromptResult};
use simpleservo::EventLoopWaker;
use xcomponent_sys::{
OH_NativeXComponent, OH_NativeXComponent_Callback, OH_NativeXComponent_GetKeyEvent,
@ -733,19 +733,17 @@ impl HostTrait for HostCallbacks {
warn!("show_context_menu not implemented")
}
fn on_load_started(&self) {
warn!("on_load_started not implemented")
}
fn on_load_ended(&self) {
// Note: It seems that we don't necessarily get 1 `on_load_ended` for each
// each time `on_loaded_started` is called. Presumably this requires some API changes,
fn notify_load_status_changed(&self, load_status: LoadStatus) {
// Note: It seems that we don't necessarily get 1 `LoadStatus::Complete` for each
// each time `LoadStatus::Started` is called. Presumably this requires some API changes,
// e.g. including webview id, perhaps URL and some additional investigation effort.
// For now we just add a trace event here, so that we can see in the trace if we
// successfully loaded **a** page.
#[cfg(feature = "tracing-hitrace")]
let _scope = hitrace::ScopedTrace::start_trace(&c"PageLoadEndedPrompt");
self.prompt_alert("Page finished loading!".to_string(), true);
if load_status == LoadStatus::Complete {
#[cfg(feature = "tracing-hitrace")]
let _scope = hitrace::ScopedTrace::start_trace(&c"PageLoadEndedPrompt");
self.prompt_alert("Page finished loading!".to_string(), true);
}
}
fn on_title_changed(&self, title: Option<String>) {

View file

@ -479,11 +479,10 @@ impl ServoGlue {
.host_callbacks
.on_url_changed(entries[current].clone().to_string());
},
EmbedderMsg::LoadStart(_) => {
self.callbacks.host_callbacks.on_load_started();
},
EmbedderMsg::LoadComplete(_) => {
self.callbacks.host_callbacks.on_load_ended();
EmbedderMsg::NotifyLoadStatusChanged(_, load_status) => {
self.callbacks
.host_callbacks
.notify_load_status_changed(load_status);
},
EmbedderMsg::GetSelectedBluetoothDevice(_, _, sender) => {
let _ = sender.send(None);
@ -653,7 +652,6 @@ impl ServoGlue {
EmbedderMsg::MoveTo(..) |
EmbedderMsg::SetCursor(..) |
EmbedderMsg::NewFavicon(..) |
EmbedderMsg::HeadParsed(..) |
EmbedderMsg::SetFullscreenState(..) |
EmbedderMsg::ReportProfile(..) |
EmbedderMsg::EventDelivered(..) |