3

My Flex app uses local SharedObjects. There have been incidents of the Flash cookie getting corrupt, for example, due to a plugin crash. In this case SharedObjects.getLocal will throw an exception (#2006).

My client wants the app to recover gracefully: if the cookie is corrupt, I should replace it with an empty one.

The problem is, if SharedObject.getLocal doesn't return an instance of SharedObject, I've nothing to call clear() on.

How can I delete or replace such a cookie?

Many thanks!

EDIT:

There isn't much code to show - I access the local cookie, and I can easily catch the exception. But how can I create a fresh shared object at the same location once I caught the exception?

 try {
     localStorage = SharedObject.getLocal("heywoodsApp");
 } catch (err:Error) {
       // what do I do here?
 }

The error is easily reproduced by damaging the binary content of a Flash cookie with an editor.

Thomas Heywood
  • 903
  • 2
  • 9
  • 18
  • +1 for the question; but I haven't the foggiest idea what the solution is. What is your app doing that plugin crashes are commonplace? Can you share code? Can you share the full exception? I wonder if you could use an uncaughtException event to create a brand new SharedObject? – JeffryHouser Mar 29 '12 at 13:42
  • The app is a frontend to monitor and analyze business data for a company's internal use. Crashes aren't really commonplace, but there has been a report of a corrupt cookie following a Windows crash, and as the users aren't technically proficient enough to clean up their Flash cookies, the client has made a request for feature (i.e. I get more money if I do it) that the app does it for them if the incident repeats. I'll put the code in the original comment. – Thomas Heywood Mar 29 '12 at 14:24
  • @ThomasHeywood have you solved this issue somehow? I don't see any good answer here :/ – mizi_sk Jun 20 '14 at 07:36
  • No, we let it slide and documented the problem. – Thomas Heywood Jun 23 '14 at 13:38

2 Answers2

0

You need to be testing for the length of SharedObject and recreate if it's 0. Also, always use flush to write to the object. Here's a function we use to count the number of times our software is launched:

private function usageNumber():void {
    usage = SharedObject.getLocal("usage");

    if (usage.size > 0) {
       var usageStr:String = usage.data.usage;      
       var usageNum:Number = parseInt(usageStr);

       usageNum = usageNum + 1; 
       usageStr = usageNum.toString();

       usage.data.usage = usageStr;
       usage.flush();

       countService.send();

    } else {

       usage.data.usage = "1";
       usage.flush();

       countService.send();
    }

}

It's important to note that if the object isn't available it will automatically be recreated. That's the confusing part about SharedObjects.

All we're doing is declaring the variable globally:

public var usage:SharedObject;

And then calling it in the init() function:

usage = SharedObject.getLocal("usage");

If it's not present, then it gets created.

Brandon
  • 1,399
  • 4
  • 20
  • 37
  • Thanks for the great code snippet. Unfortunately, it doesn't solve my problem. I never get an instance of SharedObject (the variable representing it gets assigned null), so there's nothing to call length() (or flush(), etc.) on. – Thomas Heywood Mar 29 '12 at 13:55
  • okay so you are getting an exception while accessing the shared object ? – Triode Mar 29 '12 at 14:05
  • Yes. I call SharedObject.getLocal("myStorage"), which throws RangeError, which is expected behavior when getLocal finds a Flash cookie but can't retrieve it. So I don't get an instance of SharedObject to work with. – Thomas Heywood Mar 29 '12 at 14:32
  • Updated my answer with how we initialize. Nothing I've found would suggest a range error would ever occur. Also, I should point out that when I was testing I would use clear() to ensure the objects were fresh. – Brandon Mar 29 '12 at 18:03
  • @ThomasHeywood Why not check for null and then recreate if null? Does that not work for you? Obviously, you would have checked that but I had to ask. – Brandon Apr 01 '12 at 04:48
  • @Brandon I can check for null, but I'm not sure how to recreate it. If I call getLocal("location"), I get null again, not an empty cookie. And I can't delete the old one because I don't have an instance of cookie to call clear() on. I could put it in a different location, I suppose, but then I'd have the problem of remembering where it is. It's a weird little problem :) – Thomas Heywood Apr 02 '12 at 14:30
0

I'm not really sure why you'd be getting a range error - esp if you report that can find it. My only guess for something like this is there is a possibility of crossing boundries with respect to the cross-domain policy. Assuming IT has control over where the server is hosted, if the sub-domain ever changed or even access type (from standard to https) this can cause issues especially if the application is ongoing (having been through several releases). I would find it rather hard to believe that you are trying to retrieve a named SO that has already been named by another application - essentially a name collision. In this regard many of us still uses the reverse-dns style naming convention even on these things.

If you can catch the error it should be relatively trivial to recover from: - just declare the variable outside the scope of the try so it's accessible to catch as well. [edit]: Since it's a static method, you may need to create a postfix to essentially start over with a new identifier.

var mySO:SharedObject;
....
catch(e:Error)
{
      mySO = SharedObject.getLocal('my.reversedns.so_name_temp_name');
      //might want to dispatch an error event or rethrow a specific exception
      //to alert the user their "preferences" were reset.
}
Mike Petty
  • 949
  • 6
  • 6