avm2: Properly set LoaderInfo.contentType from sniffed type

This commit is contained in:
Aaron Hill 2023-12-24 16:11:53 -05:00
parent 41fb30a6a9
commit 583327ff62
10 changed files with 65 additions and 27 deletions

View File

@ -8,6 +8,7 @@ use crate::avm2::value::Value;
use crate::avm2::{AvmString, Error};
use crate::avm2_stub_getter;
use crate::display_object::TDisplayObject;
use crate::loader::ContentType;
use swf::{write_swf, Compression};
pub use crate::avm2::object::loader_info_allocator;
@ -175,16 +176,14 @@ pub fn get_content_type<'gc>(
this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(loader_stream) = this
.as_loader_info_object()
.and_then(|o| o.as_loader_stream())
{
match &*loader_stream {
LoaderStream::NotYetLoaded(_, _, _) => return Ok(Value::Null),
LoaderStream::Swf(_, _) => {
return Ok("application/x-shockwave-flash".into());
}
}
if let Some(loader_info) = this.as_loader_info_object() {
return match loader_info.content_type_hide_before_init() {
ContentType::Swf => Ok("application/x-shockwave-flash".into()),
ContentType::Jpeg => Ok("image/jpeg".into()),
ContentType::Png => Ok("image/png".into()),
ContentType::Gif => Ok("image/gif".into()),
ContentType::Unknown => Ok(Value::Null),
};
}
Ok(Value::Undefined)

View File

@ -10,6 +10,7 @@ use crate::avm2::Error;
use crate::avm2::EventObject;
use crate::context::UpdateContext;
use crate::display_object::{DisplayObject, TDisplayObject};
use crate::loader::ContentType;
use crate::tag_utils::SwfMovie;
use core::fmt;
use gc_arena::{Collect, GcCell, GcWeakCell, Mutation};
@ -99,6 +100,9 @@ pub struct LoaderInfoObjectData<'gc> {
uncaught_error_events: Object<'gc>,
cached_avm1movie: Option<Object<'gc>>,
#[collect(require_static)]
content_type: ContentType,
}
impl<'gc> LoaderInfoObject<'gc> {
@ -134,6 +138,7 @@ impl<'gc> LoaderInfoObject<'gc> {
.uncaughterrorevents
.construct(activation, &[])?,
cached_avm1movie: None,
content_type: ContentType::Swf,
},
))
.into();
@ -179,6 +184,7 @@ impl<'gc> LoaderInfoObject<'gc> {
.uncaughterrorevents
.construct(activation, &[])?,
cached_avm1movie: None,
content_type: ContentType::Unknown,
},
))
.into();
@ -201,6 +207,17 @@ impl<'gc> LoaderInfoObject<'gc> {
return self.0.read().uncaught_error_events;
}
/// Gets the `ContentType`, 'hiding' it by returning `ContentType::Unknown`
/// if we haven't yet fired the 'init' event. The real ContentType first becomes
/// visible to ActionScript in the 'init' event.
pub fn content_type_hide_before_init(&self) -> ContentType {
if self.0.read().init_event_fired {
self.0.read().content_type
} else {
ContentType::Unknown
}
}
pub fn fire_init_and_complete_events(
&self,
context: &mut UpdateContext<'_, 'gc>,
@ -269,6 +286,10 @@ impl<'gc> LoaderInfoObject<'gc> {
self.0.write(mc).loaded_stream = Some(stream);
}
pub fn set_content_type(&self, content_type: ContentType, mc: &Mutation<'gc>) {
self.0.write(mc).content_type = content_type;
}
/// Returns the AVM1Movie corresponding to the loaded movie- if
/// it doesn't exist yet, creates it.
pub fn get_or_init_avm1movie(

View File

@ -32,8 +32,8 @@ use crate::drawing::Drawing;
use crate::events::{ButtonKeyCode, ClipEvent, ClipEventResult};
use crate::font::{Font, FontType};
use crate::limits::ExecutionLimit;
use crate::loader;
use crate::loader::Loader;
use crate::loader::{self, ContentType};
use crate::prelude::*;
use crate::streams::NetStream;
use crate::string::{AvmString, SwfStrExt as _, WStr, WString};
@ -332,10 +332,14 @@ impl<'gc> MovieClip<'gc> {
let loader_info = if movie.is_action_script_3() {
// The root movie doesn't have a `Loader`
// We will replace this with a `LoaderStream::Swf` later in this function
Some(
let loader_info =
LoaderInfoObject::not_yet_loaded(activation, movie.clone(), None, None, false)
.expect("Failed to construct LoaderInfoObject"),
)
.expect("Failed to construct LoaderInfoObject");
loader_info
.as_loader_info_object()
.unwrap()
.set_content_type(ContentType::Swf, activation.context.gc_context);
Some(loader_info)
} else {
None
};

View File

@ -1668,6 +1668,10 @@ impl<'gc> Loader<'gc> {
};
if let MovieLoaderVMData::Avm2 { loader_info, .. } = vm_data {
loader_info
.as_loader_info_object()
.unwrap()
.set_content_type(sniffed_type, activation.context.gc_context);
let fake_movie = Arc::new(SwfMovie::empty_fake_compressed_len(
activation.context.swf.version(),
length,

View File

@ -43,6 +43,7 @@
trace("loader.contentLoaderInfo.bytes = " + loader.contentLoaderInfo.bytes);
trace("loader.contentLoaderInfo.url = " + loader.contentLoaderInfo.url);
trace("loader.contentLoaderInfo.parameters = " + loader.contentLoaderInfo.parameters);
trace("loader.contentLoaderInfo.contentType = " + loader.contentLoaderInfo.contentType);
dumpParams(loader.contentLoaderInfo.parameters);
}
@ -64,7 +65,8 @@
+ ", loader.contentLoaderInfo.bytesLoaded = " + loader.contentLoaderInfo.bytesLoaded
+ ", loader.contentLoaderInfo.bytesTotal = " + loader.contentLoaderInfo.bytesTotal
+ ", loader.contentLoaderInfo.bytes.length = " + loader.contentLoaderInfo.bytes.length
+ ", loader.contentLoaderInfo.url = " + url);
+ ", loader.contentLoaderInfo.url = " + url
+ ", loader.contentLoaderInfo.contentType = " + loader.contentLoaderInfo.contentType);
dumpParams(loader.contentLoaderInfo.parameters);
}

View File

@ -5,6 +5,7 @@ loader.contentLoaderInfo.bytesTotal = 0
loader.contentLoaderInfo.bytes = null
loader.contentLoaderInfo.url = null
loader.contentLoaderInfo.parameters = [object Object]
loader.contentLoaderInfo.contentType = null
Parameters: (len=0)
Directly after load:
@ -15,15 +16,16 @@ loader.contentLoaderInfo.bytesTotal = 0
loader.contentLoaderInfo.bytes =
loader.contentLoaderInfo.url = null
loader.contentLoaderInfo.parameters = [object Object]
loader.contentLoaderInfo.contentType = null
Parameters: (len=0)
Event [Event type="open" bubbles=false cancelable=false eventPhase=2]: loader.numChildren = 0, loader.content = null, loader.contentLoaderInfo.bytesLoaded = 0, loader.contentLoaderInfo.bytesTotal = 0, loader.contentLoaderInfo.bytes.length = 0, loader.contentLoaderInfo.url = null
Event [Event type="open" bubbles=false cancelable=false eventPhase=2]: loader.numChildren = 0, loader.content = null, loader.contentLoaderInfo.bytesLoaded = 0, loader.contentLoaderInfo.bytesTotal = 0, loader.contentLoaderInfo.bytes.length = 0, loader.contentLoaderInfo.url = null, loader.contentLoaderInfo.contentType = null
Parameters: (len=0)
Event [ProgressEvent type="progress" bubbles=false cancelable=false eventPhase=2 bytesLoaded=0 bytesTotal=893]: loader.numChildren = 0, loader.content = null, loader.contentLoaderInfo.bytesLoaded = 0, loader.contentLoaderInfo.bytesTotal = 893, loader.contentLoaderInfo.bytes.length = 0, loader.contentLoaderInfo.url = null
Event [ProgressEvent type="progress" bubbles=false cancelable=false eventPhase=2 bytesLoaded=0 bytesTotal=893]: loader.numChildren = 0, loader.content = null, loader.contentLoaderInfo.bytesLoaded = 0, loader.contentLoaderInfo.bytesTotal = 893, loader.contentLoaderInfo.bytes.length = 0, loader.contentLoaderInfo.url = null, loader.contentLoaderInfo.contentType = null
Parameters: (len=0)
Event [ProgressEvent type="progress" bubbles=false cancelable=false eventPhase=2 bytesLoaded=893 bytesTotal=893]: loader.numChildren = 0, loader.content = null, loader.contentLoaderInfo.bytesLoaded = 893, loader.contentLoaderInfo.bytesTotal = 893, loader.contentLoaderInfo.bytes.length = 1490, loader.contentLoaderInfo.url = null
Event [ProgressEvent type="progress" bubbles=false cancelable=false eventPhase=2 bytesLoaded=893 bytesTotal=893]: loader.numChildren = 0, loader.content = null, loader.contentLoaderInfo.bytesLoaded = 893, loader.contentLoaderInfo.bytesTotal = 893, loader.contentLoaderInfo.bytes.length = 1490, loader.contentLoaderInfo.url = null, loader.contentLoaderInfo.contentType = null
Parameters: (len=2)
paramOne = ValOne,paramTwo = ValTwo
Hello from loaded SWF main timeline: this.stage=null this.parent=null
@ -33,13 +35,13 @@ Added circle
Event.ADDED_TO_STAGE: circle.parent =[object LoadableMainTimeline] circle.stage=[object Stage] main.parent=[object Loader] main.stage=[object Stage]
loader.contentLoaderInfo === loader.content.loaderInfo : true
loader.contentLoaderInfo.content === loader.content : true
Event [Event type="init" bubbles=false cancelable=false eventPhase=2]: loader.numChildren = 1, loader.content = [object LoadableMainTimeline], loader.contentLoaderInfo.bytesLoaded = 893, loader.contentLoaderInfo.bytesTotal = 893, loader.contentLoaderInfo.bytes.length = 1490, loader.contentLoaderInfo.url = file:///
Event [Event type="init" bubbles=false cancelable=false eventPhase=2]: loader.numChildren = 1, loader.content = [object LoadableMainTimeline], loader.contentLoaderInfo.bytesLoaded = 893, loader.contentLoaderInfo.bytesTotal = 893, loader.contentLoaderInfo.bytes.length = 1490, loader.contentLoaderInfo.url = file:///, loader.contentLoaderInfo.contentType = application/x-shockwave-flash
Parameters: (len=2)
paramOne = ValOne,paramTwo = ValTwo
Event [HTTPStatusEvent type="httpStatus" bubbles=false cancelable=false eventPhase=2 status=0 redirected=false responseURL=null]: loader.numChildren = 1, loader.content = [object LoadableMainTimeline], loader.contentLoaderInfo.bytesLoaded = 893, loader.contentLoaderInfo.bytesTotal = 893, loader.contentLoaderInfo.bytes.length = 1490, loader.contentLoaderInfo.url = file:///
Event [HTTPStatusEvent type="httpStatus" bubbles=false cancelable=false eventPhase=2 status=0 redirected=false responseURL=null]: loader.numChildren = 1, loader.content = [object LoadableMainTimeline], loader.contentLoaderInfo.bytesLoaded = 893, loader.contentLoaderInfo.bytesTotal = 893, loader.contentLoaderInfo.bytes.length = 1490, loader.contentLoaderInfo.url = file:///, loader.contentLoaderInfo.contentType = application/x-shockwave-flash
Parameters: (len=2)
paramOne = ValOne,paramTwo = ValTwo
Event [Event type="complete" bubbles=false cancelable=false eventPhase=2]: loader.numChildren = 1, loader.content = [object LoadableMainTimeline], loader.contentLoaderInfo.bytesLoaded = 893, loader.contentLoaderInfo.bytesTotal = 893, loader.contentLoaderInfo.bytes.length = 1490, loader.contentLoaderInfo.url = file:///
Event [Event type="complete" bubbles=false cancelable=false eventPhase=2]: loader.numChildren = 1, loader.content = [object LoadableMainTimeline], loader.contentLoaderInfo.bytesLoaded = 893, loader.contentLoaderInfo.bytesTotal = 893, loader.contentLoaderInfo.bytes.length = 1490, loader.contentLoaderInfo.url = file:///, loader.contentLoaderInfo.contentType = application/x-shockwave-flash
Parameters: (len=2)
paramOne = ValOne,paramTwo = ValTwo
Starting orphan Loader
@ -50,6 +52,7 @@ loader.contentLoaderInfo.bytesTotal = 0
loader.contentLoaderInfo.bytes = null
loader.contentLoaderInfo.url = null
loader.contentLoaderInfo.parameters = [object Object]
loader.contentLoaderInfo.contentType = null
Parameters: (len=0)
Directly after load:
@ -60,15 +63,16 @@ loader.contentLoaderInfo.bytesTotal = 0
loader.contentLoaderInfo.bytes =
loader.contentLoaderInfo.url = null
loader.contentLoaderInfo.parameters = [object Object]
loader.contentLoaderInfo.contentType = null
Parameters: (len=0)
Event [Event type="open" bubbles=false cancelable=false eventPhase=2]: loader.numChildren = 0, loader.content = null, loader.contentLoaderInfo.bytesLoaded = 0, loader.contentLoaderInfo.bytesTotal = 0, loader.contentLoaderInfo.bytes.length = 0, loader.contentLoaderInfo.url = null
Event [Event type="open" bubbles=false cancelable=false eventPhase=2]: loader.numChildren = 0, loader.content = null, loader.contentLoaderInfo.bytesLoaded = 0, loader.contentLoaderInfo.bytesTotal = 0, loader.contentLoaderInfo.bytes.length = 0, loader.contentLoaderInfo.url = null, loader.contentLoaderInfo.contentType = null
Parameters: (len=0)
Event [ProgressEvent type="progress" bubbles=false cancelable=false eventPhase=2 bytesLoaded=0 bytesTotal=893]: loader.numChildren = 0, loader.content = null, loader.contentLoaderInfo.bytesLoaded = 0, loader.contentLoaderInfo.bytesTotal = 893, loader.contentLoaderInfo.bytes.length = 0, loader.contentLoaderInfo.url = null
Event [ProgressEvent type="progress" bubbles=false cancelable=false eventPhase=2 bytesLoaded=0 bytesTotal=893]: loader.numChildren = 0, loader.content = null, loader.contentLoaderInfo.bytesLoaded = 0, loader.contentLoaderInfo.bytesTotal = 893, loader.contentLoaderInfo.bytes.length = 0, loader.contentLoaderInfo.url = null, loader.contentLoaderInfo.contentType = null
Parameters: (len=0)
Event [ProgressEvent type="progress" bubbles=false cancelable=false eventPhase=2 bytesLoaded=893 bytesTotal=893]: loader.numChildren = 0, loader.content = null, loader.contentLoaderInfo.bytesLoaded = 893, loader.contentLoaderInfo.bytesTotal = 893, loader.contentLoaderInfo.bytes.length = 1490, loader.contentLoaderInfo.url = null
Event [ProgressEvent type="progress" bubbles=false cancelable=false eventPhase=2 bytesLoaded=893 bytesTotal=893]: loader.numChildren = 0, loader.content = null, loader.contentLoaderInfo.bytesLoaded = 893, loader.contentLoaderInfo.bytesTotal = 893, loader.contentLoaderInfo.bytes.length = 1490, loader.contentLoaderInfo.url = null, loader.contentLoaderInfo.contentType = null
Parameters: (len=2)
paramOne = ValOne,paramTwo = ValTwo
Hello from loaded SWF main timeline: this.stage=null this.parent=null
@ -77,12 +81,12 @@ Event.ADDED: circle.parent =[object LoadableMainTimeline] circle.stage=null main
Added circle
loader.contentLoaderInfo === loader.content.loaderInfo : true
loader.contentLoaderInfo.content === loader.content : true
Event [Event type="init" bubbles=false cancelable=false eventPhase=2]: loader.numChildren = 1, loader.content = [object LoadableMainTimeline], loader.contentLoaderInfo.bytesLoaded = 893, loader.contentLoaderInfo.bytesTotal = 893, loader.contentLoaderInfo.bytes.length = 1490, loader.contentLoaderInfo.url = file:///
Event [Event type="init" bubbles=false cancelable=false eventPhase=2]: loader.numChildren = 1, loader.content = [object LoadableMainTimeline], loader.contentLoaderInfo.bytesLoaded = 893, loader.contentLoaderInfo.bytesTotal = 893, loader.contentLoaderInfo.bytes.length = 1490, loader.contentLoaderInfo.url = file:///, loader.contentLoaderInfo.contentType = application/x-shockwave-flash
Parameters: (len=2)
paramOne = ValOne,paramTwo = ValTwo
Event [HTTPStatusEvent type="httpStatus" bubbles=false cancelable=false eventPhase=2 status=0 redirected=false responseURL=null]: loader.numChildren = 1, loader.content = [object LoadableMainTimeline], loader.contentLoaderInfo.bytesLoaded = 893, loader.contentLoaderInfo.bytesTotal = 893, loader.contentLoaderInfo.bytes.length = 1490, loader.contentLoaderInfo.url = file:///
Event [HTTPStatusEvent type="httpStatus" bubbles=false cancelable=false eventPhase=2 status=0 redirected=false responseURL=null]: loader.numChildren = 1, loader.content = [object LoadableMainTimeline], loader.contentLoaderInfo.bytesLoaded = 893, loader.contentLoaderInfo.bytesTotal = 893, loader.contentLoaderInfo.bytes.length = 1490, loader.contentLoaderInfo.url = file:///, loader.contentLoaderInfo.contentType = application/x-shockwave-flash
Parameters: (len=2)
paramOne = ValOne,paramTwo = ValTwo
Event [Event type="complete" bubbles=false cancelable=false eventPhase=2]: loader.numChildren = 1, loader.content = [object LoadableMainTimeline], loader.contentLoaderInfo.bytesLoaded = 893, loader.contentLoaderInfo.bytesTotal = 893, loader.contentLoaderInfo.bytes.length = 1490, loader.contentLoaderInfo.url = file:///
Event [Event type="complete" bubbles=false cancelable=false eventPhase=2]: loader.numChildren = 1, loader.content = [object LoadableMainTimeline], loader.contentLoaderInfo.bytesLoaded = 893, loader.contentLoaderInfo.bytesTotal = 893, loader.contentLoaderInfo.bytes.length = 1490, loader.contentLoaderInfo.url = file:///, loader.contentLoaderInfo.contentType = application/x-shockwave-flash
Parameters: (len=2)
paramOne = ValOne,paramTwo = ValTwo

View File

@ -1,4 +1,8 @@
Progress event: [ProgressEvent type="progress" bubbles=false cancelable=false eventPhase=2 bytesLoaded=0 bytesTotal=334]
loader.contentLoaderInfo.contentType: null
Progress event: [ProgressEvent type="progress" bubbles=false cancelable=false eventPhase=2 bytesLoaded=334 bytesTotal=334]
loader.contentLoaderInfo.contentType: null
Init event: [Event type="init" bubbles=false cancelable=false eventPhase=2]
loader.contentLoaderInfo.contentType: image/png
Complete event: [Event type="complete" bubbles=false cancelable=false eventPhase=2]
loader.contentLoaderInfo.contentType: image/png

BIN
tests/tests/swfs/avm2/loader_image/test.fla Normal file → Executable file

Binary file not shown.