1 /**
  2  * @fileOverview use flash to accomplish cross domain request , usage scenario ? why not jsonp ?
  3  * @author yiminghe@gmail.com
  4  */
  5 KISSY.add("ajax/XdrFlashTransport", function (S, io, DOM) {
  6 
  7     var // current running request instances
  8         maps = {},
  9         ID = "io_swf",
 10         // flash transporter
 11         flash,
 12         doc = S.Env.host.document,
 13         // whether create the flash transporter
 14         init = false;
 15 
 16     // create the flash transporter
 17     function _swf(uri, _, uid) {
 18         if (init) {
 19             return;
 20         }
 21         init = true;
 22         var o = '<object id="' + ID +
 23             '" type="application/x-shockwave-flash" data="' +
 24             uri + '" width="0" height="0">' +
 25             '<param name="movie" value="' +
 26             uri + '" />' +
 27             '<param name="FlashVars" value="yid=' +
 28             _ + '&uid=' +
 29             uid +
 30             '&host=KISSY.require(\'ajax\')" />' +
 31             '<param name="allowScriptAccess" value="always" />' +
 32             '</object>',
 33             c = doc.createElement('div');
 34         DOM.prepend(c, doc.body || doc.documentElement);
 35         c.innerHTML = o;
 36     }
 37 
 38     function XdrFlashTransport(xhrObj) {
 39         S.log("use flash xdr");
 40         this.xhrObj = xhrObj;
 41     }
 42 
 43     S.augment(XdrFlashTransport, {
 44         // rewrite send to support flash xdr
 45         send:function () {
 46             var self = this,
 47                 xhrObj = self.xhrObj,
 48                 c = xhrObj.config;
 49             var xdr = c['xdr'] || {};
 50             // 不提供则使用 cdn 默认的 flash
 51             _swf(xdr.src || (S.Config.base + "ajax/io.swf"), 1, 1);
 52             // 简便起见,用轮训
 53             if (!flash) {
 54                 // S.log("detect xdr flash");
 55                 setTimeout(function () {
 56                     self.send();
 57                 }, 200);
 58                 return;
 59             }
 60             self._uid = S.guid();
 61             maps[self._uid] = self;
 62 
 63             // ie67 send 出错?
 64             flash.send(c.url, {
 65                 id:self._uid,
 66                 uid:self._uid,
 67                 method:c.type,
 68                 data:c.hasContent && c.data || {}
 69             });
 70         },
 71 
 72         abort:function () {
 73             flash.abort(this._uid);
 74         },
 75 
 76         _xdrResponse:function (e, o) {
 77             S.log(e);
 78             var self = this,
 79                 ret,
 80                 xhrObj = self.xhrObj;
 81 
 82             // need decodeURI to get real value from flash returned value
 83             xhrObj.responseText = decodeURI(o.c.responseText);
 84 
 85             switch (e) {
 86                 case 'success':
 87                     ret = { status:200, statusText:"success" };
 88                     delete maps[o.id];
 89                     break;
 90                 case 'abort':
 91                     delete maps[o.id];
 92                     break;
 93                 case 'timeout':
 94                 case 'transport error':
 95                 case 'failure':
 96                     delete maps[o.id];
 97                     ret = { status:500, statusText:e };
 98                     break;
 99             }
100             if (ret) {
101                 xhrObj._xhrReady(ret.status, ret.statusText);
102             }
103         }
104     });
105 
106     /*called by flash*/
107     io['applyTo'] = function (_, cmd, args) {
108         // S.log(cmd + " execute");
109         var cmds = cmd.split(".").slice(1),
110             func = io;
111         S.each(cmds, function (c) {
112             func = func[c];
113         });
114         func.apply(null, args);
115     };
116 
117     // when flash is loaded
118     io['xdrReady'] = function () {
119         flash = doc.getElementById(ID);
120     };
121 
122     /**
123      * when response is returned from server
124      * @param e response status
125      * @param o internal data
126      * @param c internal data
127      */
128     io['xdrResponse'] = function (e, o, c) {
129         var xhr = maps[o.uid];
130         xhr && xhr._xdrResponse(e, o, c);
131     };
132 
133     return XdrFlashTransport;
134 
135 }, {
136     requires:["./base", 'dom']
137 });