External Javascript Interface on Flash Player not working on CDN (Cloudfront) - javascript

I have a flash player with an external javascript interface: reloadData() I'm calling that function via Javascript when editing information on the page - basically to keep data on the page and in the player in synch.
The reloadData() function works fine when the player is hosted locally. When we move it to the CDN (Amazon Cloudfront), the player loads successfully, but the external javascript interface no longer works - console.log(player) reveals the following:
<object type=​"application/​x-shockwave-flash" data=​"[our_cloudfront_url].swf" width=​"920" height=​"404" id=​"player" style=​"visibility:​ visible;​ ">​
Uncaught TypeError: Object #<an HTMLObjectElement> has no method 'reloadData'
I know there are a lot of things that behave differently when working with items on a CDN, but I'm wondering if anyone has experienced a similar problem and figured out a fix.
Oh, yeah...we're using a CNAME to point to the cloudfront distribution (buildid.ourdomain.net => distributionid.cloudfront.net)

Well, we figured this one out. Two things are necessary:
On the page when embedding the swf: allowScriptAccess="always"
In the swf itself: System.security.allowDomain("ourdomain.com")
I guess this is sort of obvious, but I figured I'd post it here in case some other poor lost soul such as myself is having the same problem.

Related

how do you allow javascript communications with Flex/Flash/Actionscript

