19 Replies Latest reply on Mar 10, 2007 6:26 PM by Bzyku@GB

    Cross-domain loading module to local application

    Bzyku@GB
      Crying for help!

      I've spend loads of time trying to solve the problem. Googling doesn't
      give any solutions, so it's time for the experts :)

      I need application running on local machine (swf file on Desktop) to
      download a module from server and display it.

      So far I can download it, set the applicationDomain, but how to
      display it?

      Local app.:
      ===================================================
      <?xml version="1.0" encoding="utf-8"?>
      <mx:Application xmlns:mx=" http://www.adobe.com/2006/mxml"
      creationComplete="setup()">
      <mx:Script>
      <![CDATA[
      import mx.events.ModuleEvent;
      import mx.controls.Alert;
      import flash.system.ApplicationDomain;
      import flash.system.Security
      import mx.modules.*;
      import mx.core.UIComponent;
      private var go:String = " http://some.domain/browse.swf";
      public var loader:Loader = new Loader();
      private var uicomp:UIComponent = new UIComponent();
      private var panel:Panel = new Panel();

      public function setup():void {
      Security.allowDomain("some.domain");
      Security.loadPolicyFile(" http://some.domain/crossdomain.xml");
      handleGo();
      }

      private function handleGo():void {
      var request:URLRequest = new URLRequest(go);
      var loaderContext:LoaderContext = new LoaderContext();
      loaderContext.applicationDomain = ApplicationDomain.currentDomain;
      loaderContext.checkPolicyFile = true;
      // loaderContext.securityDomain = SecurityDomain.currentDomain;
      // LOCAL SWF files may not set loaderContext.securityDomain
      loader.contentLoaderInfo.addEventListener(Event.COMPLETE, modComplete);
      loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, def);
      loader.load(request, loaderContext);
      }
      private function modComplete(event:Event):void{
      // Alert.show(loader.contentLoaderInfo.childAllowsParent.toString(),"ch"); // gives TRUE
      // Alert.show(loader.contentLoaderInfo.parentAllowsChild.toString(),"p"); // gives TRUE

      // Now if I go with following:

      uicomp.addChild(loader.content);
      panel.addChild(uicomp);
      panel.width = 200;
      panel.height = 200;
      mainCanvas.addChild(panel);

      // It showes only a panel but no module content inside :(

      }

      private function def(event:Event):void{
      Alert.show(event.toString(), event.type);
      }
      ]]>
      </mx:Script>
      <mx:Canvas id="mainCanvas" width="100%" height="100%" />
      </mx:Application>
      ===================================================

      Remote mod.:
      ===================================================
      <?xml version="1.0" encoding="utf-8"?>
      <mx:Module xmlns:mx=" http://www.adobe.com/2006/mxml"
      percentWidth="100" percentHeight="100">
      <mx:HBox xmlns:mx=" http://www.adobe.com/2006/mxml" width="100%"
      height="100%" backgroundColor="#ffffff">
      <mx:Text text="test text 1"/>
      <mx:Text text="test text 2"/>
      </mx:HBox>
      </mx:Module>
      ===================================================

      HELP!
        • 1. Re: Cross-domain loading module to local application
          buabco Level 1
          HI!

          I think you've been complicating yourself. First of all the player will look for the crossdomain file by itself. Also all this cross domain stuff is only necesary if both flash application require some interaction between each other.

          I'm not sure where in your code is the problem, since it looks good, but why no try something simpler like:
          <?xml version="1.0" encoding="utf-8"?>
          <mx:Application xmlns:mx=" http://www.adobe.com/2006/mxml">
          <mx:SWFLoader id="module" source="{go}" width="100%" height="100%" scaleContent="true" autoLoad="true"/>
          </mx:Application>

          This should work as long as you crossdomain file is OK.


          • 2. Re: Cross-domain loading module to local application
            Bzyku@GB Level 1
            I'm afraid it doesn't work. Besides I need the shell and the module to communicate :(
            • 3. Re: Cross-domain loading module to local application
              buabco Level 1
              I think you are in trouble here, cos ether you access the local disk or the net, you can't do both. If you want this last thing, you'll have to manually setup the security configuration on the flash player so it will consider your movie as a trusted one.
              • 4. Re: Cross-domain loading module to local application
                Bzyku@GB Level 1
                The think is that it loads. If I set:

                loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, def);

                It shows the full file data uploaded. The:

                Alert.show(loader.content.toString());
                and
                Alert.show(loader.contentLoaderInfo.contentType.toString())

                give:

                [object _toBrowse_mx_core_FlexModuleFactory]
                and
                application/x-shockwave-flash

                What I'm struggling with is how to handle FlexModuleFactory type of object and throw it to the display.

                uicomp.addChild(loader.content);

                Takes it with no problem, but should I do that?... My knowledge and understanding is not enough right now.

                The suggested Global Security Settings of a player doesn't seem to handle the problem.
                • 5. Re: Cross-domain loading module to local application
                  buabco Level 1
                  actually, you can also do addChild(loader);

                  But if it works, why are you having trouble....

                  If you are using flex though I sugest you use flex component to do the job and if you are loading a SWF use the SWFLoader. This because is seem that when you add childs to flex components, the are requiered to implement various functions of UIComponent, specially on the measuring and positioning side, when you do the addChild(loader.content) you are adding a DisplayObject so you might have some unimplemented functions there.

                  Since SWFLoader is a UIComponent, you can add it directly to the panel, even if the loading havent finished jet.
                  • 6. Re: Cross-domain loading module to local application
                    Bzyku@GB Level 1
                    addChild(loader) => gives an error:

                    TypeError: Error #1034: Type Coercion failed: cannot convert flash.display::Loader@13835e1 to

                    mx.core.IUIComponent.

                    addChild(loader.content) => gives an error:

                    TypeError: Error #1034: Type Coercion failed: cannot convert _brow_mx_core_FlexModuleFactory@11d4ac1 to mx.core.IUIComponent.

                    I've spotted an interesting thing. If I do:

                    var rect:Shape = new Shape();
                    rect.graphics.beginFill(0xFFFFFF);
                    rect.graphics.drawRect(0, 0, 100, 100);
                    uicomp.addChild(rect);
                    mainCanvas.addChild(uicomp);

                    it's being displayed OK, but if I make the shape as a mask of what's loaded:

                    loader.mask=rect;

                    it's simple not there and NO errors.
                    I'm digging all the Security docs I can put my hands on and keep my fingers crossed.
                    • 7. Re: Cross-domain loading module to local application
                      Bzyku@GB Level 1
                      The think is that loaded swf is a MODULE, not some movie.
                      • 8. Re: Cross-domain loading module to local application
                        buabco Level 1
                        I haven't been able to find the mx_core_FlexModuleFactory in the documentation, is this a class you made yourself? if so, which is the inheritance of it?
                        • 9. Re: Cross-domain loading module to local application
                          Bzyku@GB Level 1
                          :) I wish. That's the sting of an error. It's actually about IFlexModuleFactory. The IFlexModuleFactory interface represents the contract expected for bootstrapping Flex applications and dynamically loaded modules.

                          http://livedocs.adobe.com/flex/201/langref/mx/core/IFlexModuleFactory.html

                          It goes with Interface IModuleInfo.

                          http://livedocs.adobe.com/flex/201/langref/mx/modules/IModuleInfo.html

                          I just wish to know more...
                          • 10. Re: Cross-domain loading module to local application
                            buabco Level 1
                            Uff... never seen that before :) but here are some tips:

                            This is a SystemManager Object. The SystemManager Object is not a Display Object so there is no way you'll be able to load it into the display list. Since it's a Factory object you need to call the create method in order to have the actual class you are loading. (Whitch might be a displayObject I guess).

                            Since you are trying to load a display object the most simple way will be for you to turn this swf into a Application object instead of a Factory object.
                            • 11. Re: Cross-domain loading module to local application
                              Bzyku@GB Level 1
                              I’ve made fief changes:
                              Module:
                              ==================
                              <?xml version="1.0" encoding="utf-8"?>
                              <mx:Module xmlns:mx=" http://www.adobe.com/2006/mxml>
                              <mx:Script>
                              <![CDATA[
                              import mx.controls.Alert;
                              Security.allowDomain("*");
                              Alert.show("aqq") // Displays even before “addChild”
                              ]]>
                              </mx:Script>
                              <mx:HBox >
                              <mx:Text text="test text 1"/>
                              <mx:Text text="test text 2"/>
                              </mx:HBox>
                              </mx:Module>
                              ==================

                              In the App:

                              1)

                              To monitor sandbox <=> securitydomain I’ve added:

                              <mx:Text text="Sandbox Type: {String(Security.sandboxType)}"/>

                              2)

                              loader.contentLoaderInfo.addEventListener(Event.INIT, hInit);
                              ...
                              private function hInit(event:Event):void{
                              Alert.show("loaded swf has called 'Security.allowDomain'")
                              // works just perfect regardless where is the file loaded from (local / serv)
                              }

                              3)

                              private function modComplete(event:Event):void{
                              Alert.show("ch: " + loader.contentLoaderInfo.childAllowsParent.toString()+"\np: " + loader.contentLoaderInfo.parentAllowsChild.toString() + "\nsd: " + loader.contentLoaderInfo.sameDomain.toString());
                              // shows: that both files allow to ~ exchange data

                              Alert.show(String(event.target.loader.content))
                              // shows: [object _brow_mx_core_FlexModuleFactory]

                              addChild(event.target.loader.content.factory.create())
                              // gives: ReferenceError: Error #1069: Property factory not found on _brow_mx_core_FlexModuleFactory and there is no default value.

                              // if we try:
                              addChild(loader.content.factory.create())
                              // Flex will not even allow to compile saying:
                              // 1119: Access of possibly undefined property factory through a reference with static type flash.display:DisplayObject.


                              }

                              4)

                              On another approach I CAN :) !!! get it loaded and displayed BUT ONLY within the same domain, where:

                              private var modInfo:IModuleInfo;
                              private function handleGoEvent():void {
                              modInfo = ModuleManager.getModule(go);
                              modInfo.addEventListener(ModuleEvent.READY, goMod);
                              modInfo.addEventListener(ModuleEvent.ERROR, def);
                              modInfo.load(ApplicationDomain.currentDomain);
                              }
                              private function goMod(event:Event):void {
                              var a = modInfo.factory.create()
                              addChild(a)
                              }

                              It’s 6am. My last battle duration time: 24h... War duration time: aprox. 1 week... Heads UP! :)
                              • 12. Re: Cross-domain loading module to local application
                                mikeSibbald
                                Check it it is running on different domains.

                                sample:
                                http://labs.flexcoders.nl/samples/ModuleSamples/

                                code:
                                http://labs.flexcoders.nl/samples/ModuleSamples/srcview/index.html

                                The only thing I didn't get to work is that if I try to test it on my computer and load the remote module. It's not working and the sandboxtype is set to "localTrusted" (on-line it's "remote"). But if I place it on my server it is working. So if anybody can tell me how I can test it locally?(with remote modules)

                                ***********************************************************************************
                                This post can be outdated and that remote module may be deleted. But the code still works.
                                • 13. Re: Cross-domain loading module to local application
                                  Bzyku@GB Level 1
                                  That's the thing. If Security.sandboxType of both is not the same module simply doesn't work. As I understand the sandbox is a securityDomain... or something. I will dig deeper this subject.
                                  • 15. Re: Cross-domain loading module to local application
                                    buabco Level 1
                                    well in that case the correct configuration on the FLASH advanced preferences should solve the problem, you have to add the application as a trusted zone. This will make everithing work correctly.

                                    As an alternative, make sure the module, also has allowed the domain as a trusted zone, you must do this in both files, the module one and the one loading the module.

                                    In my experience though, have never been able to make the trust relation work without configuring the trust zones in FLASH PLAYER PROPERTIES, in fact even with everything ok, I've been having problems with event dispatching, it seems they can't travel correctly between zones.
                                    • 16. Re: Cross-domain loading module to local application
                                      murugast
                                      Yes i faced same porblem in my application , after a long fight i finally decided changed the CFG file to trust my folder , and its works . Please try to get an way to change configuration file for flash player dynamically

                                      Thanks
                                      • 18. Re: Cross-domain loading module to local application
                                        buabco Level 1
                                        I've read in some of the documentation that you can setup the trusted zone through the use of an installer that change this parameters in windows registry.... don't know where in the registry though.
                                        • 19. Re: Cross-domain loading module to local application
                                          Bzyku@GB Level 1
                                          I’m sorry gentlemen for keeping you waiting for so long. At this stage I can say there are three/four approaches to the subject:

                                          1) public var loader:Loader = new Loader();

                                          private function loadmod():void {
                                          var request:URLRequest = new URLRequest(go);
                                          var loaderContext:LoaderContext = new LoaderContext();
                                          loaderContext.applicationDomain = ApplicationDomain.currentDomain;
                                          loaderContext.checkPolicyFile = true;
                                          //loaderContext.securityDomain = Security.currentDomain;
                                          //LOCAL SWF files may not set LoaderContext.securityDomain
                                          loader.contentLoaderInfo.addEventListener(Event.COMPLETE, modComplete);
                                          loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, def)
                                          loader.load(request, loaderContext);
                                          }
                                          private function modComplete(event:Event):void{
                                          addChild(event.target.loader.content.factory.create())
                                          }

                                          2) private var modInfo:IModuleInfo;

                                          private function loadmod():void {
                                          modInfo = ModuleManager.getModule(go);
                                          modInfo.addEventListener(ModuleEvent.READY, goMod);
                                          modInfo.addEventListener(ModuleEvent.ERROR, def);
                                          modInfo.load(ApplicationDomain.currentDomain);
                                          }
                                          private function goMod(event:Event):void {
                                          var a = modInfo.factory.create()
                                          addChild(a)
                                          }

                                          3) public var moduleLoader:ModuleLoader = new ModuleLoader();

                                          private function loadmod ():void {
                                          moduleLoader.addEventListener(ModuleEvent.ERROR, this.modError);
                                          moduleLoader.addEventListener(ModuleEvent.READY, this.modComplete);
                                          moduleLoader.url = go;
                                          moduleLoader.loadModule();
                                          }
                                          private function modComplete(event:ModuleEvent = null):void{
                                          this.main_container.addChild(moduleLoader);
                                          }

                                          The 2nd and 3rd can work under one domain. The first one seemed to me be the one gives me the most control over what I download, but only allows loadee’s scripts to work (which in my case is not the think I’m looking for)

                                          Tricky think about my approach is that I work with desktop loader and net based loadee. As the docs. say – ALL net content is loaded to REMOTE sandboxes. There is no way of making local file part of REMOTE. We have three different other ones for it.

                                          I’m thinking of the 4th way out of here:

                                          4)
                                          The local application with <SWFLoader> loads net application which loads net modules… but it also ends up with sandbox violation :(

                                          Thank you all for your time and great ideas! I do appreciate.