danriegsecker / swfobject

Automatically exported from code.google.com/p/swfobject
0 stars 0 forks source link

Discuss a possible solution for corrupt installers #155

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
I would like to involve the guys at Adobe to see how we can avoid corrupt
installers in the future (that install Flash Player versions where the
version number exposed to script languages like JavaScript is different
than the real and correct version number as exposed inside Flash). 

Original issue reported on code.google.com by bobbyvandersluis on 25 Aug 2008 at 3:25

GoogleCodeExporter commented 9 years ago

Original comment by bobbyvandersluis on 25 Aug 2008 at 3:26

GoogleCodeExporter commented 9 years ago
I agree we need to engage Adobe more. I hope and wish we can see more 
responsiveness 
from them in regards to working with the opensource community, because we truly 
are 
their biggest "customer" and their technology is going to live-and-die by how 
we 
feel about it.  :)

Short of more direct involvement from them, though, one thought I had tossed 
around 
awhile back, which might be worth considering, is the idea of creating a set of 
canonical "version sniffer" micro-swf's (~1k each) which target specific 
functionality in some of the (troublesome) major (and minor) versions of the 
player 
plugins. These might have to be platform specific, I'm not sure.  But basically 
the 
idea would be that they could be embedded dynamically onto a page one at a 
time, 
with their success or failure helping to determine version more definitively.

Or, another thought would be to just leverage the internal swf's capability to 
version detect, and expose that version to javascript through the various 
"external 
interface" ways (getURL, fscommand, EI). A single micro-swf for version 
detection 
could be embedded at page load to help the javascript.

Original comment by get...@gmail.com on 26 Aug 2008 at 1:07

GoogleCodeExporter commented 9 years ago
I think getify's second solution is best; simply create a small SWF that 
contains
nothing but a callback that sends out its version number to Javascript as soon 
as it
has loaded.

I'd argue that waiting for them Adobe to address this would be like writing 
code that
IE doesn't support and waiting for the IE team to fix it. While Adobe should
obviously fix this bug as soon as possible, the bug fix will only go out to 
users who
update their Flash players. Right now, the bug is very real in the wild and 
fairly
common (it affects almost half of the dozen machines or so I tested) -- and 
this will
continue to be the case for a long time after Adobe fixes the bug in a release.

Original comment by donaldwh...@gmail.com on 4 Sep 2008 at 6:53

GoogleCodeExporter commented 9 years ago
I don't think that using a SWF to do the version detect is the solution. 
Currently we
detect the Flash Player version using JavaScript directly, as soon as the 
script is
executed. If you would like Flash to do the version detection for you, you 
would need
to wait until the DOM of a page is ready (in some browsers this will be onload),
dynamically create a SWF, communicate with this SWF, etc. etc. overhead, 
overhead,
slow overhead... And we would have to supply an extra SWF to do this work for 
you,
which means a more complicated authoring process.

The real solution is for Adobe to keep their act together, this can be done by 
having
their test teams explicitly test if the Flash version and script versions are 
in sync
before a new installer goes out, or maybe automate their publishing process in 
such
way that these numbers are always synced.

re: "I'd argue that ... in a release."

Yes it is a problem, however you overrate it. If I use one corrupt install to 
update
all my computers, all my installations will be corrupted by it. In reality only 
a
small percentage of users really suffer from it. But it is a problem that needs 
to be
adressed. And IMO it needs to be solved at its root cause, by Adobe.

Original comment by bobbyvandersluis on 5 Sep 2008 at 10:04

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
I'd like to share my latest research.

I'm currently investigating a new and alternative route of version detection for
non-IE browsers, which basis is:

window.onload = function() {
    var o = document.createElement("object");
    o.setAttribute("type", "application/x-shockwave-flash");
    document.getElementsByTagName("body")[0].appendChild(o);
    alert(o.GetVariable("$version"));
};