Well here's a problem.
I've got a website with large javascript backend. This backend talks to a server over a socket with a socket bridge using http://blog.deconcept.com/swfobject/
The socket "bridge" is a Flex/Flash .swf application/executable/plugin/thing for which the source is missing.
I've got to change it.
More facts:
file appExePluginThing.swf
appExePluginThing.swf Macromedia Flash data (compressed), version 9
I've used https://www.free-decompiler.com/flash/ to decompile the .swf file and I think I've sorted out what's the original code vs the libraries and things Flash/Flex built into it.
I've used FDT (the free version) to rebuild the decompiled code into MYappExePluginThing.swf so I can run it with the javascript code and see what happens.
I'm here because what happens isn't good. Basically, my javascript code (MYjavascript.js) gets to the point where it does
window.log("init()");
var so = new SWFObject("flash/MYappExePluginThing.swf"", socketObjectId, "0", "0", "9", "#FFFFFF");
window.log("init() created MYappExecPluginThing!!!");
so.addParam("allowScriptAccess", "always");
log("init() added Param!!");
so.write(elId);
log("init() wrote!");
IE9's console (yeah, you read that right) shows
init()
created MYappExecPluginThing!!!
init() added Param!!
init() wrote!
but none of the debugging i've got in MYappExePluginThing.as displays and nothing else happens.
I'm trying to figure out what I've screwed up/what's going on? Is MYappExePluginThing.as running? Is it waiting on something? Did it fail? Why aren't the log messages in MYappExePluginThing.as showing up?
The first most obvious thing is I'm using FDT which, I suspect, was not used to build the original. Is there some kind of magic "build javascript accessible swf thing" in FlashBuilder or some other IDE?
First noteworthy thing I find is:
file MYappExePluginThing.swf
MYappExePluginThing.swf Macromedia Flash data (compressed), version 14
I'm using Flex 4.6 which, for all I know, may have a completely different mechanism for allowing javascript communication than was used in appExePluginThing.swf
Does anyone know if that's true?
For example, when FDT runs this thing (I can compile but FDT does not create a .swf unless i run it) I get a warning in the following method:
private function init() : void
{
Log.log("console.log", "MYappExePluginThing init()");
//var initCallback:String = Application.application.parameters.initCallback?Application.application.parameters.initCallback:"MYjavascript.MYappExePluginThing_init";
var initCallback:String = FlexGlobals.topLevelApplication.parameters.initCallback?FlexGlobals.topLevelApplication.parameters.initCallback:"MYjavascript.MYappExePluginThing_init";
try
{
ExternalInterface.addCallback("method1Callback",method1);
ExternalInterface.addCallback("method2Callback",method2);
ExternalInterface.call(initCallback);
}
catch(err:Error)
{
Log.log("console.log", "MYappExePluginThing init() ERROR err="+err);
}
}
I got a warning that Application.application was deprecated and I should change:
var initCallback:String = Application.application.parameters.initCallback?Application.application.parameters.initCallback:"MYjavascript.MYappExePluginThing_init";
to:
var initCallback:String = FlexGlobals.topLevelApplication.parameters.initCallback?FlexGlobals.topLevelApplication.parameters.initCallback:"MYjavascript.MYappExePluginThing_init";
which I did but which had no effect on making the thing work.
(FYI Log.log() is something I added:
public class Log{
public static function log(dest:String, mssg:String):void{
if(ExternalInterface.available){
try{
ExternalInterface.call(dest, mssg);
}
catch(se:SecurityError){
}
catch(e:Error){
}
}
trace(mssg);
}
}
)
Additionally, in MYjavascript.js MYappExePluginThing_init looks like this:
this.MYappExePluginThing_init = function () {
log("MYjavascript.js - MYappExePluginThing_init:");
};
Its supposed to be executed when MYappExePluginThing finishes initializing itself.
Except its not. The message is NOT displaying on the console.
Unfortunately, I cannot find any references explaining how you allow javascript communication in Flex 4.6 so I can check if I've got this structured correctly.
Is it a built in kind of thing all Flex/Flash apps can do? Is my swf getting accessed? Is it having some kind of error? Is it unable to communicate back to my javascript?
Does anyone have any links to references?
If this was YOUR problem, what would you do next?
(Not a full solution but I ran out of room in the comment section.)
To answer your basic question, there's nothing special you should need to do to allow AS3-to-JS communication beyond what you've shown. However, you may have sandbox security issues on localhost; to avoid problems, set your SWFs as local-trusted (right-click Flash Player > Global Settings > Advanced > Trusted Location Settings). I'm guessing this not your problem, though, because you'd normally get a sandbox violation error.
More likely IMO is that something is broken due to decompilation and recompilation. SWFs aren't meant to do that, it's basically a hack made mostly possible due to SWF being an open format.
What I suggest is that you debug your running SWF. Using break-points and stepping through the code you should be able to narrow down where things are going wrong. You can also more easily see any errors your SWF is throwing.
Not really an answer, but an idea to get you started is to start logging everything on the Flash side to see where the breakage is.
Since you're using IE, I recommend getting the Debug flash player, installing it, then running Vizzy along side to show your traces.
Should give you a good idea of where the app is breaking down.
Vizzy
Debug Player

jQuery on MTurk, why does Chrome report "Unsafe JavaScript attempt to access frame with URL"?

I'm doing a couple of things with jQuery in an MTurk HIT, and I'm guessing one of these is the culprit. I have no need to access the surrounding document from the iframe, so if I am, I'd like to know where that's happening and how to stop it!
Otherwise, MTurk may be doing something incorrect (they use the 5-character token & to separate URL arguments in the iframe URL, for example, so they DEFINITELY do incorrect things).
Here are the snippets that might be causing the problem. All of this is from within an iframe that's embedded in the MTurk HIT** (and related) page(s):
I'm embedding my JS in a $(window).load(). As I understand it, I need to use this instead of $(document).ready() because the latter won't wait for my iframe to load. Please correct me if I'm wrong.
I'm also running a RegExp.exec on window.location.href to extract the workerId.
I apologize in advance if this is a duplicate. Indeed - after writing this, SO seems to have a made a good guess at this: Debugging "unsafe javascript attempt to access frame with URL ... ". I'll answer this question if I figure it out before you do.
It'd be great to get a good high-level reference on where to learn about this kind of thing. It doesn't fit naturally into any topic that I know - maybe learn about cross-site scripting so I can avoid it?
** If you don't know, an MTurk HIT is the unit of work for folks doing tasks on MTurk. You can see what they look like pretty quick if you navigate to http://mturk.com and view a HIT.
I've traced the code to the following chunk run within jquery from the inject.js file:
try {
isHiddenIFrame = !isTopWindow && window.frameElement && window.frameElement.style.display === "none";
} catch(e) {}
I had a similar issue running jQuery in MechanicalTurk through Chrome.
The solution for me was to download the jQuery JS files I wanted, then upload them to the secure amazon S3 service.
Then, in my HIT, I called the .js files at their new home at https://s3.amazonaws.com.
Tips on how to make code 'secure' by chrome's standards are here:
http://developer.chrome.com/extensions/contentSecurityPolicy.html
This isn't a direct answer to your question, but our lab has been successful at circumventing (read hack) this problem by asking workers click on a button inside the iframe that opens a separate pop-up window. Within the pop-up window, you're free to use jQuery and any other standard JS resources you want without triggering any of AMT's security alarms. This method has the added benefit of allowing workers to view your task in a full-sized browser window instead of AMT's tiny embedded iframes.

Javascript throws error when trying to send var to AS3 ExternalInterface

I know there have been tons of questions about this topic already but none of them have solved my issue, perhaps I am just missing something.
Anyways, here is the deal. I have a happy little html5 game that plays some audio and sound affects etc and it works great in every browser that supports html5. However, those that don't require a flash fallback. No big deal right? Apparently not… I've made a small swf that should accept the mp3 url from JS and then get the mp3 and play it. I have to use this way as there are a lot of audio files and I would like to try and avoid making a swf file for each one.
Here is the AS - I'm using the ExternalInterface to receive the variable from js.
import flash.external.*;
ExternalInterface.addCallback("callFlash", playSound);
function playSound(file:String):void {
var s:Sound = new Sound();
s.load(new URLRequest(file));
s.play();
}
And then my JS to pass the variable:
var flash = $('#fbplayer')[0];
console.log(flash); //returns flash object so jquery is not the issue
flash.callFlash(fallSource);
So theoretically everything should work fine (if I understand ExternalInterface correctly). However, the following error is thrown:
TypeError: flash.callFlash is not a function
flash.callFlash(fallSource);
I can't seem to find where the issue was.
I'm open to any answers or even a completely different way of doing this.
As long as it works as this is holding up the delivery of the project :C
Thanks!
I know this is really old, but I've never had success finding my flash objects properly with jquery. It's better to go with a getElementById. Also, one other crazy thing I ran into with some modern browsers just a couple months ago is that I actually needed to tell flash to wait a frame after initializing any callbacks via ExternalInterface.

Uncaught TypeError: Cannot call method 'each' of undefined

I have this error while trying to run mediaelement player.
The error is reported at mediaelement-and-player.min.js:44.
Edit: My apologies, I posted this from the mediaelementjs.com Support website.
I was trying to use mediaelement.js to play audio on my website.
Edit 8/2: The interesting thing is that when i load the full mediaelement-and-player.js instead of the minified version, it works fine.
I just dealt with this same issue while trying to use the Drupal module, http://drupal.org/project/mediaelement.
Turns out that a core Drupal javascript file, drupal.js, was calling jQuery.noConflict() which removes the $ variable from being defined in the global scope, hence bringing this bug in mediaelement-and-player.js to light.
This was reported in the issue queue for the mediaelement project and it looks like the fix just got committed: https://github.com/johndyer/mediaelement/pull/570
Most likely you have not loaded the jquery library into your script.
You have to reference the library (a js file) from within the header of your page via url. The url can point to a copy pf jquery you keep local or to a public site.

SoundManager2 SWF Load Issue

Trying to load Soundmanager2's SWF file from our CDN. I assume I'm running into cross domain flash issues. has anybody done this? it is even possible?
here's what I'm trying...
var allowxdomainscripting = true;
var xdomain = "*";
soundManager.url = 'http://cdn.mycompany.com/inc/soundmanager2.swf';
there's a very obscure reference to this in the documentation, but it's pretty vague...
http://www.schillmania.com/projects/soundmanager2/doc/generated/src/SoundManager2_AS3.html
any help is appreciated.
I ran into this as well at one point. SoundManager2 now comes with cross-domain versions of the swf files.
They are zipped up in swf/soundmanager2_flash_xdomain.zip
https://github.com/scottschiller/SoundManager2/tree/master/swf
Simply unzip and replace with the standard .swf files provided with SoundManager2 and your problem should go away.
THANK YOU VERY MUCH!
I stumbled upon this answer by total chance after wasting a couple of hours trying to get SM2 SWF embed to work.
I'm going to "revive" this to add a few keywords so Google indexes this answer... Maybe the next person trying to embed SoundManager2 SWF in a cross-domain environment gets it done a little quicker than I did :)
The error I was getting upon flash initialization was: Error calling method on NPObject
On the JS side, this was the code that broke everything:
// attempt to talk to Flash
flash._externalInterfaceTest(false); <- KABOOM!
NPObject errors might have many meanings, but more often than not (in our environment) it means: You're trying to call the ExternalInterface through JS on a flash movie hosted on a different domain.
After a while I popped open SoundManager2 ActionScript 3 code and saw this:
public var allow_xdomain_scripting:Boolean = false;
public var xdomain:String = "*";
[... other stuff ...]
if (allow_xdomain_scripting && xdomain) {
Security.allowDomain(xdomain);
version_as += ' - cross-domain enabled';
}
Of course that means that the movie that you might be using (no matter if it's debug or not) will not be accessible from a different domain (a CDN, or whatever).
The solution was –as stated in #amlutz160's answer– to use the files contained in swf/soundmanager2_flash_xdomain.zip, which are compiled with allow_xdomain_scripting = true.
Posting this is quite embarrassing, and the solution is obvious, but I lost quite a bit of time with this and AFAIK the contents of that mysterious zip file are not documented anywhere (I found a tangential mention on SM2 forums).
PS: I'm forwarding this answer to Scott Schiller so maybe he can update SoundManager2 docs a little bit :P
Regards!

Categories