From 8f5afe09a1925bee8f7a51a77b1b800dee0f96b1 Mon Sep 17 00:00:00 2001 From: David Wendt Date: Thu, 8 Sep 2022 22:17:01 -0400 Subject: [PATCH] core: Refactor `movie_loader` and its `loadBytes` variant to call into the same code. --- core/src/loader.rs | 338 ++++++++++++++++----------------------------- 1 file changed, 122 insertions(+), 216 deletions(-) diff --git a/core/src/loader.rs b/core/src/loader.rs index 7a9d9c514..98df964dc 100644 --- a/core/src/loader.rs +++ b/core/src/loader.rs @@ -708,120 +708,22 @@ impl<'gc> Loader<'gc> { })?; match fetch.await { + Ok(response) if replacing_root_movie => { + ContentType::sniff(&response.body).expect(ContentType::Swf)?; + + let movie = + SwfMovie::from_data(&response.body, Some(response.url), loader_url)?; + player.lock().unwrap().set_root_movie(movie); + return Ok(()); + } Ok(response) => { - let sniffed_type = ContentType::sniff(&response.body); - let mut length = response.body.len(); - - if replacing_root_movie { - sniffed_type.expect(ContentType::Swf)?; - - let movie = - SwfMovie::from_data(&response.body, Some(response.url), loader_url)?; - player.lock().unwrap().set_root_movie(movie); - return Ok(()); - } - - player.lock().unwrap().update(|uc| { - let (clip, event_handler) = match uc.load_manager.get_loader(handle) { - Some(Loader::Movie { - target_clip, - event_handler, - .. - }) => (*target_clip, *event_handler), - None => return Err(Error::Cancelled), - _ => unreachable!(), - }; - - if let ContentType::Unknown = sniffed_type { - length = 0; - } - - if let Some(MovieLoaderEventHandler::Avm2LoaderInfo(_)) = event_handler { - // Flash always fires an initial 'progress' event with - // bytesLoaded=0 and bytesTotal set to the proper value. - // This only seems to happen for an AVM2 event handler - Loader::movie_loader_progress(handle, uc, 0, length)?; - } - - match sniffed_type { - ContentType::Swf => { - let movie = Arc::new(SwfMovie::from_data( - &response.body, - Some(response.url), - loader_url, - )?); - - match uc.load_manager.get_loader_mut(handle) { - Some(Loader::Movie { - movie: old, - loader_status, - .. - }) => { - *loader_status = LoaderStatus::Parsing; - *old = Some(movie.clone()) - } - _ => unreachable!(), - }; - - let mut activation = Avm2Activation::from_nothing(uc.reborrow()); - let parent_domain = activation.avm2().global_domain(); - let domain = - Avm2Domain::movie_domain(&mut activation, parent_domain); - activation - .context - .library - .library_for_movie_mut(movie.clone()) - .set_avm2_domain(domain); - - if let Some(mut mc) = clip.as_movie_clip() { - let loader_info = if let Some( - MovieLoaderEventHandler::Avm2LoaderInfo(loader_info), - ) = event_handler - { - Some(*loader_info.as_loader_info_object().unwrap()) - } else { - None - }; - - // Store our downloaded `SwfMovie` into our target `MovieClip`, - // and initialize it. - - mc.replace_with_movie( - &mut activation.context, - Some(movie), - loader_info, - ); - } - - // NOTE: Certain tests specifically expect small files to preload immediately - Loader::preload_tick( - handle, - uc, - &mut ExecutionLimit::with_max_actions_and_time( - 10000, - Duration::from_millis(1), - ), - )?; - - return Ok(()); - } - ContentType::Gif | ContentType::Jpeg | ContentType::Png => { - let bitmap = uc.renderer.register_bitmap_jpeg_2(&response.body)?; - let bitmap_obj = - Bitmap::new(uc, 0, bitmap.handle, bitmap.width, bitmap.height); - - if let Some(mc) = clip.as_movie_clip() { - mc.replace_at_depth(uc, bitmap_obj.into(), 1); - } - } - ContentType::Unknown => {} - } - - Loader::movie_loader_progress(handle, uc, length, length)?; - Loader::movie_loader_complete(handle, uc)?; - - Ok(()) - })?; //TODO: content sniffing errors need to be reported somehow + Loader::movie_loader_data( + handle, + player, + &response.body, + Some(response.url), + loader_url, + )?; } Err(e) => { log::error!("Error during movie loading: {:?}", e); @@ -870,115 +772,15 @@ impl<'gc> Loader<'gc> { Ok(()) })?; - let sniffed_type = ContentType::sniff(&bytes); - let mut length = bytes.len(); - if replacing_root_movie { - sniffed_type.expect(ContentType::Swf)?; + ContentType::sniff(&bytes).expect(ContentType::Swf)?; - let movie = SwfMovie::from_data(&bytes, None, None)?; + let movie = SwfMovie::from_data(&bytes, Some("file:///".into()), None)?; player.lock().unwrap().set_root_movie(movie); return Ok(()); } - player.lock().unwrap().update(|uc| { - let (clip, event_handler) = match uc.load_manager.get_loader(handle) { - Some(Loader::Movie { - target_clip, - event_handler, - .. - }) => (*target_clip, *event_handler), - None => return Err(Error::Cancelled), - _ => unreachable!(), - }; - - if let ContentType::Unknown = sniffed_type { - length = 0; - } - - if let Some(MovieLoaderEventHandler::Avm2LoaderInfo(_)) = event_handler { - // Flash always fires an initial 'progress' event with - // bytesLoaded=0 and bytesTotal set to the proper value. - // This only seems to happen for an AVM2 event handler - Loader::movie_loader_progress(handle, uc, 0, length)?; - } - - match sniffed_type { - ContentType::Swf => { - let movie = Arc::new(SwfMovie::from_data(&bytes, None, None)?); - - match uc.load_manager.get_loader_mut(handle) { - Some(Loader::Movie { - movie: old, - loader_status, - .. - }) => { - *loader_status = LoaderStatus::Parsing; - *old = Some(movie.clone()) - } - _ => unreachable!(), - }; - - let mut activation = Avm2Activation::from_nothing(uc.reborrow()); - let parent_domain = activation.avm2().global_domain(); - let domain = Avm2Domain::movie_domain(&mut activation, parent_domain); - activation - .context - .library - .library_for_movie_mut(movie.clone()) - .set_avm2_domain(domain); - - if let Some(mut mc) = clip.as_movie_clip() { - let loader_info = - if let Some(MovieLoaderEventHandler::Avm2LoaderInfo(loader_info)) = - event_handler - { - Some(*loader_info.as_loader_info_object().unwrap()) - } else { - None - }; - - // Store our downloaded `SwfMovie` into our target `MovieClip`, - // and initialize it. - - mc.replace_with_movie( - &mut activation.context, - Some(movie), - loader_info, - ); - } - - // NOTE: Certain tests specifically expect small files to preload immediately - Loader::preload_tick( - handle, - uc, - &mut ExecutionLimit::with_max_actions_and_time( - 10000, - Duration::from_millis(1), - ), - )?; - - return Ok(()); - } - ContentType::Gif | ContentType::Jpeg | ContentType::Png => { - let bitmap = uc.renderer.register_bitmap_jpeg_2(&bytes)?; - let bitmap_obj = - Bitmap::new(uc, 0, bitmap.handle, bitmap.width, bitmap.height); - - if let Some(mc) = clip.as_movie_clip() { - mc.replace_at_depth(uc, bitmap_obj.into(), 1); - } - } - ContentType::Unknown => {} - } - - Loader::movie_loader_progress(handle, uc, length, length)?; - Loader::movie_loader_complete(handle, uc)?; - - Ok(()) - })?; //TODO: content sniffing errors need to be reported somehow - - Ok(()) + Loader::movie_loader_data(handle, player, &bytes, Some("file:///".into()), None) }) } @@ -1455,6 +1257,110 @@ impl<'gc> Loader<'gc> { Ok(()) } + /// Load data into a movie loader. + fn movie_loader_data( + handle: Handle, + player: Arc>, + data: &[u8], + url: Option, + loader_url: Option, + ) -> Result<(), Error> { + let sniffed_type = ContentType::sniff(data); + let mut length = data.len(); + + player.lock().unwrap().update(|uc| { + let (clip, event_handler) = match uc.load_manager.get_loader(handle) { + Some(Loader::Movie { + target_clip, + event_handler, + .. + }) => (*target_clip, *event_handler), + None => return Err(Error::Cancelled), + _ => unreachable!(), + }; + + if let ContentType::Unknown = sniffed_type { + length = 0; + } + + if let Some(MovieLoaderEventHandler::Avm2LoaderInfo(_)) = event_handler { + // Flash always fires an initial 'progress' event with + // bytesLoaded=0 and bytesTotal set to the proper value. + // This only seems to happen for an AVM2 event handler + Loader::movie_loader_progress(handle, uc, 0, length)?; + } + + match sniffed_type { + ContentType::Swf => { + let movie = Arc::new(SwfMovie::from_data(data, url, loader_url)?); + + match uc.load_manager.get_loader_mut(handle) { + Some(Loader::Movie { + movie: old, + loader_status, + .. + }) => { + *loader_status = LoaderStatus::Parsing; + *old = Some(movie.clone()) + } + _ => unreachable!(), + }; + + let mut activation = Avm2Activation::from_nothing(uc.reborrow()); + let parent_domain = activation.avm2().global_domain(); + let domain = Avm2Domain::movie_domain(&mut activation, parent_domain); + activation + .context + .library + .library_for_movie_mut(movie.clone()) + .set_avm2_domain(domain); + + if let Some(mut mc) = clip.as_movie_clip() { + let loader_info = + if let Some(MovieLoaderEventHandler::Avm2LoaderInfo(loader_info)) = + event_handler + { + Some(*loader_info.as_loader_info_object().unwrap()) + } else { + None + }; + + // Store our downloaded `SwfMovie` into our target `MovieClip`, + // and initialize it. + + mc.replace_with_movie(&mut activation.context, Some(movie), loader_info); + } + + // NOTE: Certain tests specifically expect small files to preload immediately + Loader::preload_tick( + handle, + uc, + &mut ExecutionLimit::with_max_actions_and_time( + 10000, + Duration::from_millis(1), + ), + )?; + + return Ok(()); + } + ContentType::Gif | ContentType::Jpeg | ContentType::Png => { + let bitmap = uc.renderer.register_bitmap_jpeg_2(&data)?; + let bitmap_obj = Bitmap::new(uc, 0, bitmap.handle, bitmap.width, bitmap.height); + + if let Some(mc) = clip.as_movie_clip() { + mc.replace_at_depth(uc, bitmap_obj.into(), 1); + } + } + ContentType::Unknown => {} + } + + Loader::movie_loader_progress(handle, uc, length, length)?; + Loader::movie_loader_complete(handle, uc)?; + + Ok(()) + }) //TODO: content sniffing errors need to be reported somehow + } + /// Report a movie loader progress event to script code. /// /// The current and total length are always reported as compressed lengths.