diff --git a/components/constellation/tracing.rs b/components/constellation/tracing.rs
index 562c499cef4..cbedd2da872 100644
--- a/components/constellation/tracing.rs
+++ b/components/constellation/tracing.rs
@@ -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")
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index 83a98351ddc..b2c7ddd68a6 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -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);
},
diff --git a/components/script/dom/htmlbodyelement.rs b/components/script/dom/htmlbodyelement.rs
index 228e1490200..b531e27f0a1 100644
--- a/components/script/dom/htmlbodyelement.rs
+++ b/components/script/dom/htmlbodyelement.rs
@@ -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,
+ ));
}
}
diff --git a/components/shared/embedder/lib.rs b/components/shared/embedder/lib.rs
index 5d425983800..92e1ba9e6e6 100644
--- a/components/shared/embedder/lib.rs
+++ b/components/shared/embedder/lib.rs
@@ -193,16 +193,12 @@ pub enum EmbedderMsg {
SetCursor(WebViewId, Cursor),
/// A favicon was detected
NewFavicon(WebViewId, ServoUrl),
- /// `
` tag finished parsing
- HeadParsed(WebViewId),
/// The history state has changed.
HistoryChanged(WebViewId, Vec, 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,
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 `` 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
+ Complete,
+}
diff --git a/ports/servoshell/desktop/minibrowser.rs b/ports/servoshell/desktop/minibrowser.rs
index aaab62930fb..d30dacde8fb 100644
--- a/ports/servoshell/desktop/minibrowser.rs
+++ b/ports/servoshell/desktop/minibrowser.rs
@@ -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);
}
diff --git a/ports/servoshell/desktop/tracing.rs b/ports/servoshell/desktop/tracing.rs
index 243fc02f05a..eedee21ca65 100644
--- a/ports/servoshell/desktop/tracing.rs
+++ b/ports/servoshell/desktop/tracing.rs
@@ -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"),
diff --git a/ports/servoshell/desktop/webview.rs b/ports/servoshell/desktop/webview.rs
index abad072daa8..ce6a646d95f 100644
--- a/ports/servoshell/desktop/webview.rs
+++ b/ports/servoshell/desktop/webview.rs
@@ -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,
) -> 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;
diff --git a/ports/servoshell/egl/android.rs b/ports/servoshell/egl/android.rs
index 503494d7c03..7039c387c0f 100644
--- a/ports/servoshell/egl/android.rs
+++ b/ports/servoshell/egl/android.rs
@@ -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) {
diff --git a/ports/servoshell/egl/host_trait.rs b/ports/servoshell/egl/host_trait.rs
index bc18a48572b..7d6ee078bea 100644
--- a/ports/servoshell/egl/host_trait.rs
+++ b/ports/servoshell/egl/host_trait.rs
@@ -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;
/// Show context menu
fn show_context_menu(&self, title: Option, items: Vec);
- /// 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);
/// Allow Navigation.
diff --git a/ports/servoshell/egl/ohos.rs b/ports/servoshell/egl/ohos.rs
index 908a4c75240..de32080d9bd 100644
--- a/ports/servoshell/egl/ohos.rs
+++ b/ports/servoshell/egl/ohos.rs
@@ -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) {
diff --git a/ports/servoshell/egl/servo_glue.rs b/ports/servoshell/egl/servo_glue.rs
index 5311f2a197c..2d9f9db1b41 100644
--- a/ports/servoshell/egl/servo_glue.rs
+++ b/ports/servoshell/egl/servo_glue.rs
@@ -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(..) |