mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
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:
parent
b8ab820e3c
commit
fdfaf7b15c
11 changed files with 97 additions and 92 deletions
|
@ -121,6 +121,8 @@ mod from_compositor {
|
|||
}
|
||||
|
||||
mod from_script {
|
||||
use embedder_traits::LoadStatus;
|
||||
|
||||
use super::LogTarget;
|
||||
|
||||
macro_rules! target {
|
||||
|
@ -222,11 +224,17 @@ mod from_script {
|
|||
Self::SetClipboardContents(..) => target_variant!("SetClipboardContents"),
|
||||
Self::SetCursor(..) => target_variant!("SetCursor"),
|
||||
Self::NewFavicon(..) => target_variant!("NewFavicon"),
|
||||
Self::HeadParsed(..) => target_variant!("HeadParsed"),
|
||||
Self::HistoryChanged(..) => target_variant!("HistoryChanged"),
|
||||
Self::SetFullscreenState(..) => target_variant!("SetFullscreenState"),
|
||||
Self::LoadStart(..) => target_variant!("LoadStart"),
|
||||
Self::LoadComplete(..) => target_variant!("LoadComplete"),
|
||||
Self::NotifyLoadStatusChanged(_, LoadStatus::Started) => {
|
||||
target_variant!("NotifyLoadStatusChanged(LoadStatus::Started)")
|
||||
},
|
||||
Self::NotifyLoadStatusChanged(_, LoadStatus::HeadParsed) => {
|
||||
target_variant!("NotifyLoadStatusChanged(LoadStatus::HeadParsed)")
|
||||
},
|
||||
Self::NotifyLoadStatusChanged(_, LoadStatus::Complete) => {
|
||||
target_variant!("NotifyLoadStatusChanged(LoadStatus::Complete")
|
||||
},
|
||||
Self::Panic(..) => target_variant!("Panic"),
|
||||
Self::GetSelectedBluetoothDevice(..) => {
|
||||
target_variant!("GetSelectedBluetoothDevice")
|
||||
|
|
|
@ -24,8 +24,8 @@ use cssparser::match_ignore_ascii_case;
|
|||
use devtools_traits::ScriptToDevtoolsControlMsg;
|
||||
use dom_struct::dom_struct;
|
||||
use embedder_traits::{
|
||||
ClipboardEventType, EmbedderMsg, MouseButton, MouseEventType, TouchEventType, TouchId,
|
||||
WheelDelta,
|
||||
ClipboardEventType, EmbedderMsg, LoadStatus, MouseButton, MouseEventType, TouchEventType,
|
||||
TouchId, WheelDelta,
|
||||
};
|
||||
use encoding_rs::{Encoding, UTF_8};
|
||||
use euclid::default::{Point2D, Rect, Size2D};
|
||||
|
@ -1032,13 +1032,19 @@ impl Document {
|
|||
match state {
|
||||
DocumentReadyState::Loading => {
|
||||
if self.window().is_top_level() {
|
||||
self.send_to_embedder(EmbedderMsg::LoadStart(self.webview_id()));
|
||||
self.send_to_embedder(EmbedderMsg::NotifyLoadStatusChanged(
|
||||
self.webview_id(),
|
||||
LoadStatus::Started,
|
||||
));
|
||||
self.send_to_embedder(EmbedderMsg::Status(self.webview_id(), None));
|
||||
}
|
||||
},
|
||||
DocumentReadyState::Complete => {
|
||||
if self.window().is_top_level() {
|
||||
self.send_to_embedder(EmbedderMsg::LoadComplete(self.webview_id()));
|
||||
self.send_to_embedder(EmbedderMsg::NotifyLoadStatusChanged(
|
||||
self.webview_id(),
|
||||
LoadStatus::Complete,
|
||||
));
|
||||
}
|
||||
update_with_current_instant(&self.dom_complete);
|
||||
},
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom_struct::dom_struct;
|
||||
use embedder_traits::EmbedderMsg;
|
||||
use embedder_traits::{EmbedderMsg, LoadStatus};
|
||||
use html5ever::{local_name, namespace_url, ns, LocalName, Prefix};
|
||||
use js::rust::HandleObject;
|
||||
use servo_url::ServoUrl;
|
||||
|
@ -153,7 +153,10 @@ impl VirtualMethods for HTMLBodyElement {
|
|||
let window = self.owner_window();
|
||||
window.prevent_layout_until_load_event();
|
||||
if window.is_top_level() {
|
||||
window.send_to_embedder(EmbedderMsg::HeadParsed(window.webview_id()));
|
||||
window.send_to_embedder(EmbedderMsg::NotifyLoadStatusChanged(
|
||||
window.webview_id(),
|
||||
LoadStatus::HeadParsed,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -193,16 +193,12 @@ pub enum EmbedderMsg {
|
|||
SetCursor(WebViewId, Cursor),
|
||||
/// A favicon was detected
|
||||
NewFavicon(WebViewId, ServoUrl),
|
||||
/// `<head>` tag finished parsing
|
||||
HeadParsed(WebViewId),
|
||||
/// The history state has changed.
|
||||
HistoryChanged(WebViewId, Vec<ServoUrl>, usize),
|
||||
/// Enter or exit fullscreen
|
||||
SetFullscreenState(WebViewId, bool),
|
||||
/// The load of a page has begun
|
||||
LoadStart(WebViewId),
|
||||
/// The load of a page has completed
|
||||
LoadComplete(WebViewId),
|
||||
/// The [`LoadStatus`] of the Given `WebView` has changed.
|
||||
NotifyLoadStatusChanged(WebViewId, LoadStatus),
|
||||
WebResourceRequested(
|
||||
Option<WebViewId>,
|
||||
WebResourceRequest,
|
||||
|
@ -286,11 +282,11 @@ impl Debug for EmbedderMsg {
|
|||
EmbedderMsg::SetClipboardContents(..) => write!(f, "SetClipboardContents"),
|
||||
EmbedderMsg::SetCursor(..) => write!(f, "SetCursor"),
|
||||
EmbedderMsg::NewFavicon(..) => write!(f, "NewFavicon"),
|
||||
EmbedderMsg::HeadParsed(..) => write!(f, "HeadParsed"),
|
||||
EmbedderMsg::HistoryChanged(..) => write!(f, "HistoryChanged"),
|
||||
EmbedderMsg::SetFullscreenState(..) => write!(f, "SetFullscreenState"),
|
||||
EmbedderMsg::LoadStart(..) => write!(f, "LoadStart"),
|
||||
EmbedderMsg::LoadComplete(..) => write!(f, "LoadComplete"),
|
||||
EmbedderMsg::NotifyLoadStatusChanged(_, status) => {
|
||||
write!(f, "NotifyLoadStatusChanged({status:?})")
|
||||
},
|
||||
EmbedderMsg::WebResourceRequested(..) => write!(f, "WebResourceRequested"),
|
||||
EmbedderMsg::Panic(..) => write!(f, "Panic"),
|
||||
EmbedderMsg::GetSelectedBluetoothDevice(..) => write!(f, "GetSelectedBluetoothDevice"),
|
||||
|
@ -736,3 +732,17 @@ pub enum MediaSessionActionType {
|
|||
/// The action intent is to move the playback time to a specific time.
|
||||
SeekTo,
|
||||
}
|
||||
|
||||
/// The status of the load in this `WebView`.
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||
pub enum LoadStatus {
|
||||
/// The load has started, but the headers have not yet been parsed.
|
||||
Started,
|
||||
/// The `<head>` tag has been parsed in the currently loading page. At this point the page's
|
||||
/// `HTMLBodyElement` is now available in the DOM.
|
||||
HeadParsed,
|
||||
/// The `Document` and all subresources have loaded. This is equivalent to
|
||||
/// `document.readyState` == `complete`.
|
||||
/// See <https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState>
|
||||
Complete,
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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"),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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>) {
|
||||
|
|
|
@ -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(..) |
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue