Files
ELY-Browser/crates/ely_servo_host/src/host.rs
T

341 lines
8.0 KiB
Rust

use ely_domain::{
ProfileId, SiteOrigin, SitePermissionDecision, SitePermissionFeature, TabId, UrlText, WebViewId,
};
use crate::ServoHostError;
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum WebViewState {
Created,
Loading,
Complete,
Sleeping,
Crashed,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RenderedFrameSummary {
width: u32,
height: u32,
opaque_pixel_count: u64,
non_white_pixel_count: u64,
content_pixel_count: u64,
sample_hash: u64,
}
impl RenderedFrameSummary {
#[must_use]
pub fn from_rgba_bytes(width: u32, height: u32, rgba_bytes: &[u8]) -> Self {
let mut opaque_pixel_count = 0;
let mut non_white_pixel_count = 0;
let mut content_pixel_count = 0;
let mut sample_hash = 0xcbf29ce484222325_u64;
for (index, pixel) in rgba_bytes.chunks_exact(4).enumerate() {
let [red, green, blue, alpha] = [pixel[0], pixel[1], pixel[2], pixel[3]];
if alpha > 0 {
opaque_pixel_count += 1;
}
if alpha > 0 && (red < 245 || green < 245 || blue < 245) {
non_white_pixel_count += 1;
}
if alpha > 0 && (red < 220 || green < 220 || blue < 220) {
content_pixel_count += 1;
}
if index % 97 == 0 {
for byte in pixel {
sample_hash ^= u64::from(*byte);
sample_hash = sample_hash.wrapping_mul(0x100000001b3);
}
}
}
Self {
width,
height,
opaque_pixel_count,
non_white_pixel_count,
content_pixel_count,
sample_hash,
}
}
#[must_use]
pub fn width(&self) -> u32 {
self.width
}
#[must_use]
pub fn height(&self) -> u32 {
self.height
}
#[must_use]
pub fn opaque_pixel_count(&self) -> u64 {
self.opaque_pixel_count
}
#[must_use]
pub fn non_white_pixel_count(&self) -> u64 {
self.non_white_pixel_count
}
#[must_use]
pub fn content_pixel_count(&self) -> u64 {
self.content_pixel_count
}
#[must_use]
pub fn sample_hash(&self) -> u64 {
self.sample_hash
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RenderedFrame {
width: u32,
height: u32,
rgba_bytes: Vec<u8>,
summary: RenderedFrameSummary,
}
impl RenderedFrame {
#[must_use]
pub fn from_rgba_bytes(width: u32, height: u32, rgba_bytes: Vec<u8>) -> Self {
let summary = RenderedFrameSummary::from_rgba_bytes(width, height, &rgba_bytes);
Self { width, height, rgba_bytes, summary }
}
#[must_use]
pub fn width(&self) -> u32 {
self.width
}
#[must_use]
pub fn height(&self) -> u32 {
self.height
}
#[must_use]
pub fn rgba_bytes(&self) -> &[u8] {
&self.rgba_bytes
}
#[must_use]
pub fn summary(&self) -> &RenderedFrameSummary {
&self.summary
}
#[must_use]
pub fn opaque_pixel_count(&self) -> u64 {
self.summary.opaque_pixel_count()
}
#[must_use]
pub fn non_white_pixel_count(&self) -> u64 {
self.summary.non_white_pixel_count()
}
#[must_use]
pub fn content_pixel_count(&self) -> u64 {
self.summary.content_pixel_count()
}
#[must_use]
pub fn sample_hash(&self) -> u64 {
self.summary.sample_hash()
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct WebViewSnapshot {
webview_id: WebViewId,
tab_id: TabId,
profile_id: ProfileId,
state: WebViewState,
url: Option<String>,
title: Option<String>,
has_pending_frame: bool,
}
impl WebViewSnapshot {
#[must_use]
pub fn new(
webview_id: WebViewId,
tab_id: TabId,
profile_id: ProfileId,
state: WebViewState,
url: Option<String>,
title: Option<String>,
has_pending_frame: bool,
) -> Self {
Self { webview_id, tab_id, profile_id, state, url, title, has_pending_frame }
}
#[must_use]
pub fn webview_id(&self) -> &WebViewId {
&self.webview_id
}
#[must_use]
pub fn tab_id(&self) -> &TabId {
&self.tab_id
}
#[must_use]
pub fn profile_id(&self) -> &ProfileId {
&self.profile_id
}
#[must_use]
pub fn state(&self) -> &WebViewState {
&self.state
}
#[must_use]
pub fn url(&self) -> Option<&str> {
self.url.as_deref()
}
#[must_use]
pub fn title(&self) -> Option<&str> {
self.title.as_deref()
}
#[must_use]
pub fn has_pending_frame(&self) -> bool {
self.has_pending_frame
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct NavigationRequest {
pub webview_id: WebViewId,
pub tab_id: TabId,
pub url: UrlText,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ScrollRequest {
pub webview_id: WebViewId,
pub delta_x: i32,
pub delta_y: i32,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ResizeRequest {
pub webview_id: WebViewId,
pub width: u32,
pub height: u32,
}
#[derive(Clone, Debug, PartialEq)]
pub struct PageZoomRequest {
pub webview_id: WebViewId,
pub zoom_factor: f32,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct MouseClickRequest {
pub webview_id: WebViewId,
pub x: u32,
pub y: u32,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct MouseDragRequest {
pub webview_id: WebViewId,
pub from_x: u32,
pub from_y: u32,
pub to_x: u32,
pub to_y: u32,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct TouchTapRequest {
pub webview_id: WebViewId,
pub x: u32,
pub y: u32,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct KeyboardTextRequest {
pub webview_id: WebViewId,
pub text: String,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ScreenshotRequest {
pub webview_id: WebViewId,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct PermissionRequest {
pub webview_id: WebViewId,
pub profile_id: ProfileId,
pub origin: SiteOrigin,
pub feature: SitePermissionFeature,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum PermissionDecision {
AllowOnce,
AllowAlways,
DenyAlways,
}
impl From<SitePermissionDecision> for PermissionDecision {
fn from(decision: SitePermissionDecision) -> Self {
match decision {
SitePermissionDecision::AllowOnce => Self::AllowOnce,
SitePermissionDecision::AllowAlways => Self::AllowAlways,
SitePermissionDecision::DenyAlways => Self::DenyAlways,
}
}
}
pub trait ServoHost {
fn create_webview(
&mut self,
tab_id: TabId,
profile_id: ProfileId,
) -> Result<WebViewId, ServoHostError>;
fn navigate(&mut self, request: NavigationRequest) -> Result<(), ServoHostError>;
fn scroll(&mut self, request: ScrollRequest) -> Result<(), ServoHostError>;
fn resize(&mut self, request: ResizeRequest) -> Result<(), ServoHostError>;
fn set_page_zoom(&mut self, request: PageZoomRequest) -> Result<(), ServoHostError>;
fn click(&mut self, request: MouseClickRequest) -> Result<(), ServoHostError>;
fn drag(&mut self, request: MouseDragRequest) -> Result<(), ServoHostError>;
fn touch_tap(&mut self, request: TouchTapRequest) -> Result<(), ServoHostError>;
fn type_text(&mut self, request: KeyboardTextRequest) -> Result<(), ServoHostError>;
fn capture_screenshot(
&mut self,
request: ScreenshotRequest,
) -> Result<RenderedFrame, ServoHostError>;
fn set_permission(
&mut self,
request: PermissionRequest,
decision: PermissionDecision,
) -> Result<(), ServoHostError>;
fn state(&self, webview_id: &WebViewId) -> Result<WebViewState, ServoHostError>;
fn snapshot(&self, webview_id: &WebViewId) -> Result<WebViewSnapshot, ServoHostError>;
fn tick(&mut self) -> bool;
fn paint(&mut self, webview_id: &WebViewId) -> Result<(), ServoHostError>;
fn last_rendered_frame(&self) -> Result<RenderedFrame, ServoHostError>;
}