From b57897e56a21eeb5b4ffb29ed39ceae410c9b009 Mon Sep 17 00:00:00 2001 From: Adrian Wielgosik Date: Fri, 14 Feb 2025 23:22:43 +0100 Subject: [PATCH] AVM2: Partially support parentAllowsChild when domains match --- .../avm2/globals/flash/display/loader_info.rs | 69 ++++++++++++------- core/src/avm2/object/loaderinfo_object.rs | 1 + 2 files changed, 44 insertions(+), 26 deletions(-) diff --git a/core/src/avm2/globals/flash/display/loader_info.rs b/core/src/avm2/globals/flash/display/loader_info.rs index 86f534e5a815c..06b17e85d65ba 100644 --- a/core/src/avm2/globals/flash/display/loader_info.rs +++ b/core/src/avm2/globals/flash/display/loader_info.rs @@ -10,6 +10,7 @@ use crate::display_object::TDisplayObject; use crate::loader::ContentType; use crate::{avm2_stub_getter, avm2_stub_method}; use swf::{write_swf, Compression}; +use url::Url; const INSUFFICIENT: &str = "Error #2099: The loading object is not sufficiently loaded to provide this information."; @@ -288,22 +289,30 @@ pub fn get_child_allows_parent<'gc>( ) -> Result, Error<'gc>> { let this = this.as_object().unwrap(); - if let Some(loader_stream) = this - .as_loader_info_object() - .and_then(|o| o.as_loader_stream()) - { - match &*loader_stream { - LoaderStream::NotYetLoaded(_, _, _) => { - return Err(Error::AvmError(error(activation, INSUFFICIENT, 2099)?)); - } - LoaderStream::Swf(_root, _) => { - avm2_stub_getter!(activation, "flash.display.LoaderInfo", "childAllowsParent"); - return Ok(false.into()); + let loader_info = this.as_loader_info_object().unwrap(); + let loader_stream = loader_info.as_loader_stream().unwrap(); + match &*loader_stream { + LoaderStream::NotYetLoaded(_, _, _) => { + Err(Error::AvmError(error(activation, INSUFFICIENT, 2099)?)) + } + LoaderStream::Swf(root, _) => { + // TODO: respect allowDomain() and polices. + avm2_stub_getter!(activation, "flash.display.LoaderInfo", "childAllowsParent"); + + let loader = loader_info.loader().expect("Loader should be Some"); + let loader = loader.as_display_object().expect("Loader is a DO"); + let parent_movie = loader.movie(); + + if let Ok(child_url) = Url::parse(root.url()) { + if let Ok(parent_url) = Url::parse(parent_movie.url()) { + if child_url.host() == parent_url.host() { + return Ok(true.into()); + } + } } + Ok(false.into()) } } - - Ok(Value::Undefined) } /// `parentAllowsChild` getter @@ -314,22 +323,30 @@ pub fn get_parent_allows_child<'gc>( ) -> Result, Error<'gc>> { let this = this.as_object().unwrap(); - if let Some(loader_stream) = this - .as_loader_info_object() - .and_then(|o| o.as_loader_stream()) - { - match &*loader_stream { - LoaderStream::NotYetLoaded(_, _, _) => { - return Err(Error::AvmError(error(activation, INSUFFICIENT, 2099)?)); - } - LoaderStream::Swf(_root, _) => { - avm2_stub_getter!(activation, "flash.display.LoaderInfo", "parentAllowsChild"); - return Ok(false.into()); + let loader_info = this.as_loader_info_object().unwrap(); + let loader_stream = loader_info.as_loader_stream().unwrap(); + match &*loader_stream { + LoaderStream::NotYetLoaded(_, _, _) => { + Err(Error::AvmError(error(activation, INSUFFICIENT, 2099)?)) + } + LoaderStream::Swf(root, _) => { + // TODO: respect allowDomain() and polices. + avm2_stub_getter!(activation, "flash.display.LoaderInfo", "parentAllowsChild"); + + let loader = loader_info.loader().expect("Loader should be Some"); + let loader = loader.as_display_object().expect("Loader is a DO"); + let parent_movie = loader.movie(); + + if let Ok(child_url) = Url::parse(root.url()) { + if let Ok(parent_url) = Url::parse(parent_movie.url()) { + if child_url.host() == parent_url.host() { + return Ok(true.into()); + } + } } + Ok(false.into()) } } - - Ok(Value::Undefined) } /// `swfVersion` getter diff --git a/core/src/avm2/object/loaderinfo_object.rs b/core/src/avm2/object/loaderinfo_object.rs index de62f3a07ed37..75e0869feaa3a 100644 --- a/core/src/avm2/object/loaderinfo_object.rs +++ b/core/src/avm2/object/loaderinfo_object.rs @@ -302,6 +302,7 @@ impl<'gc> LoaderInfoObject<'gc> { /// Unwrap this object's loader stream pub fn as_loader_stream(&self) -> Option>> { + // TODO: this can be non-Option. Some(self.0.loaded_stream.borrow()) }