Programming Flex 3: Chapter 20, Embedding Flex Applications in a Browser
Pages: 1, 2, 3, 4, 5, 6, 7, 8, 9
As we already mentioned, the history.js file code is shortsighted in the
way it works, and because of this you'll need to edit it for it to work
with SWFObject-embedded applications. The primary error is that
history.js assumes that all
applications are embedded using object tags for Internet Explorer and embed tags for other browsers. That assumption
doesn't work for SWFObject-embedded applications that use nested
object tags. Therefore, you need to adapt the history.js code to be able to find
applications embedded using nested object tags. The authors of this book don't
claim to be JavaScript experts, and we don't claim that our solution is
the best or most elegant, but it does work and it is simple. All you
need to do is edit history.js and
add a few lines of code to the getPlayer() method, as shown in Example 20-11. This code returns
if it
is defined. We'll set this property in the HTML file using SWFObject to
retrieve the reference.
Example 20-11. Changes to getPlayer() in history.js
function getPlayer(objectId) {
if(BrowserHistory.flexApplication != null) {
return BrowserHistory.flexApplication;
}
var objectId = objectId || null;
var player = null;
if (browser.ie && objectId != null) {
player = document.getElementById(objectId);
}
if (player == null) {
player = document.getElementsByTagName('object')[0];
}
if (player == null || player.object == null) {
player = document.getElementsByTagName('embed')[0];
}
return player;
}
Next, in the HTML, we need to set BrowserHistory.flexApplication to reference the Flex application instance. We need to use
SWFObject's getObjectById() method to
retrieve the reference. We'll also use the addLoadEvent() method of SWFObject to ensure
that we assign the reference once the application is defined in the
page. Example 20-12 shows
the new code.
Example 20-12. Setting BrowserHistory.flexApplication in the HTML file
<script type="text/javascript">
swfobject.registerObject("flexApplication", "9.0.0");
swfobject.addLoadEvent(loadEventHandler);
function loadEventHandler() {
BrowserHistory.flexApplication =
swfobject.getObjectById("flexApplication");
}
</script>
With these changes, SWFObject will work with BrowserManager. You need to make sure that
when you deploy the application, you deploy the .swf file, the HTML file, swfobject.js, and the history directory with history.js, history.css, and historyFrame.html.
Flash Player enforces security rules for what and how applications can access data, and you'll notice this especially when embedding a Flex application in an HTML page. Flex applications can typically access all data resources in the same domain as the .swf. For example, if the .swf is deployed to www.example.com, it can access a web service that is also deployed at www.example.com. However, access to data resources at different domains is disallowed by Flash Player unless that domain explicitly gives permission. The Flash Player security rules disallow access to data resources unless the domains match exactly, including subdomains, even if the domain names resolve to the same physical address. That means an .swf deployed at www.example.com cannot access data from test.example.com or even example.com unless the server explicitly allows access. The domain can give permission by way of a cross-domain policy file.
Note: When working with the socket class and loading data through sockets rather than through request/response mechanisms, Flash Player 9,0,115,0 and later introduce an additional socket policy file requirement. Since Flash Player security is continually evolving, we recommend that you review the latest articles at http://www.adobe.com/devnet/flashplayer/ for any changes that may impact your application.
A cross-domain policy file is an XML file that resides on the server that hosts the data resources. The format for a cross-domain policy file is as follows:
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM
"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain="www.example.com" />
</cross-domain-policy>
The root <cross-domain-policy> node can contain one
or more <allow-access-from>
elements. The <allow-access-from>
elements specify the domains that can access the resources on the server.
You can use an * wildcard in place of
the subdomain, which means that any subdomain can access the data
resources. For example, the following policy allows access from www.example.com, beta.example.com, test.example.com, etc.:
This excerpt is from Programming Flex 3. If you want to try your hand at developing rich Internet applications with Adobe's Flex 3, and already have experience with frameworks such as .NET or Java, this is the ideal book to get you started. Programming Flex 3 gives you a solid understanding of Flex 3's core concepts, and valuable insight into how, why, and when to use specific Flex features. Learn to get the most from this amazing and sophisticated technology.
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM
"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain="*.example.com" />
</cross-domain-policy>
You can also use the * wildcard
in place of the entire domain to allow access from all domains:
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM
"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain="*" />
</cross-domain-policy>
If the server uses HTTPS and wants to allow access to .swf files deployed on nonsecure domains, it must specify a value for the secure attribute. The following allows access to .swf files deployed at www.example.com:
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM
"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain="www.example.com" secure="false" />
</cross-domain-policy>
By default, Flash Player looks for a policy file named crossdomain.xml at the root of the web server
from which it is requesting the data resources. If Flash Player attempts
to load an XML document from http://www.example.com/data/xml/data.xml, it will look for
http://www.example.com/crossdomain.xml. If you want
to set different permissions for different resources on a server, you can
optionally deploy different policy files in different locations on the
server. For example, a policy file located at http://www.example.com/data/xml would apply only to the
resources in that directory. However, when you place policy files in
nondefault locations, you must use ActionScript to load the policy file in
your Flex application. The ActionScript code uses the static loadPolicyFile() method of the flash.system.Security class. The following loads a policy file:
Security.loadPolicyFile("http://www.example.com/data/xml/policy.xml");
Deploying a cross-domain policy file presupposes that you have access to the server with the data resources—or that you can persuade those with the server to deploy the policy file. In the few cases where you cannot deploy a policy file on a server whose data resources you need to utilize, you have the option of deploying a proxy file on your server. A proxy file is a file that exists on your server (a .jsp, an ASP.NET page, a ColdFusion page, a PHP page, etc.) to which your Flex application can make requests. The proxy file then makes the requests to the remote resource and relays the data back to Flash Player.
Runtime shared libraries are a way to share assets and libraries among multiple .swf files on the same domain. This is useful when you have several .swf files that comprise an application or that span several applications deployed in the same domain in which each .swf file utilizes many common assets and/or libraries. For example, if a.swf and b.swf both utilize the same subset of 25 classes and embedded images that add up to 100 KB, the user has to download the same 100 KB twice, once for each .swf.
The theory behind runtime shared libraries involves a concept called linking. All .swf files employ one or both forms of linking: static and dynamic. By default, all linking is static. When an asset or source file is statically linked with an .swf, it is compiled into the .swf. Dynamic linking means that the asset or source file is not compiled into the .swf, but the .swf has a reference to an .swf into which it has been compiled. Through dynamic linking, you can specify certain elements that should not be compiled into an .swf to reduce the total file size of the .swf. The .swf is then linked to another .swf where the elements have been compiled. This allows you to extract common elements from two or more .swf files and place them into another .swf to which all the .swf files are linked dynamically. This new .swf is called a runtime shared library.
We can understand the benefit of runtime shared libraries by looking at the a.swf and b.swf example in more detail. In this example, a.swf is 200 KB and b.swf is 400 KB. Both .swf files are deployed on the same domain. The two .swf files happen to use of common elements. That means that if a user uses both a.swf and b.swf, she downloads 600 KB, of which 100 KB is duplicate content. Using a runtime shared library, you can introduce a new .swf, library.swf, which contains the 100 KB of common content. Although there's some overhead in creating a runtime shared library for our purposes, we'll keep the numbers simple: a.swf will now be 100 KB and b.swf will now be 300 KB. Each will be dynamically linked to library.swf, which also has to download. However, the second time the user requests library.swf it will be retrieved from client cache rather than from the server, effectively saving 100 KB.
The underlying manner in which you create and use runtime shared libraries is always the same. However, if you are working with the compiler from a command line or from a custom build script using Ant, the workflow is different from using Flex Builder, which automates a lot of the work involved with runtime shared libraries.