Skip to content

Commit

Permalink
Custom XD Fragment and cleanup
Browse files Browse the repository at this point in the history
Summary:
CNN & Amazon are asking for a custom XD Fragment URL. Generally, there
is one case where the Fragment transport fails -- when there is
background audio/video on the page, loading it in the iframe can cause
it to be play over there as well resulting in double audio streams
(video part would be hidden).

I've given postMessage the highest priority, but a custom channelUrl
will be prefered over Flash, where as without a custom channelUrl, we'll
still prefer Flash to reusing the current page.

I've also explicitly not documented the param in FB.init() for now, as I
think it will be confusing.

The channel file itself just needs to contain this line:

  <script src="http://connect.facebook.net/en_US/all.js"></script>

We could also suggest this URL instead, which results in a much smaller
JS file, but I'm not going to because the one above should already be
cached:

  http://connect.facebook.net/en_US/xd.js

Test Plan:
Working on adding tests..

DiffCamp Revision: 112249
Reviewed By: wzhu
CC: platform-diffs@lists, lshepard, brent, mattwkelly, wzhu, selekman
Tasks:

Revert Plan:
OK
  • Loading branch information
daaku committed May 7, 2010
1 parent f3d138e commit f17ec6b
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 23 deletions.
5 changes: 3 additions & 2 deletions src/core/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,10 @@
*
* JavaScript library providing Facebook Connect integration.
*
* TODO: add back fb.api to requires
*
* @provides fb.init
* @requires fb.prelude
* fb.auth
* fb.api
* fb.cookie
* fb.ui
* fb.xd
Expand Down Expand Up @@ -140,6 +139,8 @@ FB.provide('', {
FB._logging = false;
}

FB.XD.init(opts.channelUrl);

if (FB._apiKey) {
// enable cookie support if told to do so
FB.Cookie.setEnabled(options.cookie);
Expand Down
43 changes: 24 additions & 19 deletions src/core/xd.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,10 @@ FB.provide('XD', {
/**
* Initialize the XD layer. Native postMessage or Flash is required.
*
* @param channelUrl {String} optional channel URL
* @access private
*/
init: function() {
init: function(channelUrl) {
// only do init once, if this is set, we're already done
if (FB.XD._origin) {
return;
Expand All @@ -56,7 +57,7 @@ FB.provide('XD', {
window.location.host + '/' + FB.guid());
FB.XD.PostMessage.init();
FB.XD._transport = 'postmessage';
} else if (FB.Flash.hasMinVersion()) {
} else if (!channelUrl && FB.Flash.hasMinVersion()) {
// The origin here is used for Flash XD security. It needs to be based on
// document.domain rather than the URL of the current window. It is
// required and validated by Facebook as part of the xd_proxy.php.
Expand All @@ -66,6 +67,7 @@ FB.provide('XD', {
FB.XD._transport = 'flash';
} else {
FB.XD._transport = 'fragment';
FB.XD.Fragment._channelUrl = channelUrl || window.location.toString();
}
},

Expand All @@ -77,8 +79,7 @@ FB.provide('XD', {
* @returns {Node} the resolved window object
* @throws SyntaxError if the id is malformed
*/

resolveRelation : function(id) {
resolveRelation: function(id) {
var
pt,
matches,
Expand All @@ -91,7 +92,7 @@ FB.provide('XD', {
if (pt === 'opener' || pt === 'parent' || pt === 'top') {
node = node[pt];
} else if (matches = /^frames\[['"]?([a-zA-Z0-9-_]+)['"]?\]$/.exec(pt)) {
// these regex has the `feature' of fixing some badly quote strings
// these regex has the `feature' of fixing some badly quoted strings
node = node.frames[matches[1]];
} else {
throw new SyntaxError('Malformed id to resolve: ' + id + ', pt: ' + pt);
Expand All @@ -116,7 +117,15 @@ FB.provide('XD', {
* @return {String} the xd url bound to the callback
*/
handler: function(cb, relation, forever) {
FB.XD.init();
// if for some reason, we end up trying to create a handler on a page that
// is already being used for XD comm as part of the fragment, we simply
// return 'javascript:false' to prevent a recursive page load loop
//
// the // after it makes any appended things to the url become a JS
// comment, and prevents JS parse errors. cloWntoWn.
if (window.location.toString().indexOf(FB.XD.Fragment._magic) > 0) {
return 'javascript:false;//';
}

// the ?=& tricks login.php into appending at the end instead
// of before the fragment as a query string
Expand All @@ -128,17 +137,15 @@ FB.provide('XD', {
// in fragment mode, the url is the current page and a fragment with a
// magic token
if (FB.XD._transport == 'fragment') {
xdProxy = window.location.toString();
xdProxy = FB.XD.Fragment._channelUrl;
var poundIndex = xdProxy.indexOf('#');
if (poundIndex > 0) {
xdProxy = xdProxy.substr(0, poundIndex);
}

// fb_xd_bust changes the url to prevent firefox from refusing to load
// because it thinks its smarter than the developer and believes it to be
// a recusive load. the rest are explanined in the note above.
xdProxy += xdProxy.indexOf('?') < 0 ? '?' : '&';
xdProxy += 'fb_xd_bust#?=&' + FB.XD.Fragment._magic + '&';
xdProxy += (
(xdProxy.indexOf('?') < 0 ? '?' : '&') +
FB.XD.Fragment._magic + '#?=&'
);
}

if (forever) {
Expand Down Expand Up @@ -255,7 +262,7 @@ FB.provide('XD', {
var
loc = window.location.toString(),
fragment = loc.substr(loc.indexOf('#') + 1),
magicIndex = fragment.indexOf(FB.XD.Fragment._magic);
magicIndex = loc.indexOf(FB.XD.Fragment._magic);

if (magicIndex > 0) {
// make these no-op to help with performance
Expand All @@ -265,12 +272,10 @@ FB.provide('XD', {
FB.init = FB.getLoginStatus = FB.api = function() {};

// display none helps prevent loading of some stuff
document.body.style.display = 'none';
document.documentElement.style.display = 'none';

fragment = fragment.substr(magicIndex + FB.XD.Fragment._magic.length);
var params = FB.QS.decode(fragment);
var w = FB.XD.resolveRelation(params.relation);
w.FB.XD.recv(fragment);
FB.XD.resolveRelation(
FB.QS.decode(fragment).relation).FB.XD.recv(fragment);
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions src/data/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* TODO: add back fb.api to requires
*
* @provides fb.data
* @layer data
* @requires fb.prelude
* fb.type
* fb.api
* fb.array
* fb.string
* fb.obj
Expand Down
8 changes: 8 additions & 0 deletions tests/channel.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<!--
In production, this should be a single script to the URL:
http://connect.facebook.net/en_US/all.js
-->

<script src="../src/core/prelude.js"></script>
<script src="../src/core/qs.js"></script>
<script src="../src/core/xd.js"></script>
37 changes: 37 additions & 0 deletions tests/js/xd.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ test(
}

var oldTransport = FB.XD._transport;
var oldChannel = FB.XD._channelUrl;
FB.XD._transport = 'fragment';
FB.XD.Fragment._channelUrl = window.location.toString();

var url = FB.XD.handler(function(response) {
ok(response.answer == 42, 'expect the answer');
Expand All @@ -91,6 +93,41 @@ test(
}, 'parent') + '&answer=42';

FB.XD._transport = oldTransport;
FB.XD._channelUrl = oldChannel;

FB.UIServer.hidden({
id: 'a',
size: {},
url: url
});

expect(1);
stop();
}
);

test(
'test fragment message flow with custom channel URL',

function() {
var oldTransport = FB.XD._transport;
var oldChannel = FB.XD._channelUrl;
FB.XD._transport = 'fragment';
// this is pretty hacky. but this is a test
FB.XD.Fragment._channelUrl = window
.location
.toString()
.replace('index.html', 'channel.html')
.replace(/(\?|#)(.*)/, '');

var url = FB.XD.handler(function(response) {
ok(response.answer == 42, 'expect the answer');
FB.UIServer._xdRecv({frame: 'a'}, function() {});
start();
}, 'parent') + '&answer=42';

FB.XD._transport = oldTransport;
FB.XD._channelUrl = oldChannel;

FB.UIServer.hidden({
id: 'a',
Expand Down

0 comments on commit f17ec6b

Please sign in to comment.