1//////////////////////////////////////////////////////////////////////////////// 2// 3// ADOBE SYSTEMS INCORPORATED 4// Copyright 2005-2007 Adobe Systems Incorporated 5// All Rights Reserved. 6// 7// NOTICE: Adobe permits you to use, modify, and distribute this file 8// in accordance with the terms of the license agreement accompanying it. 9// 10//////////////////////////////////////////////////////////////////////////////// 11 12package mx.core 13{ 14 15import flash.display.LoaderInfo; 16import flash.display.MovieClip; 17import flash.events.ErrorEvent; 18import flash.events.Event; 19import flash.events.IOErrorEvent; 20import flash.events.SecurityErrorEvent; 21import flash.events.TimerEvent; 22import flash.system.ApplicationDomain; 23import flash.text.TextField; 24import flash.text.TextFieldAutoSize; 25import flash.utils.Dictionary; 26import flash.utils.Timer; 27import flash.utils.getDefinitionByName; 28import mx.core.RSLItem; 29import mx.core.RSLListLoader; 30import mx.events.ModuleEvent; 31import mx.resources.IResourceManager; 32import mx.resources.ResourceManager; 33 34[ExcludeClass] 35 36/** 37 * @private 38 */ 39public class FlexModuleFactory extends MovieClip implements IFlexModuleFactory 40{ 41 include "../core/Version.as"; 42 43 //-------------------------------------------------------------------------- 44 // 45 // Class constants 46 // 47 //-------------------------------------------------------------------------- 48 49 /** 50 * @private 51 */ 52 private static const INIT_STATE:int = 0; 53 54 /** 55 * @private 56 */ 57 private static const RSL_START_LOAD_STATE:int = 1; 58 59 /** 60 * @private 61 */ 62 private static const APP_LOAD_STATE:int = 2; 63 64 /** 65 * @private 66 */ 67 private static const APP_START_STATE:int = 3; 68 69 /** 70 * @private 71 */ 72 private static const APP_RUNNING_STATE:int = 4; 73 74 /** 75 * @private 76 */ 77 private static const ERROR_STATE:int = 5; 78 79 /** 80 * @private 81 */ 82 private static const RSL_LOADING_STATE:int = 6; 83 84 85 //-------------------------------------------------------------------------- 86 // 87 // Constructor 88 // 89 //-------------------------------------------------------------------------- 90 91 /** 92 * @private 93 */ 94 public function FlexModuleFactory() 95 { 96 super(); 97 98 var rsls:Array = info()["rsls"]; 99 var cdRsls:Array = info()["cdRsls"]; 100 101 // Put cross-domain RSL information in the RSL list. 102 var rslList:Array = []; 103 var n:int; 104 var i:int; 105 if (cdRsls && cdRsls.length > 0) 106 { 107 var crossDomainRSLItem:Class = Class(getDefinitionByName("mx.core::CrossDomainRSLItem")); 108 n = cdRsls.length; 109 for (i = 0; i < n; i++) 110 { 111 // If crossDomainRSLItem is null, then this is a compiler error. It should not be null. 112 var cdNode:Object = new crossDomainRSLItem( 113 cdRsls[i]["rsls"], 114 cdRsls[i]["policyFiles"], 115 cdRsls[i]["digests"], 116 cdRsls[i]["types"], 117 cdRsls[i]["isSigned"]); 118 119 rslList.push(cdNode); 120 } 121 122 } 123 124 // Append RSL information in the RSL list. 125 if (rsls != null && rsls.length > 0) 126 { 127 n = rsls.length; 128 for (i = 0; i < n; i++) 129 { 130 var node:RSLItem = new RSLItem(rsls[i].url); 131 rslList.push(node); 132 } 133 } 134 135 rslListLoader = new RSLListLoader(rslList); 136 137 mixinList = info()["mixins"]; 138 139 stop(); // Make sure to stop the playhead on the currentframe 140 141 loaderInfo.addEventListener(Event.COMPLETE, moduleCompleteHandler); 142 143 var docFrame:int = totalFrames == 1 ? 0 : 1; 144 145 addEventListener(Event.ENTER_FRAME, docFrameListener); 146 147 timer = new Timer(100); 148 timer.addEventListener(TimerEvent.TIMER, timerHandler); 149 timer.start(); 150 151 update(); 152 } 153 154 private function docFrameListener(event:Event):void 155 { 156 if (currentFrame == 2) 157 { 158 removeEventListener(Event.ENTER_FRAME, docFrameListener); 159 if (totalFrames > 2) 160 addEventListener(Event.ENTER_FRAME, extraFrameListener); 161 162 docFrameHandler(); 163 } 164 } 165 166 private function extraFrameListener(event:Event):void 167 { 168 if (lastFrame == currentFrame) 169 return; 170 171 lastFrame = currentFrame; 172 173 if (currentFrame + 1 > totalFrames) 174 removeEventListener(Event.ENTER_FRAME, extraFrameListener); 175 176 extraFrameHandler(); 177 } 178 179 //-------------------------------------------------------------------------- 180 // 181 // Variables 182 // 183 //-------------------------------------------------------------------------- 184 185 /** 186 * @private 187 */ 188 private var rslListLoader:RSLListLoader; 189 190 /** 191 * @private 192 */ 193 private var mixinList:Array; 194 195 /** 196 * @private 197 */ 198 private var state:int = INIT_STATE; 199 200 /** 201 * @private 202 */ 203 private var appReady:Boolean = false; 204 205 /** 206 * @private 207 */ 208 private var appLoaded:Boolean = false; 209 210 /** 211 * @private 212 */ 213 private var timer:Timer = null; 214 215 /** 216 * @private 217 * Track which frame was last processed 218 */ 219 private var lastFrame:int; 220 221 /** 222 * @private 223 */ 224 private var nextFrameTimer:Timer = null; 225 226 /** 227 * @private 228 */ 229 private var errorMessage:String = null; 230 231 //---------------------------------- 232 // preloadedRSLs 233 //---------------------------------- 234 235 /** 236 * The RSLs loaded by this FlexModuleFactory before the application 237 * starts. RSLs loaded by the application are not included in this list. 238 * 239 * Information about preloadedRSLs is stored in a Dictionary. The key is 240 * the RSL's LoaderInfo. The value is the url the RSL was loaded from. 241 */ 242 public function get preloadedRSLs():Dictionary 243 { 244 // Overriden by compiler generate code. 245 return null; 246 } 247 248 //-------------------------------------------------------------------------- 249 // 250 // Methods 251 // 252 //-------------------------------------------------------------------------- 253 254 /** 255 * @private 256 * This method is overridden in the autogenerated subclass. 257 */ 258 public function create(... params):Object 259 { 260 var mainClassName:String = info()["mainClassName"]; 261 262 if (mainClassName == null) 263 { 264 var url:String = loaderInfo.loaderURL; 265 var dot:Number = url.lastIndexOf("."); 266 var slash:Number = url.lastIndexOf("/"); 267 mainClassName = url.substring(slash + 1, dot); 268 } 269 270 var mainClass:Class = Class(getDefinitionByName(mainClassName)); 271 272 return mainClass? new mainClass() : null; 273 } 274 275 /** 276 * @private 277 */ 278 public function info():Object 279 { 280 return {}; 281 } 282 283 /** 284 * Calls Security.allowDomain() for the SWF associated with this FlexModuleFactory. 285 * plus all the SWFs assocatiated with RSLs preloaded by this FlexModuleFactory. 286 * 287 */ 288 public function allowDomain(... domains):void 289 { 290 // Overridden by compiler generated code. 291 } 292 293 /** 294 * Calls Security.allowInsecureDomain() for the SWF associated with this FlexModuleFactory 295 * plus all the SWFs assocatiated with RSLs preloaded by this FlexModuleFactory. 296 * 297 */ 298 public function allowInsecureDomain(... domains):void 299 { 300 // Overridden by compiler generated code. 301 } 302 303 /** 304 * @inheritDoc 305 */ 306 public function getDefinitionByName(name:String):Object 307 { 308 const domain:ApplicationDomain = 309 info()["currentDomain"] as ApplicationDomain; 310 311 var definition:Object; 312 if (domain.hasDefinition(name)) 313 definition = domain.getDefinition(name); 314 315 return definition; 316 } 317 318 /** 319 * @private 320 */ 321 private function update():void 322 { 323 switch (state) 324 { 325 case INIT_STATE: 326 { 327 if (rslListLoader.isDone()) 328 state = APP_LOAD_STATE; 329 else 330 state = RSL_START_LOAD_STATE; 331 break; 332 } 333 334 case RSL_START_LOAD_STATE: 335 { 336 // start loading all the rsls 337 rslListLoader.load(null, 338 rslCompleteHandler, 339 rslErrorHandler, 340 rslErrorHandler, 341 rslErrorHandler); 342 state = RSL_LOADING_STATE; 343 break; 344 } 345 case RSL_LOADING_STATE: 346 { 347 if (rslListLoader.isDone()) 348 { 349 state = APP_LOAD_STATE; 350 } 351 break; 352 } 353 354 case APP_LOAD_STATE: 355 { 356 if (appLoaded) 357 { 358 deferredNextFrame(); 359 state = APP_START_STATE; 360 } 361 break; 362 } 363 364 case APP_START_STATE: 365 { 366 if (appReady) 367 { 368 if (mixinList && mixinList.length > 0) 369 { 370 var n:int = mixinList.length; 371 for (var i:int = 0; i < n; i++) 372 { 373 var c:Class; 374 try 375 { 376 c = Class(getDefinitionByName(mixinList[i])); 377 c["init"](this); 378 } 379 catch(e:Error) 380 { 381 } 382 } 383 } 384 385 state = APP_RUNNING_STATE; 386 timer.removeEventListener(TimerEvent.TIMER, timerHandler); 387 // Stop the timer. 388 timer.reset(); 389 390 dispatchEvent(new Event("ready")); 391 392 loaderInfo.removeEventListener(Event.COMPLETE, moduleCompleteHandler); 393 } 394 break; 395 } 396 397 case ERROR_STATE: 398 { 399 if (timer != null) 400 { 401 timer.removeEventListener(TimerEvent.TIMER, timerHandler); 402 // stop the timer 403 timer.reset(); 404 } 405 406 var tf:TextField = new TextField(); 407 tf.text = errorMessage; 408 tf.x = 0; 409 tf.y = 0; 410 tf.autoSize = TextFieldAutoSize.LEFT; 411 addChild(tf); 412 413 dispatchEvent(new ModuleEvent(ModuleEvent.ERROR, false, false, 414 0, 0, errorMessage)); 415 416 loaderInfo.removeEventListener(Event.COMPLETE, moduleCompleteHandler); 417 break; 418 } 419 } 420 } 421 422 /** 423 * @private 424 */ 425 public function autorun():Boolean 426 { 427 return true; 428 } 429 430 /** 431 * @private 432 */ 433 private function displayError(msg:String):void 434 { 435 errorMessage = msg; 436 state = ERROR_STATE; 437 update(); 438 } 439 440 /** 441 * @private 442 */ 443 private function docFrameHandler(event:Event = null):void 444 { 445 // Register singleton classes. 446 // Note: getDefinitionByName() will return null 447 // if the class can't be found. 448 449 Singleton.registerClass("mx.managers::IBrowserManager", 450 Class(getDefinitionByName("mx.managers::BrowserManagerImpl"))); 451 452 Singleton.registerClass("mx.managers::ICursorManager", 453 Class(getDefinitionByName("mx.managers::CursorManagerImpl"))); 454 455 Singleton.registerClass("mx.managers::IDragManager", 456 Class(getDefinitionByName("mx.managers::DragManagerImpl"))); 457 458 Singleton.registerClass("mx.managers::IHistoryManager", 459 Class(getDefinitionByName("mx.managers::HistoryManagerImpl"))); 460 461 Singleton.registerClass("mx.managers::ILayoutManager", 462 Class(getDefinitionByName("mx.managers::LayoutManager"))); 463 464 Singleton.registerClass("mx.managers::IPopUpManager", 465 Class(getDefinitionByName("mx.managers::PopUpManagerImpl"))); 466 467 Singleton.registerClass("mx.resources::IResourceManager", 468 Class(getDefinitionByName("mx.resources::ResourceManagerImpl"))); 469 470 Singleton.registerClass("mx.styles::IStyleManager", 471 Class(getDefinitionByName("mx.styles::StyleManagerImpl"))); 472 473 Singleton.registerClass("mx.styles::IStyleManager2", 474 Class(getDefinitionByName("mx.styles::StyleManagerImpl"))); 475 476 Singleton.registerClass("mx.managers::IToolTipManager2", 477 Class(getDefinitionByName("mx.managers::ToolTipManagerImpl"))); 478 479 appReady = true; 480 481 // The resources must be installed before update() creates components 482 // (such as DateChooswer) that might need them immediately. 483 installCompiledResourceBundles(); 484 485 update(); 486 487 if (currentFrame < totalFrames) 488 deferredNextFrame(); 489 } 490 491 /** 492 * @private 493 */ 494 private function installCompiledResourceBundles():void 495 { 496 //trace("FlexModuleFactory.installCompiledResourceBundles"); 497 498 var info:Object = this.info(); 499 500 var applicationDomain:ApplicationDomain = 501 info["currentDomain"]; 502 503 var compiledLocales:Array /* of String */ = 504 info["compiledLocales"]; 505 506 var compiledResourceBundleNames:Array /* of String */ = 507 info["compiledResourceBundleNames"]; 508 509 var resourceManager:IResourceManager = 510 ResourceManager.getInstance(); 511 512 resourceManager.installCompiledResourceBundles( 513 applicationDomain, compiledLocales, compiledResourceBundleNames); 514 515 // If the localeChain wasn't specified in the FlashVars of the SWF's 516 // HTML wrapper, or in the query parameters of the SWF URL, 517 // then initialize it to the list of compiled locales, 518 // sorted according to the system's preferred locales as reported by 519 // Capabilities.languages or Capabilities.language. 520 // For example, if the applications was compiled with, say, 521 // -locale=en_US,ja_JP and Capabilities.languages reports [ "ja-JP" ], 522 // set the localeChain to [ "ja_JP" "en_US" ]. 523 if (!resourceManager.localeChain) 524 resourceManager.initializeLocaleChain(compiledLocales); 525 } 526 527 /** 528 * @private 529 */ 530 private function deferredNextFrame():void 531 { 532 if (currentFrame + 1 <= framesLoaded) 533 { 534 nextFrame(); 535 } 536 else 537 { 538 // Next frame isn't baked yet, we'll check back... 539 nextFrameTimer = new Timer(100); 540 nextFrameTimer.addEventListener(TimerEvent.TIMER, 541 nextFrameTimerHandler); 542 nextFrameTimer.start(); 543 } 544 } 545 /** 546 * @private 547 */ 548 private function extraFrameHandler(event:Event = null):void 549 { 550 var frameList:Object = info()["frames"]; 551 552 if (frameList && frameList[currentLabel]) 553 { 554 var c:Class; 555 try 556 { 557 c = Class(getDefinitionByName(frameList[currentLabel])); 558 c["frame"](this); 559 } 560 catch(e:Error) 561 { 562 } 563 } 564 565 if (currentFrame < totalFrames) 566 deferredNextFrame(); 567 } 568 569 //-------------------------------------------------------------------------- 570 // 571 // Event handlers 572 // 573 //-------------------------------------------------------------------------- 574 575 /** 576 * @private 577 */ 578 private function rslCompleteHandler(event:Event):void 579 { 580 var rsl:RSLItem = rslListLoader.getItem(rslListLoader.getIndex()); 581 if (event.target is LoaderInfo) 582 preloadedRSLs[event.target] = rsl.urlRequest.url; 583 update(); 584 } 585 586 /** 587 * @private 588 */ 589 private function rslErrorHandler(event:Event):void 590 { 591 var rsl:RSLItem = rslListLoader.getItem(rslListLoader.getIndex()); 592 var detailedError:String; 593 var message:String; 594 595 if (event is ErrorEvent) 596 detailedError = ErrorEvent(event).text; 597 598 if (!detailedError) 599 detailedError = ""; 600 601 message = "RSL " + rsl.urlRequest.url + " failed to load. " + detailedError; 602 trace(message); 603 displayError(message); 604 } 605 606 /** 607 * @private 608 */ 609 private function moduleCompleteHandler(event:Event):void 610 { 611 appLoaded = true; 612 update(); 613 } 614 615 /** 616 * @private 617 */ 618 private function timerHandler(event:TimerEvent):void 619 { 620 if (totalFrames > 2 && framesLoaded >= 2 || 621 framesLoaded == totalFrames) 622 { 623 appLoaded = true; 624 } 625 626 update(); 627 } 628 629 /** 630 * @private 631 */ 632 private function nextFrameTimerHandler(event:TimerEvent):void 633 { 634 if (currentFrame + 1 <= framesLoaded) 635 { 636 nextFrame(); 637 nextFrameTimer.removeEventListener(TimerEvent.TIMER, 638 nextFrameTimerHandler); 639 // stop the timer 640 nextFrameTimer.reset(); 641 } 642 } 643} 644 645} 646