About The Author
Michael Flynn is a Senior Developer at Unicon, a consulting company that focuses on enterprise deployments of open source software. He specializes in web technologies that include C# .NET, SQL, XML, AJAX, jQuery, Flash, and also skills in Photoshop and Illustrator. He was been involved in web development since 1998, and earned a Bachelors and Masters degree in Computer Engineering and Computer Science from the Univerisity of Louisville and holds an MSCT certificate in Web Applications.
Calendar
<<  May 2012  >>
SMTWTFS
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

Facebook Canvas, IFrames, and Cookies

Working with iframes can be quite easy when working under the same domain, but when your project contains a cross-domain scenario it can get kind of tricky.  This article will will give a scenario of just that, but within a Facebook canvas page that needs iframe resizing, and the setting of cookies.

1. Facebook Application Setup

The first step is to create a Facebook Application.  You can do this from the Facebook Developers application page.  After you have created your application and setup all the necessary settings, we are ready to setup an iframe canvas page. 

First select the Facebook Integration tab on the left menu under your application settings.

image

The Canvas section is the section to target.  The Canvas Page is the landing page within Facebook for your application.  The Canvas URL is the canvas url that will contain your iframe, and is the landing page Facebook will display from the canvas page.  The Canvas Type needs to have IFrame selected to use an iframe within a canvas page.  The last thing that needs to be done is to select Auto-resize under IFrame Size.  This will automatically resize our iframe when the height of it increases or decreases.

image

2. Facebook Connect Setup

If we setup our settings correctly the page should be visible within Facebook.  If you were to resize the page with javascript within the iframe, Facebook wouldn’t resize the iframe to fit the page content.  The last step to accomplish this is to insert some Facebook Connect javascript. 

The old Facebook Javascript SDK is used first.  Insert the following javascript include below right after the <body> tag to initialize Facebook Connect. If this is on a secure page, Facebook also has a https version.

   1: <script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php/en_US"
   2:         type="text/javascript"></script>

Then at the bottom of the site right before the </body> tag insert the following javascript.

   1: FB_RequireFeatures(["CanvasUtil"], function () {
   2:     FB.CanvasClient.startTimerToSizeToContent();
   3: });

The new Facebook Javascript SDK is used below.  This SDK uses asynchronous loading which helps out with page loads.  The code below initializes the Facebook Javascript SDK, and can be inserted at the bottom of the page right before the </body> tag.

   1: <div id="fb-root"></div>
   2: <script>   
   3:  
   4:   (function() {
   5:     var e = document.createElement('script'); e.async = true;
   6:     e.src = document.location.protocol +
   7:       '//connect.facebook.net/en_US/all.js';
   8:     document.getElementById('fb-root').appendChild(e);
   9:   }());

The last step is to add the auto resize javascript code.  The code below should be inserted after the initializing code.

   1: window.fbAsyncInit = function() {
   2:   FB.Canvas.setAutoResize();
   3: }

Now your Facebook application will resize automatically when the height of your iframe contents changes.

3. Cross Domain IFrame Cookies

Another obstacle of this project was the use of cookies being set within the iframe on Facebook.  The main culprits of the problem are Internet Explorer, Safari, and Chrome.  These browsers contain default settings that block cookies from being set within the iframe.  Internet Explorer’s problem can be solved by setting up a P3P privacy policy, but this only fixes part of the problem.  Safari and Chrome still block cookies within an iframe even with a P3P privacy policy.  Below is the preferences window from Safari 5.0 on Windows.  If the Accept cookies had Always selected then this wouldn’t be a big deal, but by default it is not, and we don’t expect our users to know this.

 

image

The only full proof way to set cookies within an a cross domain iframe is to use popups.  But beware you must do it in such a way that a popup blocker doesn’t block it.  Below is a function that opens a popup window and centers it.

   1: function openWindow {
   2:     var height = 225;
   3:     var width = 470;
   4:     var left = (screen.width/2)-(width/2);
   5:     var top = (screen.height/2)-(height/2);
   6:     mywindow = window.open("", "login","location=1,status=1,scrollbars=1,top=" + top + ",left=" + left + ",width=" + width + ",height=" + height); 
   7:  
   8:     if(mywindow == null) {
   9:         alert('Please disable your popup blocker, and try again');
  10:     }
  11:     else {
  12:         var html = "<html><body> <script> window.location = ('http://example.com/window'); </script></body></html>";
  13:         mywindow.document.write(html);
  14:     }
  15: }

So how do we stop popups?  The main thing to do is have the popup originate from a click event.  This is because a user generated action is probably safe to open since the user initiated it, but opening popups on a timer or onload event can in turn be like spamming.  You can read more about Internet Explorer pop-up blocker guidelines for more information, and other steps to avoid.

   1: <a href="#" onclick="openWindow(); return false;">Register</a>

Also by trial and error, a popup window wouldn’t open from a successful ajax call even though it originated from a click event.  The fix for this was to open the popup before the ajax call, and have some text letting the user know it is loading within the popup.  When the ajax call is finished, since the popup is already open, a call is made to reopen the popup which will use the existing one skipping any blocking functionality from the browser.

image

After the popup is open you can execute code to set your cookie within the popup.  This particular popup is setting a cookie from javascript using the JQuery cookies plugin.  After the cookie is set a call can be made to the opener page to reload the page or execute a function, and last close the popup.  The opener iframe page will keep the cookie that was set in the popup. 

   1: window.opener.callFunction();
   2: window.close();

If you are dealing with https and must call the opener page that was http then a cross domain error will occur. Here is a small trick you can do (thanks da Ritchie).  After you are done doing your logic within the https popup, you can do a redirect to the same page but replace https with http and append a query string.

   1: window.location = window.location.toString().split('?')[0].replace('https://', 'http://').replace('#', '') + '?success=true';

After the page redirects you can test for success from the url.

   1: if (window.location.toString().indexOf('?success') > -1) {
   2:     window.opener.callFunction();
   3:     window.close();
   4: }

You have officially conquered the iframe within a cross domain scenario on Facebook.

Posted on 10/4/2010 6:43:00 PM by cblaze22

Permalink | Comments (0) | Post RSSRSS comment feed |

Categories:

Tags:

Currently rated 1.9 by 15 people

  • Currently 1.933333/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Comments

Add A Comment




  Country flag