From 55b1a9be2fd9b219b019022d98b0276de86f0a79 Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Wed, 26 Mar 2025 13:49:40 +0800 Subject: [PATCH] Process Key Value Pairs into ViewportDescription Signed-off-by: Shubham Gupta --- components/script/dom/htmlmetaelement.rs | 14 ++++++-- components/shared/compositing/lib.rs | 1 + .../compositing/viewport_description.rs | 36 +++++++++++++++++++ 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/components/script/dom/htmlmetaelement.rs b/components/script/dom/htmlmetaelement.rs index d1bfffa6609..8453258308d 100644 --- a/components/script/dom/htmlmetaelement.rs +++ b/components/script/dom/htmlmetaelement.rs @@ -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 { } /// - fn parse_viewport(&self) { - let _element = self.upcast::(); + 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::(); + if let Some(content) = element.get_attribute(&ns!(), &local_name!("content")) { + let _viewport = ViewportDescription::from_str(&content.value()).unwrap_or_default(); + } } /// diff --git a/components/shared/compositing/lib.rs b/components/shared/compositing/lib.rs index 67ff0046885..ee4e230fcf0 100644 --- a/components/shared/compositing/lib.rs +++ b/components/shared/compositing/lib.rs @@ -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}; diff --git a/components/shared/compositing/viewport_description.rs b/components/shared/compositing/viewport_description.rs index 2418921e2c3..64f374d7b7b 100644 --- a/components/shared/compositing/viewport_description.rs +++ b/components/shared/compositing/viewport_description.rs @@ -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; /// pub const DEFAULT_ZOOM: f32 = 1.0; +/// +const SEPARATORS: [char; 2] = [',', ';']; // Comma (0x2c) and Semicolon (0x3b) + /// A set of viewport descriptors: /// /// @@ -137,3 +141,35 @@ impl ViewportDescription { zoom.clamp(self.minimum_scale.get(), self.maximum_scale.get()) } } + +/// +/// +/// 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 { + 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::>(); + + Ok(Self::process_viewport_key_value_pair(parsed_values)) + } +}