Process Key Value Pairs into ViewportDescription

Signed-off-by: Shubham Gupta <shubham13297@gmail.com>
This commit is contained in:
Shubham Gupta 2025-03-26 13:49:40 +08:00
parent 6b63f6f82f
commit 55b1a9be2f
3 changed files with 48 additions and 3 deletions

View file

@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use compositing_traits::viewport_description::ViewportDescription;
use dom_struct::dom_struct;
use html5ever::{LocalName, Prefix, local_name, ns};
use js::rust::HandleObject;
@ -62,7 +63,7 @@ impl HTMLMetaElement {
self.apply_referrer();
}
if name == "viewport" {
self.parse_viewport();
self.parse_and_send_viewport_if_necessary();
}
// https://html.spec.whatwg.org/multipage/#attr-meta-http-equiv
} else if !self.HttpEquiv().is_empty() {
@ -119,8 +120,15 @@ impl HTMLMetaElement {
}
/// <https://drafts.csswg.org/css-viewport/#parsing-algorithm>
fn parse_viewport(&self) {
let _element = self.upcast::<Element>();
fn parse_and_send_viewport_if_necessary(&self) {
// Skip processing if this isn't the top level frame
if !self.owner_window().is_top_level() {
return;
}
let element = self.upcast::<Element>();
if let Some(content) = element.get_attribute(&ns!(), &local_name!("content")) {
let _viewport = ViewportDescription::from_str(&content.value()).unwrap_or_default();
}
}
/// <https://html.spec.whatwg.org/multipage/#attr-meta-http-equiv-content-security-policy>

View file

@ -23,6 +23,7 @@ use webrender_api::DocumentId;
pub mod display_list;
pub mod rendering_context;
pub mod viewport_description;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};

View file

@ -5,6 +5,7 @@
//! This module contains helpers for Viewport
use std::collections::HashMap;
use std::str::FromStr;
use euclid::default::Scale;
use serde::{Deserialize, Serialize};
@ -18,6 +19,9 @@ pub const MAX_ZOOM: f32 = 10.0;
/// <https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_meta_tag#initial-scale>
pub const DEFAULT_ZOOM: f32 = 1.0;
/// <https://drafts.csswg.org/css-viewport/#parsing-algorithm>
const SEPARATORS: [char; 2] = [',', ';']; // Comma (0x2c) and Semicolon (0x3b)
/// A set of viewport descriptors:
///
/// <https://www.w3.org/TR/css-viewport-1/#viewport-meta>
@ -137,3 +141,35 @@ impl ViewportDescription {
zoom.clamp(self.minimum_scale.get(), self.maximum_scale.get())
}
}
/// <https://drafts.csswg.org/css-viewport/#parsing-algorithm>
///
/// This implementation differs from the specified algorithm, but is equivalent because
/// 1. It uses higher-level string operations to process string instead of character-by-character iteration.
/// 2. Uses trim() operation to handle whitespace instead of explicitly handling throughout the parsing process.
impl FromStr for ViewportDescription {
type Err = ViewportDescriptionParseError;
fn from_str(string: &str) -> Result<Self, Self::Err> {
if string.is_empty() {
return Err(ViewportDescriptionParseError::Empty);
}
// Parse key-value pairs from the content string
// 1. Split the content string using SEPARATORS
// 2. Split into key-value pair using "=" and trim whitespaces
// 3. Insert into HashMap
let parsed_values = string
.split(SEPARATORS)
.filter_map(|pair| {
let mut parts = pair.split('=').map(str::trim);
if let (Some(key), Some(value)) = (parts.next(), parts.next()) {
Some((key.to_string(), value.to_string()))
} else {
None
}
})
.collect::<HashMap<String, String>>();
Ok(Self::process_viewport_key_value_pair(parsed_values))
}
}