This new way of version detection works pretty well in my tests and avoids the 
following:
1. corrupt installer versions because this only impacts the plugins array 
description
string (still need to thoroughly test this)
2. correct info about build/release numbers, e.g. "WIN 10.0.12.27" gives more 
info
than "... 10.0 b27"
3. it appeared that with the plug-ins Array when you install a browser with a
preinstalled Flash plug-in, the latter is copied over as a seperate install for 
other
browsers. Although this is a rare case, SWFObject currently only looks at the 
first
entry (because we only expected 1), however this is likely to be the lower 
version
(see issue report 198; 
http://code.google.com/p/swfobject/issues/detail?id=198). This
would require us to loop over the Array, so more code ...

The disadvantages are that:
1. It requires the presence of the DOM; currently version detection takes place
before the availability of the DOM
2. Opera returns an exception, still have to look into this
3. object.GetVariable is possibly dependent on stricter security settings (have 
to
investigate exact impact)

Any way, if you have any tips or ideas to make this idea shine brighter, please 
let
me know.   

Original comment by bobbyvandersluis on 30 Oct 2008 at 12:49

GoogleCodeExporter commented 9 years ago
I like the direction you're going with it.  My thoughts are:

1. In regards to the "gap" of having to wait for the DOM to load to do the 
version 
checking, maybe we should have both detection methods (existing one before DOM 
ready, new one after DOM ready). Only if they disagree, then it can complain 
(or 
initiate ExpressInstall, etc), otherwise it can go forward with the embed as 
normal.  This should also help with multiple installed versions, right, as the 
second one is always going to use the newest plugin, it would seem.

2. #1 above seems like it might work for dynamic embedding, but I'm unclear as 
to 
how it might work with or affect static embedding. Perhaps the same logic 
applies, 
but maybe it needs different thinking.

3. The "delay" in processing of logic may require some re-working of how and 
when 
swfobject does its magic.  For instance, we might want to go ahead an embed a 
SWF as 
soon as possible, and get it to start loading, but maybe not display it until 
both 
version checks have passed.  In this way, we could do version detection both 
before 
DOM ready *and* after DOM ready, but *not* actually prevent an embed (force EI) 
until after both version checks have occurred. So to the calling code, it 
proceeds 
as normal, and the decision to swap to call removeSWF() on the already loaded 
SWF 
and instead swap in EI could be done transparently to both the user and the 
calling 
code.  Combined with the visibility thing I just mentioned, this could keep the 
transition still pretty seamless for users, with the side effect being that 
some 
extra (possibly unnecessary) SWF downloading had to occur.

4. Or, perhaps, to prevent so much impact on that existing logic flow, we could 
instead have users of swfobject be able to register a callback function to be 
notified if version conflicts are found.  That way the author can respond 
appropriately (calling removeSWF(), hiding, retrying to initiate EI, etc) if 
their 
code is notified that a version mismatch has later been detected.

Original comment by get...@gmail.com on 30 Oct 2008 at 5:11

GoogleCodeExporter commented 9 years ago
Ok, this seems to work cross-browser:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
    <head>
        <title></title>
        <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
        <script type="text/javascript" src="swfobject.js"></script>
        <script type="text/javascript">
        function test() {
            var b = document.getElementsByTagName("body")[0];
            var o = document.createElement("object");
            o.setAttribute("type", "application/x-shockwave-flash");
            b.appendChild(o);
            var t = setTimeout (function() {
                if (typeof o.GetVariable != "undefined") {
                    alert(o.GetVariable("$version"));
                }
                else {
                    alert("not supported");
                }
                b.removeChild(o);
                clearInterval(t);
                t = null;
            }, 10);
        }
        swfobject.addDomLoadEvent(test);
        </script>
    </head>
    <body></body>
</html>

Original comment by bobbyvandersluis on 31 Oct 2008 at 3:54

GoogleCodeExporter commented 9 years ago
FYI: If you do a setTimeout(), you don't need to call "clearInterval()" as that 
only 
works against calls to setInterval().  Moreover, a setTimeout() automatically 
clears 
itself after it has run, so there's no need, in this usage, to call it at all.  
Setting it to null is a good practice for "semaphor" like logic, but even that 
wouldn't apply here most likely.

Original comment by get...@gmail.com on 31 Oct 2008 at 4:03

GoogleCodeExporter commented 9 years ago
Ah, I was testing with both, forgot to take that out:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
    <head>
        <title></title>
        <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
        <script type="text/javascript" src="swfobject.js"></script>
        <script type="text/javascript">
        function test() {
            var b = document.getElementsByTagName("body")[0];
            var o = document.createElement("object");
            o.setAttribute("type", "application/x-shockwave-flash");
            b.appendChild(o);
            var t = setTimeout (function() {
                if (typeof o.GetVariable != "undefined") {
                    alert(o.GetVariable("$version"));
                }
                else {
                    alert("not supported");
                }
                b.removeChild(o);
                t = null;
            }, 10);
        }
        swfobject.addDomLoadEvent(test);
        </script>
    </head>
    <body></body>
</html>

Original comment by bobbyvandersluis on 31 Oct 2008 at 4:09

GoogleCodeExporter commented 9 years ago
Just FYI, I get 'not supported' when I run this with Safari 3.1.2 (525.21) on 
Windows.  I'm using SWFObject 2.1.

Original comment by jeff.for...@gtempaccount.com on 31 Oct 2008 at 7:28

GoogleCodeExporter commented 9 years ago
This version seems to be working cross-browser:
http://www.bobbyvandersluis.com/swfobject/testsuite_2_2/test_playerversion.html

The code:

    function test() {
            var b = document.getElementsByTagName("body")[0];
            var o = document.createElement("object");
            o.setAttribute("type", "application/x-shockwave-flash");
            var testObject = b.appendChild(o);
            if (testObject) {
                var playerVersion = "0.0.0";
                var counter = 0;
                (function(){
                    if (typeof testObject.GetVariable != "undefined") {
                        var d = testObject.GetVariable("$version");
                        if (d) {
                            d = d.split(" ")[1].split(",");
                            playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
                        }
                    }
                    else if (counter < 10) {
                        counter++;
                        setTimeout(arguments.callee, 10);
                        return;
                    }
                    b.removeChild(o);
                    alert("Flash Player version: " + playerVersion + "\nAdditional initialization
time needed: " + (counter * 10) + " ms");
                })();
            }
            else {
                alert("Unable to create test object");
            }
        }
        swfobject.addDomLoadEvent(test);

Will test this more thoroughly and investigate how we can build this into 
swfobject
properly.

Original comment by bobbyvandersluis on 28 Nov 2008 at 11:00

GoogleCodeExporter commented 9 years ago
Is included in SWFObject 2.2 alpha6.

Original comment by bobbyvandersluis on 1 Dec 2008 at 3:39

GoogleCodeExporter commented 9 years ago
I gave your test_playerversion.html URL a whirl in a half-dozen non-IE browsers 
I 
have handy.  It worked fine with the usual suspects (Firefox, Chrome, Safari, 
Opera), but failed in Netscape 6.2 (but who uses that anymore?) and Lunascape 5 
alpha in Webkit mode (AppleWebKit/529) despite both having Flash installed.  
Lunascape 5a in Gecko mode worked fine.

Just FYI.

Original comment by jeff.for...@gtempaccount.com on 1 Dec 2008 at 7:25

GoogleCodeExporter commented 9 years ago
Thanks, please note that both methods are part of SWFObject 2.2 alpha6. This new
method overwrites the player version as detected with the old method, so if no 
player
version can't be found, we still have the version as can be read from the old 
method.

Original comment by bobbyvandersluis on 1 Dec 2008 at 8:17

GoogleCodeExporter commented 9 years ago
The following message is probably too little too late on this issue - It was 
written
and sent to the developers on Oct 1st, but apparently got lost in their spam 
filters.
 For some reason I didn't realize that this was the proper forum to post my
comments/ideas.  What follows is my original message from that date, which makes
little sense at the end of this thread.

Hello SWFObject team.

First let me say thank you for a the wonderful service your product provides.

Second, please consider the enclosed files as a possible patch for SWFObject  
(I will
be happy to sign whatever sort of contributor agreement you have).

The issue I am trying to resolve is the one alluded to in Issue 155 at
http://code.google.com/p/swfobject/issues/detail?id=155

Here is our situation:  We have just launched a new Flex based site: 
myWebspiration.com
We require Flash player version 9.0.124.  We are using SWFObject to embed our 
Flex
content and run the expressInstall

We are getting a large number of failures from users with FireFox 3.  For many 
of
them, the information in about:plugins does not reflect the true state of the 
plugin
that they have installed.  For example, it might report that Flash 9.0 r115 is
installed, when really 9.0 r124 is.  (This may be a FireFox specific bug, and 
it may
be due to Apple pushing r124 out as part of their software update, which may not
correctly update FireFox).

If you want to reproduce the issue yourself, (for testing purposes) it is very 
easy.
 Just find the pluginreg.dat file in your user profile, then edit this to claim
whatever version of Flash you would like.  Apparently FireFox has no mechanism 
for
checking if this cache of the plugin state is stale or not.

After reading through the discussion of issue 155, I understood your reasons 
for not
wanting to tackle this problem, but we felt we had to give our users a better 
user
experience than  a blank window.  (This is what currently happens when you try 
to run
the express install, but you are already at the latest version).

My proposed fix is not a 100% solution (Only FireFox can fix this for real), but
given the large number of problems we are seeing, it felt like this was a 
worthwhile
improvement.

The basic gist of the fix is to tell the expressInstall swf what version we are
trying to get to, then at the start of it, check to see if we're already at that
version, and if so quit the express install and launch the SWF we were supposed 
to be
launching all along.

The user with a messed up Flash install on FireFox still gets an extra screen 
flicker
as it switches from the expressInstall swf to ours, but it's better than it not
working at all.  The user who isn't using FireFox, or who has a good flash 
player
install, sees no change in behavior.

Hopefully that high level description makes sense, now on to the technical 
details. 
Please note that I am not an expert on swfobject, so there may be issues or
dependencies that I am not aware of.  Even if you don't accept this patch, I 
would
still really appreciate it if you could review it closely, and let me know if 
there
are any mistakes that I have made, or improvements you would like to see.

The first file I changed was expressInstall.as.  I added a few line at the top 
to
check the requiredVersion against the actual version.  the hasPlayerVersion 
function
was copied nearly verbatim from swfobject.as.  Second, I added a new flag to
expressInstallCallback - true for the update completed (and there won't be a 
browser
reboot), false for an error was encountered (the old behavior).

Next I made several changes to swfobject:
The variables att and par were moved from locals in the embedSWF function to 
globals.
 This is the change I am least sure about.  I've never used SWFObject to embed
multiple SWFs on the same page, and I'm not sure how that works, or if this 
change
will break that.
In showExpressInstall it sets requiredVersion in the flashvars so that the
expressInstall swf will get it.
In createSWF the local variables att and par were renamed to attStr and parStr 
- not
strictly required, but I think it makes the code clearer now that att and par 
are
global in scope.
In embedSWF now always setup att and par, even if the code thinks that it 
doesn't
have the right player version.  This doesn't take any extra time in the normal 
case,
and in the bad player version reporting case, these two variables are now setup 
for
later use.
Also in embedSWF set regObj.swfVersion so it is available in 
showExpressInstall. 
Other calls to showExpressInstall already set this value.
In expressInstallCallback add the parameter indicating that the flash player is
already up to date, or that an error occurred.  I named it this parameter 
success,
which isn't really the right name, but was the best I could think of. If we get 
a
"true" (player already at required version), then call createSWF with the 
global att
and par values.

That's it.  It was a fair number of lines to touch, and I changed an "internal" 
API,
but it appears to solve our problem.

Thanks for taking the time to review my code, and I look forward to hearing 
back from
you.

-Jason

-- 
Jason Stafford
Principal Developer
Inspiration Software, Inc.
The leader in visual thinking & learning

Now available - Kidspiration(r) 3, the visual way to explore and understand 
words,
numbers and concepts. 
Learn more at www.inspiration.com/kidspiration.

503-297-3004 Extension 119
503-297-4676 (Fax)
9400 SW Beaverton-Hillsdale Highway
Suite 300
Beaverton, OR 97005-3300

Original comment by jks...@gmail.com on 15 Dec 2008 at 7:44

Attachments:

GoogleCodeExporter commented 9 years ago
Hi Jason, thanks for your feedback, however, did you read the fixes we applied 
in
swfobject 2.2 alpha6? It's a new 'clean' technique that should work fine, also 
in
your cases. So please help us testing the new alpha versions and let us know if 
this
fixes your issues.

Original comment by bobbyvandersluis on 15 Dec 2008 at 8:28

GoogleCodeExporter commented 9 years ago
Included in the SWFObject 2.2 beta1 release

Original comment by bobbyvandersluis on 16 Apr 2009 at 3:05