Showing posts with label Flash. Show all posts
Showing posts with label Flash. Show all posts

Wednesday, June 12, 2013

Annoying differences in how browsers handle Flash movement

Everyone hates the differences between the different major browsers out there. Not to mention the different versions of those browsers. Supporting all of them is a pain in the ass. And here is just one more reason:

Action: Take a Flash Object element on a page, and then move it someplace else (append the element to a different parent node)
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var newCont = document.createElement("div");
var swfOb = document.getElementById("swf-object-element"); //already exists on the page
print(swfOb.lastChild); //<param name="flashvars" value="name=value" />
swfOb.lastChild.value = "name=value2";
document.body.appendChild(newCont);
newCont.appendChild(swfOb);
swfOb = document.getElementById("swf-object-element");
var swfExternalFunction = e.setCorner;
e.setCorner("tr"); //(attempts to) move the corner to the top right (starts in the bottom right)
//In NO browser, does that call actually WORK
//...wait 100ms
swfExternalFunction == null //false IE,FF;  true Chrome
swfExternalFunction == e.setCorner //false!! all
e.setCorner("tr") //Error! IE;  works in FF,Chrome
swfOb.lastChild //<param name="flashvars" value="name=value" />  FF!! ; <param name="flashvars" value="name=value2" />  Chrome, IE (sometimes)

Consequences:
SWF is in the bottom right. The call to "setCorner" does nothing. All browsers. 

Because::
IE: Will not let you call a Flash External Interface function on a moved element. BUT!!!! the function will still exist on the element. Buggars. And I couldn't get a straight answer from IE when modifying the Object Element before/after the location change. IE seems to have some sort of race condition going on. Sometimes it does, sometimes it doesn't, and sometimes the buggar doesn't even allow ANY External Interface any more. More hate for IE. Tested in IE 10, _but_ in IE8 standards mode. I had similar problems in actual IE8 - I could not get consistant results. I need to create better tests for IE, but that's time I don't have.

FF: FF re-inits the SWF, just like Chrome. Any changes to the "old" element will NOT be reflected in the new one. Whats WORSE is that the reference to the element's External Interface function STILL EXIST (on the Object) while the "new" object is being initialized, BUT!!! those functions STILL REFERENCE THE "OLD" OBJECT!! Talk about craziness... 
But wait, I'm not done. Firefox completely IGNORES changes to the object element in the mean time. So you can't, say, change the FlashVars and have them be updated in the "new" Object. Booooooo FF

Chrome: The best of the three. I'd still prefer that the SWF not be re-initialized, but oh well. At LEAST Chrome doesn't lie to you and expose functions that are out of date or don't exist. As well, it recognizes changes to the Object Element and on the "new" Object, those changes are present.



RESULT:

The only sure fire way to move a SWF element is to just set a timeout for after the move, and re-init it then, knowing that all your previous changes are gone. Which means you have to keep state externally, or get the current state from the Object before you move it. There's NO WAY to check to verify that it's "ok yet" to make changes after you've moved it, so you just have to set a long timeout and pray that it's long enough (iff you don't want to make browser specific code, that is).

Thursday, May 23, 2013

Security Sandbox, Flash, Data URLS, and Chrome browser


Recently I was creating a test page (HTML) for injecting HTML from a TextArea into an iframe. Of course I was doing more than just that, but we don't need to go into it. I didn't want the Iframe to be on the same domain as the page (ie.  I didn't want the injected HTML/JS to have access to the parent frame, the parent frame's DOM Storage, nor the parent frame's cookies). I of course -could- have just loaded in a random subdomain and injected it using innerHTML of the HTMLElement node, this would fix my problem, but it would be nice not to do that. So I chose to use Data URLs.
Big mistake.
Interestingly, the "domain" of a Data URL is an empty string. Which no matter what, is different than the parent frame - even running a local system file, the domain is "localhost", which is obviously not equal to the empty string and therefore cannot talk to each other. I tried to just set cookies or DOM Storage from this "" (empty string) domain, but Chrome throws Exceptions. I tried setting the document.domain of the parent frame to "", but again, got exceptions. Great, actually - all is working well, as it's supposed to, given Chrome's sandboxing. Just checking.
My real problem started when I mixed Flash into the equation.
The parent frame (either local or from web) can insert a Flash object which has access to the page scope. So from within the Flash, I can call functions which exist on the web page. This is critical to certain features of my SWF. There are restrictions to this too, but I'm fully aware of them and used to it - it all makes sense anyways, in regards to cross scripting and security.  
However, the anomaly which sparked my interest was the fact that the Flash object in the "" domain simply cannot get access to the page scope, no matter how much the page and the swf want to talk. All I can figure is that Chrome sees the domain as "" and Flash sees the domain as something else, which would impose cross scripting security. But worse than that, it seems that Flash sees the "" domain as LOCAL (non-net) **, whereas Chrome sees it as just another domain.
** this was something I figured out later and made all the problems make sense. I just thought I was dealing with some bug or oversight, but it turns out I'm trying to hack my way through the most important Flash security.

This means that there is simply no way to enable page scope access for the SWF inside the Data URL page without going to the global Flash settings and allowing ALL domains here http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html . 
Which most likely is something people aren't so willing to do. As a matter of fact, there's actually some bug there at the settings page when using both the "System" Flash settings AND the settings in the link there. Which means that devs like me who actually use the development features in that panel might have some problems. 

This got me thinking about ways around this. As I said above at the **, I didn't realize yet I was dealing with intentional security. After all, I don't need complex communication - just some small strings. Passing TO the SWF is as always, super easy. But passing information FROM the SWF is not. Within the SWF, without ExternalInterface, one is limited to app settings and network connections. I tried changing app settings, things like name, id, width/height, dispatching events, etc etc, which I knew wouldn't work and sure enough, they didn't. Then I tried from the other directing, taking the DOM object, which is apparently called an "NPObject" (which is just a wrapper around Flash, meaning "native plugin object" I imagine, restricting access to the object). On pages where the SWF has access to the scope already, you can read and write attributes on it, but sure enough, didn't have any luck within the Data URL page. I tried tricks like a javascript url from the SWF, but that was blocked. I tried the hash message method, but again, didn't work - I think due to the Data URL. I did have one idea which seems rather exotic - since Flash is treating the app as local (if indeed it is), then I could change the page location to another Data URL which loads the SWF as a DataURL. This second SWF would appear to be from the same domain as the page and such get page access. Two big "IF"s with this - can you even use a Data URL for a Flash object, and even then, would it really allow page access? Maybe one day I'll try it.

UPDATE: I tried it. Didn't work. In modern versions of Flash they stopped the ability (as in, you used to be able to do it) to use Data URIs. It seems like a major security hole if it did work. I'm just a year or two too late. Drat.