3 Replies Latest reply on Jul 1, 2010 1:37 PM by Flex harUI

    Problem when sharing singletons with external SWF

    stephan1977

      The documentation at http://livedocs.adobe.com/flex/3/html/help.html?content=18_Client_System_Environment_5.htm l states under "Usage C":

       

      ... This technique lets loaded modules share the loader's singleton objects and static class members. ...

       

      var appDomainC:ApplicationDomain = new ApplicationDomain(ApplicationDomain.currentDomain);

       

      var contextC:LoaderContext = new LoaderContext(false, appDomainC);
      var loaderC:Loader = new Loader();
      loaderC.load(new URLRequest("module3.swf"), contextC);

       

      (emphasis added)

       

      The AIR app I'm building needs to be able to share data stored in a singleton with SWF modules that are loaded at runtime. I've tried implementing all 3 usages mentioned in the article linked to above, but none of them give me the desired results. What I'm getting is two unique instances of the singleton being created -- one instance in the AIR app, and a different instance in the loaded SWF -- as if each singleton instance exists within its own sandbox.

       

      For example, my AIR app loads an external SWF at runtime using the following code:

       

      var domain:String = "http://my.server.com";
      Security.loadPolicyFile(domain + "/crossdomain.xml");

      var loader:Loader = new Loader();
      loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:Event) { trace('Security error!'); } );
      var context:LoaderContext = new LoaderContext(false, new
      ApplicationDomain(ApplicationDomain.currentDomain));
      loader.load(new URLRequest(domain + '/myExternal.swf'), context);

      addChild(loader);

       

      The external SWF loads as expected. No problems so far.

      This is my singleton:

       

      public class MySingleton extends  EventDispatcher
      {

           private static var _instance:MySingleton;

           public var uid:Number;


      public function MySingleton()
      {
           uid =
      Math.round(Math.random() * 100000));

      }


           public static function getInstance():MySingleton
           {

                if (_instance == null)
                {
                     _instance = new
      MySingleton();
                }


                return _instance;
           }

      }

       

      Here's what happens when I get the instance of MySingleton in the AIR app (loader):

       

      var myInstance:MySingleton = MySingleton.getInstance();

      trace(myInstance.uid); // Let's say this outputs 87342

       

      However, in the loaded external SWF when I attempt to get the instance of MySingleton, I get the following:

       

      var  myInstance:MySingleton = MySingleton.getInstance();

      trace(myInstance.uid);  // 5221 (should be 87342, same as the loader's instance of MySingleton)

       

      According to the documentation, it clearly states that my "loaded modules" should "share the loader's singleton objects". It's obviously not sharing the loader's singleton object. Am I missing something, or is the Flex documentation incorrect?

       

      I should add that I have no trouble sharing singletons if I package the external SWF with the AIR app and then load it at runtime. This only happens when I download and load an external SWF at runtime.

       

      Any help is greatly appreciated.

        • 1. Re: Problem when sharing singletons with external SWF
          Flex harUI Adobe Employee

          Looks like you are not using ModuleManager.  If you were, I would expect

          other errors.

           

          SWFs from the internet are insecure as far as AIR is concerned so they will

          be loaded into separate security sandboxes.

           

          You can get the SWF as a bytearray via URLLoader and use loadBytes to get

          around that, but then the SWF is not in the internet context.

          • 2. Re: Problem when sharing singletons with external SWF
            stephan1977 Level 1

            Correct, I'm not using ModuleManager. Would using that allow me to place the loaded SWFs into the same security sandbox as the AIR app?

             

            As tempting as loadBytes sounds, it opens up the AIR app to code injection, so it's not an option.

             

            Here's what I'm trying to accomplish:

             

            1) The AIR app needs to run on a client device (PC, Mac, Tablet, etc.)

            2) The app needs the ability to load modules (external SWFs) that may be developed by a thrid party. This means that the modules must be able to be loaded into the AIR app without needing to recompile or repackage the app. Third-party developers would interact with the app using an API of sorts, while the AIR app's code remains proprietary.

            3) The SWF modules must reside on a web server

            4) The SWF modules must be able to access singletons used by the AIR app.

             

            If anyone can recommend a good solution for this, I will buy you lunch

            • 3. Re: Problem when sharing singletons with external SWF
              Flex harUI Adobe Employee

              Flash/AIR security is all-or-nothing.  If you allow an untrusted SWF to

              access a Singleton, the untrusted SWF can scan the public properties and

              call public methods in the Singleton, access other sub-objects referenced by

              the Singleton, examine their public properties and methods, and potentially

              mess with the app or steal important data.

               

              So, if you have plans to trust the SWFs that much, loadBytes is not that

              much further along the danger path.

               

              Because of your requirement #3, the SWFs will be untrusted and therefore

              cannot share class definitions so a Singleton in the main App will not be

              the same Singleton in the SWF.  The loadbytes trick is essentially copying

              the SWF into the main app's memory.  By doing so the SWF is no longer

              considered to be from the domain it was served from and may have issues

              accessing the server it came from which can be both a good thing and a bad

              thing.

               

              ModuleManager will not help.  I was just making sure you weren't using

              Modules as we know them in Flex.

               

              The recommended way of dealing with your situation is to use the "Marshall

              Plan".  You can pass references to Singletons across the boundary and make

              some assumptions and watch for changes and marshall those changes to the

              Singleton on the other side.  Basically, keeping two Singletons in sync by

              sending messages across the sharedEvents dispatcher.

               

              There are more details on the Marshall Plan on my blog and on the Adobe

              Opensource site.

               

              --

              Alex Harui

              Flex SDK Team

              Adobe System, Inc.

              http://blogs.adobe.com/aharui