mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
libservo: Allow embedders to execute JavaScript scripts via the API (#35720)
This change adds a new `WebView` API `evaluate_javascript()`, which allows embedders to execute JavaScript code and wait for a reply asynchronously. Ongoing script execution is tracked by a libservo `JavaScriptEvaluator` struct, which maps an id to the callback passed to the `evaluate_javascript()` method. The id is used to track the script and its execution through the other parts of Servo. Testing: This changes includes `WebView` unit tests. --------- Signed-off-by: Narfinger <Narfinger@users.noreply.github.com> Signed-off-by: Martin Robinson <mrobinson@igalia.com> Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
91c4c7b998
commit
991be359a3
12 changed files with 391 additions and 18 deletions
|
@ -129,9 +129,10 @@ use embedder_traits::resources::{self, Resource};
|
|||
use embedder_traits::user_content_manager::UserContentManager;
|
||||
use embedder_traits::{
|
||||
AnimationState, CompositorHitTestResult, Cursor, EmbedderMsg, EmbedderProxy,
|
||||
FocusSequenceNumber, ImeEvent, InputEvent, MediaSessionActionType, MediaSessionEvent,
|
||||
MediaSessionPlaybackState, MouseButton, MouseButtonAction, MouseButtonEvent, Theme,
|
||||
ViewportDetails, WebDriverCommandMsg, WebDriverLoadStatus,
|
||||
FocusSequenceNumber, ImeEvent, InputEvent, JSValue, JavaScriptEvaluationError,
|
||||
JavaScriptEvaluationId, MediaSessionActionType, MediaSessionEvent, MediaSessionPlaybackState,
|
||||
MouseButton, MouseButtonAction, MouseButtonEvent, Theme, ViewportDetails, WebDriverCommandMsg,
|
||||
WebDriverLoadStatus,
|
||||
};
|
||||
use euclid::Size2D;
|
||||
use euclid::default::Size2D as UntypedSize2D;
|
||||
|
@ -1477,6 +1478,52 @@ where
|
|||
EmbedderToConstellationMessage::PaintMetric(pipeline_id, paint_metric_event) => {
|
||||
self.handle_paint_metric(pipeline_id, paint_metric_event);
|
||||
},
|
||||
EmbedderToConstellationMessage::EvaluateJavaScript(
|
||||
webview_id,
|
||||
evaluation_id,
|
||||
script,
|
||||
) => {
|
||||
self.handle_evaluate_javascript(webview_id, evaluation_id, script);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
tracing::instrument(skip_all, fields(servo_profiling = true), level = "trace")
|
||||
)]
|
||||
fn handle_evaluate_javascript(
|
||||
&mut self,
|
||||
webview_id: WebViewId,
|
||||
evaluation_id: JavaScriptEvaluationId,
|
||||
script: String,
|
||||
) {
|
||||
let browsing_context_id = BrowsingContextId::from(webview_id);
|
||||
let Some(pipeline) = self
|
||||
.browsing_contexts
|
||||
.get(&browsing_context_id)
|
||||
.and_then(|browsing_context| self.pipelines.get(&browsing_context.pipeline_id))
|
||||
else {
|
||||
self.handle_finish_javascript_evaluation(
|
||||
evaluation_id,
|
||||
Err(JavaScriptEvaluationError::InternalError),
|
||||
);
|
||||
return;
|
||||
};
|
||||
|
||||
if pipeline
|
||||
.event_loop
|
||||
.send(ScriptThreadMessage::EvaluateJavaScript(
|
||||
pipeline.id,
|
||||
evaluation_id,
|
||||
script,
|
||||
))
|
||||
.is_err()
|
||||
{
|
||||
self.handle_finish_javascript_evaluation(
|
||||
evaluation_id,
|
||||
Err(JavaScriptEvaluationError::InternalError),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1817,6 +1864,9 @@ where
|
|||
self.mem_profiler_chan
|
||||
.send(mem::ProfilerMsg::Report(sender));
|
||||
},
|
||||
ScriptToConstellationMessage::FinishJavaScriptEvaluation(evaluation_id, result) => {
|
||||
self.handle_finish_javascript_evaluation(evaluation_id, result)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3178,6 +3228,22 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
tracing::instrument(skip_all, fields(servo_profiling = true), level = "trace")
|
||||
)]
|
||||
fn handle_finish_javascript_evaluation(
|
||||
&mut self,
|
||||
evaluation_id: JavaScriptEvaluationId,
|
||||
result: Result<JSValue, JavaScriptEvaluationError>,
|
||||
) {
|
||||
self.embedder_proxy
|
||||
.send(EmbedderMsg::FinishJavaScriptEvaluation(
|
||||
evaluation_id,
|
||||
result,
|
||||
));
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
tracing::instrument(skip_all, fields(servo_profiling = true), level = "trace")
|
||||
|
@ -4691,6 +4757,7 @@ where
|
|||
NavigationHistoryBehavior::Replace,
|
||||
);
|
||||
},
|
||||
// TODO: This should use the ScriptThreadMessage::EvaluateJavaScript command
|
||||
WebDriverCommandMsg::ScriptCommand(browsing_context_id, cmd) => {
|
||||
let pipeline_id = match self.browsing_contexts.get(&browsing_context_id) {
|
||||
Some(browsing_context) => browsing_context.pipeline_id,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue