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))
+ }
+}