diff --git a/core/src/avm2/globals/flash/system/Security.as b/core/src/avm2/globals/flash/system/Security.as index 257613a38e46..501fc4999455 100644 --- a/core/src/avm2/globals/flash/system/Security.as +++ b/core/src/avm2/globals/flash/system/Security.as @@ -1,6 +1,8 @@ package flash.system { public final class Security { + public static native function get pageDomain():String; public static native function get sandboxType():String; + public static native function allowDomain(... domains):void; public static native function allowInsecureDomain(... domains):void; public static native function loadPolicyFile(url: String):void; diff --git a/core/src/avm2/globals/flash/system/security.rs b/core/src/avm2/globals/flash/system/security.rs index a66521d263a5..38f590b8ce26 100644 --- a/core/src/avm2/globals/flash/system/security.rs +++ b/core/src/avm2/globals/flash/system/security.rs @@ -6,6 +6,32 @@ use crate::avm2::value::Value; use crate::avm2::Error; use crate::avm2_stub_method; use crate::string::AvmString; +use url::Url; + +pub fn get_page_domain<'gc>( + activation: &mut Activation<'_, 'gc>, + _this: Object<'gc>, + _args: &[Value<'gc>], +) -> Result, Error<'gc>> { + if let Some(url) = activation + .context + .page_url + .as_ref() + .and_then(|page_url| Url::parse(page_url).ok()) + { + if !url.origin().is_tuple() { + tracing::warn!("flash.system.Security.pageDomain: Returning null for opaque origin"); + return Ok(Value::Null); + } + + let mut domain = url.origin().ascii_serialization(); + domain.push('/'); // Add trailing slash that is used by Flash, but isn't part of a standard origin. + Ok(AvmString::new_utf8(activation.context.gc_context, domain).into()) + } else { + tracing::warn!("flash.system.Security.pageDomain: No page-url available"); + Ok(Value::Null) + } +} pub fn get_sandbox_type<'gc>( activation: &mut Activation<'_, 'gc>, diff --git a/core/src/context.rs b/core/src/context.rs index e3242c38fb1f..730e2d96647b 100644 --- a/core/src/context.rs +++ b/core/src/context.rs @@ -164,6 +164,8 @@ pub struct UpdateContext<'a, 'gc> { /// The system properties pub system: &'a mut SystemProperties, + pub page_url: &'a mut Option, + /// The current instance ID. Used to generate default `instanceN` names. pub instance_counter: &'a mut i32, @@ -377,6 +379,7 @@ impl<'a, 'gc> UpdateContext<'a, 'gc> { player: self.player.clone(), load_manager: self.load_manager, system: self.system, + page_url: self.page_url, instance_counter: self.instance_counter, avm1_shared_objects: self.avm1_shared_objects, avm2_shared_objects: self.avm2_shared_objects, diff --git a/core/src/player.rs b/core/src/player.rs index 365b69aee088..8ff473737bf5 100644 --- a/core/src/player.rs +++ b/core/src/player.rs @@ -298,6 +298,8 @@ pub struct Player { system: SystemProperties, + page_url: Option, + /// The current instance ID. Used to generate default `instanceN` names. instance_counter: i32, @@ -1927,6 +1929,7 @@ impl Player { player: self.self_reference.clone(), load_manager, system: &mut self.system, + page_url: &mut self.page_url, instance_counter: &mut self.instance_counter, storage: self.storage.deref_mut(), log: self.log.deref_mut(), @@ -2184,6 +2187,7 @@ pub struct PlayerBuilder { player_version: Option, quality: StageQuality, sandbox_type: SandboxType, + page_url: Option, frame_rate: Option, external_interface_providers: Vec>, fs_command_provider: Box, @@ -2229,6 +2233,7 @@ impl PlayerBuilder { player_version: None, quality: StageQuality::High, sandbox_type: SandboxType::LocalTrusted, + page_url: None, frame_rate: None, external_interface_providers: vec![], fs_command_provider: Box::new(NullFsCommandProvider), @@ -2391,6 +2396,12 @@ impl PlayerBuilder { self } + // Configure the embedding page's URL (if applicable) + pub fn with_page_url(mut self, page_url: Option) -> Self { + self.page_url = page_url; + self + } + /// Sets and locks the player's frame rate. If None is provided, this has no effect. pub fn with_frame_rate(mut self, frame_rate: Option) -> Self { self.frame_rate = frame_rate; @@ -2532,6 +2543,7 @@ impl PlayerBuilder { // Misc. state rng: SmallRng::seed_from_u64(get_current_date_time().timestamp_millis() as u64), system: SystemProperties::new(self.sandbox_type), + page_url: self.page_url.clone(), transform_stack: TransformStack::new(), instance_counter: 0, player_version, diff --git a/desktop/src/player.rs b/desktop/src/player.rs index 1244512cf315..a0d5c320083b 100644 --- a/desktop/src/player.rs +++ b/desktop/src/player.rs @@ -156,6 +156,7 @@ impl ActivePlayer { .with_fullscreen(opt.fullscreen) .with_load_behavior(opt.load_behavior) .with_spoofed_url(opt.spoof_url.clone().map(|url| url.to_string())) + .with_page_url(opt.spoof_url.clone().map(|url| url.to_string())) .with_player_version(Some(opt.player_version)) .with_frame_rate(opt.frame_rate); let player = builder.build(); diff --git a/web/src/lib.rs b/web/src/lib.rs index 54aa3664d7ca..5442493cb891 100644 --- a/web/src/lib.rs +++ b/web/src/lib.rs @@ -674,6 +674,7 @@ impl Ruffle { .with_frame_rate(config.frame_rate) // FIXME - should this be configurable? .with_sandbox_type(SandboxType::Remote) + .with_page_url(window.location().href().ok()) .build(); let mut callstack = None;