easyxdm-rails 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,333 +0,0 @@
1
- /**
2
- * easyXDM
3
- * http://easyxdm.net/
4
- * Copyright(c) 2009-2011, Øyvind Sean Kinsey, oyvind@kinsey.no.
5
- *
6
- * Permission is hereby granted, free of charge, to any person obtaining a copy
7
- * of this software and associated documentation files (the "Software"), to deal
8
- * in the Software without restriction, including without limitation the rights
9
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
- * copies of the Software, and to permit persons to whom the Software is
11
- * furnished to do so, subject to the following conditions:
12
- *
13
- * The above copyright notice and this permission notice shall be included in
14
- * all copies or substantial portions of the Software.
15
- *
16
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
- * THE SOFTWARE.
23
- */
24
- /*jslint browser: true, immed: true, passfail: true, undef: true, newcap: true*/
25
- /*global easyXDM, window */
26
- /**
27
- * easyXDM
28
- * http://easyxdm.net/
29
- * Copyright(c) 2009-2011, Øyvind Sean Kinsey, oyvind@kinsey.no.
30
- *
31
- * Permission is hereby granted, free of charge, to any person obtaining a copy
32
- * of this software and associated documentation files (the "Software"), to deal
33
- * in the Software without restriction, including without limitation the rights
34
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
35
- * copies of the Software, and to permit persons to whom the Software is
36
- * furnished to do so, subject to the following conditions:
37
- *
38
- * The above copyright notice and this permission notice shall be included in
39
- * all copies or substantial portions of the Software.
40
- *
41
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
44
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
46
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
47
- * THE SOFTWARE.
48
- */
49
- /**
50
- * @class easyXDM.WidgetManager
51
- * A class for managing widgets.<br/>
52
- * Handles initializing widgets, and does all of the message distribution.
53
- <pre><code>
54
- _widgetManager = new easyXDM.WidgetManager({
55
- local: "../hash.html",
56
- container: document.getElementById("defaultcontainer")
57
- },function(){
58
- _widgetManager.addWidget("http://provider.easyxdm.net/example/widget.html",{});
59
- });
60
- </code></pre>
61
- * Widgets can by dynamically added using the addWidget method
62
- <pre><code>
63
- _widgetManager.addWidget("http://provider.easyxdm.net/example/widget.html",{
64
- container document.getElementById("widgetcontainer")
65
- });
66
- </code></pre>
67
- * @constructor
68
- * @param {Object} config The WidgetManagers configuration
69
- * @namespace easyXDM
70
- */
71
- easyXDM.WidgetManager = function(config){
72
- var WidgetManager = this, _hashUrl = config.local, _channelNr = 0;
73
- var Events = {
74
- WidgetInitialized: "widgetinitialized",
75
- WidgetFailed: "widgetfailed"
76
- };
77
- var _widgets = {}, _subscribers = {};
78
- var _widgetSettings = {
79
- hosturl: location.href
80
- };
81
- easyXDM.apply(_widgetSettings, config.widgetSettings);
82
- var _container = config.container || document.body;
83
-
84
- /**
85
- * @private
86
- * Raises the specified event
87
- * @param {String} event The raised event
88
- * @param {Object} arg
89
- */
90
- function _raiseEvent(event, arg){
91
- if (config.listeners && config.listeners[event]) {
92
- config.listeners[event](WidgetManager, arg);
93
- }
94
- }
95
-
96
- /**
97
- * @private
98
- * Adds the widghet to the list of subscribers for the given topic
99
- * @param {String} url The widgets url
100
- * @param {String} topic The topic to subscribe to
101
- */
102
- function _subscribe(url, topic){
103
- if (!(topic in _subscribers)) {
104
- _subscribers[topic] = [];
105
- }
106
- _subscribers[topic].push(url);
107
- }
108
-
109
- /**
110
- * @private
111
- * Initialized the widget.<br/>
112
- * This is called after the widget has notified that it is ready.
113
- * @param {Object} widget The widget
114
- * @param {String} url The widgets url
115
- * @param {Object} widgetConfig The widgets configuration
116
- */
117
- function _initializeWidget(widget, url, widgetConfig){
118
- widget.initialize(_widgetSettings, function(response){
119
- if (response.isInitialized) {
120
- _widgets[url] = widget;
121
- var i = response.subscriptions.length;
122
- while (i--) {
123
- _subscribe(url, response.subscriptions[i]);
124
- }
125
- _raiseEvent(Events.WidgetInitialized, {
126
- url: url
127
- });
128
- }
129
- else {
130
- widget.destroy();
131
- _raiseEvent(Events.WidgetFailed, {
132
- url: url
133
- });
134
- }
135
- });
136
- }
137
-
138
- /**
139
- * @private
140
- * Publishes the data to the topics subscribers
141
- * @param {String} url The senders url
142
- * @param {String} topic The datas topic
143
- * @param {Object} data The data to publish
144
- */
145
- function _publish(url, topic, data){
146
- var subscribers = _subscribers[topic];
147
- if (subscribers) {
148
- var i = subscribers.length, widgetUrl;
149
- while (i--) {
150
- widgetUrl = subscribers[i];
151
- if (widgetUrl !== url) {
152
- _widgets[widgetUrl].send(url, topic, data);
153
- }
154
- }
155
- }
156
- }
157
-
158
- /**
159
- * @private
160
- * Sets up a new widget
161
- * @param {String} url The widgets url
162
- * @param {Object} widgetConfig The widgets configuration
163
- */
164
- function _setUpWidget(url, widgetConfig){
165
- var widget = new easyXDM.Rpc({
166
- channel: "widget" + _channelNr++,
167
- local: _hashUrl,
168
- remote: url,
169
- container: widgetConfig.container || _container,
170
- swf: config.swf,
171
- onReady: function(){
172
- _initializeWidget(widget, url, widgetConfig);
173
- }
174
- }, {
175
- local: {
176
- subscribe: {
177
- isVoid: true,
178
- method: function(topic){
179
- _subscribe(url, topic);
180
- }
181
- },
182
- publish: {
183
- isVoid: true,
184
- method: function(topic, data){
185
- _publish(url, topic, data);
186
- }
187
- }
188
- },
189
- remote: {
190
- initialize: {},
191
- send: {
192
- isVoid: true
193
- }
194
- }
195
- });
196
- }
197
-
198
- /**
199
- * Adds a widget to the collection
200
- * @param {String} url The url to load the widget from
201
- * @param {Object} widgetConfig The widgets url
202
- */
203
- this.addWidget = function(url, widgetConfig){
204
- if (url in _widgets) {
205
- throw new Error("A widget with this url has already been initialized");
206
- }
207
- _setUpWidget(url, widgetConfig);
208
- };
209
-
210
- /**
211
- * Removes the widget
212
- * @param {Object} url
213
- */
214
- this.removeWidget = function(url){
215
- if (url in _widgets) {
216
- for (var topic in _subscribers) {
217
- if (_subscribers.hasOwnProperty(topic)) {
218
- var subscribers = _subscribers[topic], i = subscribers.length;
219
- while (i--) {
220
- if (subscribers[i] === url) {
221
- subscribers.splice(i, 1);
222
- break;
223
- }
224
- }
225
- }
226
- }
227
- _widgets[url].destroy();
228
- delete _widgets[url];
229
- }
230
- };
231
-
232
- /**
233
- * Publish data to a topics subscribers
234
- * @param {String} topic The topic to publish to
235
- * @param {Object} data The data to publish
236
- */
237
- this.publish = function(topic, data){
238
- _publish("", topic, data);
239
- };
240
-
241
- /**
242
- * Broadcasts data to all the widgets
243
- * @param {Object} data The data to broadcast
244
- */
245
- this.broadcast = function(data){
246
- for (var url in _widgets) {
247
- if (_widgets.hasOwnPropert(url)) {
248
- _widgets[url].send({
249
- url: "",
250
- topic: "broadcast",
251
- data: data
252
- });
253
- }
254
- }
255
- };
256
- };
257
-
258
- /**
259
- * @class easyXDM.Widget
260
- * The base framework for creating widgets
261
- * @constructor
262
- * @param {Object} config The widgets configuration
263
- * @param {Function} onReady A method to run after the widget has been initialized.
264
- * @namespace easyXDM
265
- */
266
- easyXDM.Widget = function(config){
267
- var _widget = this;
268
- var _incomingMessageHandler;
269
- var _widgetHost = new easyXDM.Rpc({
270
- swf: config.swf
271
- }, {
272
- remote: {
273
- subscribe: {
274
- isVoid: true
275
- },
276
- publish: {
277
- isVoid: true
278
- }
279
- },
280
- local: {
281
- initialize: {
282
- method: function(settings){
283
- config.initialized(_widget, _widgetHost);
284
- return {
285
- isInitialized: true,
286
- subscriptions: config.subscriptions
287
- };
288
- }
289
- },
290
- send: {
291
- isVoid: true,
292
- method: function(url, topic, data){
293
- _incomingMessageHandler(url, topic, data);
294
- }
295
- }
296
- }
297
- });
298
-
299
- /**
300
- * @private
301
- * Destroy the interface on unload
302
- */
303
- window.onunload = function(){
304
- _widgetHost.destroy();
305
- };
306
-
307
- /**
308
- * Publish data to subscribers to a topic
309
- * @param {String} topic The topic to publish to
310
- * @param {Object} data The data to publish
311
- */
312
- this.publish = function(topic, data){
313
- _widgetHost.publish(topic, data);
314
- };
315
-
316
- /**
317
- * Subscribe to a topic
318
- * @param {String} topic The topic to subscribe to
319
- */
320
- this.subscribe = function(topic){
321
- _widgetHost.subscribe(topic);
322
- };
323
-
324
- /**
325
- * Register the method that will handle incoming messages
326
- * @param {Function} fn The handler
327
- */
328
- this.registerMessageHandler = function(fn){
329
- _incomingMessageHandler = fn;
330
- };
331
-
332
- config.initialize(this, _widgetHost);
333
- };
@@ -1,24 +0,0 @@
1
- /**
2
- * easyXDM
3
- * http://easyxdm.net/
4
- * Copyright(c) 2009-2011, Øyvind Sean Kinsey, oyvind@kinsey.no.
5
- *
6
- * Permission is hereby granted, free of charge, to any person obtaining a copy
7
- * of this software and associated documentation files (the "Software"), to deal
8
- * in the Software without restriction, including without limitation the rights
9
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
- * copies of the Software, and to permit persons to whom the Software is
11
- * furnished to do so, subject to the following conditions:
12
- *
13
- * The above copyright notice and this permission notice shall be included in
14
- * all copies or substantial portions of the Software.
15
- *
16
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
- * THE SOFTWARE.
23
- */
24
- easyXDM.WidgetManager=function(e){var h=this,b=e.local,k=0;var n={WidgetInitialized:"widgetinitialized",WidgetFailed:"widgetfailed"};var j={},d={};var i={hosturl:location.href};easyXDM.apply(i,e.widgetSettings);var g=e.container||document.body;function f(p,o){if(e.listeners&&e.listeners[p]){e.listeners[p](h,o)}}function c(p,o){if(!(o in d)){d[o]=[]}d[o].push(p)}function m(p,o,q){p.initialize(i,function(r){if(r.isInitialized){j[o]=p;var s=r.subscriptions.length;while(s--){c(o,r.subscriptions[s])}f(n.WidgetInitialized,{url:o})}else{p.destroy();f(n.WidgetFailed,{url:o})}})}function a(p,o,r){var s=d[o];if(s){var q=s.length,t;while(q--){t=s[q];if(t!==p){j[t].send(p,o,r)}}}}function l(o,q){var p=new easyXDM.Rpc({channel:"widget"+k++,local:b,remote:o,container:q.container||g,swf:e.swf,onReady:function(){m(p,o,q)}},{local:{subscribe:{isVoid:true,method:function(r){c(o,r)}},publish:{isVoid:true,method:function(r,s){a(o,r,s)}}},remote:{initialize:{},send:{isVoid:true}}})}this.addWidget=function(o,p){if(o in j){throw new Error("A widget with this url has already been initialized")}l(o,p)};this.removeWidget=function(p){if(p in j){for(var o in d){if(d.hasOwnProperty(o)){var r=d[o],q=r.length;while(q--){if(r[q]===p){r.splice(q,1);break}}}}j[p].destroy();delete j[p]}};this.publish=function(o,p){a("",o,p)};this.broadcast=function(p){for(var o in j){if(j.hasOwnPropert(o)){j[o].send({url:"",topic:"broadcast",data:p})}}}};easyXDM.Widget=function(c){var a=this;var b;var d=new easyXDM.Rpc({swf:c.swf},{remote:{subscribe:{isVoid:true},publish:{isVoid:true}},local:{initialize:{method:function(e){c.initialized(a,d);return{isInitialized:true,subscriptions:c.subscriptions}}},send:{isVoid:true,method:function(f,e,g){b(f,e,g)}}}});window.onunload=function(){d.destroy()};this.publish=function(e,f){d.publish(e,f)};this.subscribe=function(e){d.subscribe(e)};this.registerMessageHandler=function(e){b=e};c.initialize(this,d)};
@@ -1,2871 +0,0 @@
1
- /**
2
- * easyXDM
3
- * http://easyxdm.net/
4
- * Copyright(c) 2009-2011, Øyvind Sean Kinsey, oyvind@kinsey.no.
5
- *
6
- * Permission is hereby granted, free of charge, to any person obtaining a copy
7
- * of this software and associated documentation files (the "Software"), to deal
8
- * in the Software without restriction, including without limitation the rights
9
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
- * copies of the Software, and to permit persons to whom the Software is
11
- * furnished to do so, subject to the following conditions:
12
- *
13
- * The above copyright notice and this permission notice shall be included in
14
- * all copies or substantial portions of the Software.
15
- *
16
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
- * THE SOFTWARE.
23
- */
24
- (function (window, document, location, setTimeout, decodeURIComponent, encodeURIComponent) {
25
- /*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
26
- /*global JSON, XMLHttpRequest, window, escape, unescape, ActiveXObject */
27
- //
28
- // easyXDM
29
- // http://easyxdm.net/
30
- // Copyright(c) 2009-2011, Øyvind Sean Kinsey, oyvind@kinsey.no.
31
- //
32
- // Permission is hereby granted, free of charge, to any person obtaining a copy
33
- // of this software and associated documentation files (the "Software"), to deal
34
- // in the Software without restriction, including without limitation the rights
35
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
36
- // copies of the Software, and to permit persons to whom the Software is
37
- // furnished to do so, subject to the following conditions:
38
- //
39
- // The above copyright notice and this permission notice shall be included in
40
- // all copies or substantial portions of the Software.
41
- //
42
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
43
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
44
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
45
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
46
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
47
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
48
- // THE SOFTWARE.
49
- //
50
-
51
- var global = this;
52
- var channelId = Math.floor(Math.random() * 10000); // randomize the initial id in case of multiple closures loaded
53
- var emptyFn = Function.prototype;
54
- var reURI = /^((http.?:)\/\/([^:\/\s]+)(:\d+)*)/; // returns groups for protocol (2), domain (3) and port (4)
55
- var reParent = /[\-\w]+\/\.\.\//; // matches a foo/../ expression
56
- var reDoubleSlash = /([^:])\/\//g; // matches // anywhere but in the protocol
57
- var namespace = ""; // stores namespace under which easyXDM object is stored on the page (empty if object is global)
58
- var easyXDM = {};
59
- var _easyXDM = window.easyXDM; // map over global easyXDM in case of overwrite
60
- var IFRAME_PREFIX = "easyXDM_";
61
- var HAS_NAME_PROPERTY_BUG;
62
- var useHash = false; // whether to use the hash over the query
63
- var flashVersion; // will be set if using flash
64
- var HAS_FLASH_THROTTLED_BUG;
65
- var _trace = emptyFn;
66
-
67
-
68
- // http://peter.michaux.ca/articles/feature-detection-state-of-the-art-browser-scripting
69
- function isHostMethod(object, property){
70
- var t = typeof object[property];
71
- return t == 'function' ||
72
- (!!(t == 'object' && object[property])) ||
73
- t == 'unknown';
74
- }
75
-
76
- function isHostObject(object, property){
77
- return !!(typeof(object[property]) == 'object' && object[property]);
78
- }
79
-
80
- // end
81
-
82
- // http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/
83
- function isArray(o){
84
- return Object.prototype.toString.call(o) === '[object Array]';
85
- }
86
-
87
- // end
88
- function hasFlash(){
89
- var name = "Shockwave Flash", mimeType = "application/x-shockwave-flash";
90
-
91
- if (!undef(navigator.plugins) && typeof navigator.plugins[name] == "object") {
92
- // adapted from the swfobject code
93
- var description = navigator.plugins[name].description;
94
- if (description && !undef(navigator.mimeTypes) && navigator.mimeTypes[mimeType] && navigator.mimeTypes[mimeType].enabledPlugin) {
95
- flashVersion = description.match(/\d+/g);
96
- }
97
- }
98
- if (!flashVersion) {
99
- var flash;
100
- try {
101
- flash = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
102
- flashVersion = Array.prototype.slice.call(flash.GetVariable("$version").match(/(\d+),(\d+),(\d+),(\d+)/), 1);
103
- flash = null;
104
- }
105
- catch (notSupportedException) {
106
- }
107
- }
108
- if (!flashVersion) {
109
- return false;
110
- }
111
- var major = parseInt(flashVersion[0], 10), minor = parseInt(flashVersion[1], 10);
112
- HAS_FLASH_THROTTLED_BUG = major > 9 && minor > 0;
113
- return true;
114
- }
115
-
116
- /*
117
- * Cross Browser implementation for adding and removing event listeners.
118
- */
119
- var on, un;
120
- if (isHostMethod(window, "addEventListener")) {
121
- on = function(target, type, listener){
122
- _trace("adding listener " + type);
123
- target.addEventListener(type, listener, false);
124
- };
125
- un = function(target, type, listener){
126
- _trace("removing listener " + type);
127
- target.removeEventListener(type, listener, false);
128
- };
129
- }
130
- else if (isHostMethod(window, "attachEvent")) {
131
- on = function(object, sEvent, fpNotify){
132
- _trace("adding listener " + sEvent);
133
- object.attachEvent("on" + sEvent, fpNotify);
134
- };
135
- un = function(object, sEvent, fpNotify){
136
- _trace("removing listener " + sEvent);
137
- object.detachEvent("on" + sEvent, fpNotify);
138
- };
139
- }
140
- else {
141
- throw new Error("Browser not supported");
142
- }
143
-
144
- /*
145
- * Cross Browser implementation of DOMContentLoaded.
146
- */
147
- var domIsReady = false, domReadyQueue = [], readyState;
148
- if ("readyState" in document) {
149
- // If browser is WebKit-powered, check for both 'loaded' (legacy browsers) and
150
- // 'interactive' (HTML5 specs, recent WebKit builds) states.
151
- // https://bugs.webkit.org/show_bug.cgi?id=45119
152
- readyState = document.readyState;
153
- domIsReady = readyState == "complete" || (~ navigator.userAgent.indexOf('AppleWebKit/') && (readyState == "loaded" || readyState == "interactive"));
154
- }
155
- else {
156
- // If readyState is not supported in the browser, then in order to be able to fire whenReady functions apropriately
157
- // when added dynamically _after_ DOM load, we have to deduce wether the DOM is ready or not.
158
- // We only need a body to add elements to, so the existence of document.body is enough for us.
159
- domIsReady = !!document.body;
160
- }
161
-
162
- function dom_onReady(){
163
- if (domIsReady) {
164
- return;
165
- }
166
- domIsReady = true;
167
- _trace("firing dom_onReady");
168
- for (var i = 0; i < domReadyQueue.length; i++) {
169
- domReadyQueue[i]();
170
- }
171
- domReadyQueue.length = 0;
172
- }
173
-
174
-
175
- if (!domIsReady) {
176
- if (isHostMethod(window, "addEventListener")) {
177
- on(document, "DOMContentLoaded", dom_onReady);
178
- }
179
- else {
180
- on(document, "readystatechange", function(){
181
- if (document.readyState == "complete") {
182
- dom_onReady();
183
- }
184
- });
185
- if (document.documentElement.doScroll && window === top) {
186
- var doScrollCheck = function(){
187
- if (domIsReady) {
188
- return;
189
- }
190
- // http://javascript.nwbox.com/IEContentLoaded/
191
- try {
192
- document.documentElement.doScroll("left");
193
- }
194
- catch (e) {
195
- setTimeout(doScrollCheck, 1);
196
- return;
197
- }
198
- dom_onReady();
199
- };
200
- doScrollCheck();
201
- }
202
- }
203
-
204
- // A fallback to window.onload, that will always work
205
- on(window, "load", dom_onReady);
206
- }
207
- /**
208
- * This will add a function to the queue of functions to be run once the DOM reaches a ready state.
209
- * If functions are added after this event then they will be executed immediately.
210
- * @param {function} fn The function to add
211
- * @param {Object} scope An optional scope for the function to be called with.
212
- */
213
- function whenReady(fn, scope){
214
- if (domIsReady) {
215
- fn.call(scope);
216
- return;
217
- }
218
- domReadyQueue.push(function(){
219
- fn.call(scope);
220
- });
221
- }
222
-
223
- /**
224
- * Returns an instance of easyXDM from the parent window with
225
- * respect to the namespace.
226
- *
227
- * @return An instance of easyXDM (in the parent window)
228
- */
229
- function getParentObject(){
230
- var obj = parent;
231
- if (namespace !== "") {
232
- for (var i = 0, ii = namespace.split("."); i < ii.length; i++) {
233
- if (!obj) {
234
- throw new Error(ii.slice(0, i + 1).join('.') + ' is not an object');
235
- }
236
- obj = obj[ii[i]];
237
- }
238
- }
239
- if (!obj || !obj.easyXDM) {
240
- throw new Error('Could not find easyXDM in parent.' + namespace);
241
- }
242
- return obj.easyXDM;
243
- }
244
-
245
- /**
246
- * Removes easyXDM variable from the global scope. It also returns control
247
- * of the easyXDM variable to whatever code used it before.
248
- *
249
- * @param {String} ns A string representation of an object that will hold
250
- * an instance of easyXDM.
251
- * @return An instance of easyXDM
252
- */
253
- function noConflict(ns){
254
- if (typeof ns != "string" || !ns) {
255
- throw new Error('namespace must be a non-empty string');
256
- }
257
- _trace("Settings namespace to '" + ns + "'");
258
-
259
- window.easyXDM = _easyXDM;
260
- namespace = ns;
261
- if (namespace) {
262
- IFRAME_PREFIX = "easyXDM_" + namespace.replace(".", "_") + "_";
263
- }
264
- return easyXDM;
265
- }
266
-
267
- /*
268
- * Methods for working with URLs
269
- */
270
- /**
271
- * Get the domain name from a url.
272
- * @param {String} url The url to extract the domain from.
273
- * @return The domain part of the url.
274
- * @type {String}
275
- */
276
- function getDomainName(url){
277
- if (!url) {
278
- throw new Error("url is undefined or empty");
279
- }
280
- return url.match(reURI)[3];
281
- }
282
-
283
- /**
284
- * Get the port for a given URL, or "" if none
285
- * @param {String} url The url to extract the port from.
286
- * @return The port part of the url.
287
- * @type {String}
288
- */
289
- function getPort(url){
290
- if (!url) {
291
- throw new Error("url is undefined or empty");
292
- }
293
- return url.match(reURI)[4] || "";
294
- }
295
-
296
- /**
297
- * Returns a string containing the schema, domain and if present the port
298
- * @param {String} url The url to extract the location from
299
- * @return {String} The location part of the url
300
- */
301
- function getLocation(url){
302
- if (!url) {
303
- throw new Error("url is undefined or empty");
304
- }
305
- if (/^file/.test(url)) {
306
- throw new Error("The file:// protocol is not supported");
307
- }
308
- var m = url.toLowerCase().match(reURI);
309
- var proto = m[2], domain = m[3], port = m[4] || "";
310
- if ((proto == "http:" && port == ":80") || (proto == "https:" && port == ":443")) {
311
- port = "";
312
- }
313
- return proto + "//" + domain + port;
314
- }
315
-
316
- /**
317
- * Resolves a relative url into an absolute one.
318
- * @param {String} url The path to resolve.
319
- * @return {String} The resolved url.
320
- */
321
- function resolveUrl(url){
322
- if (!url) {
323
- throw new Error("url is undefined or empty");
324
- }
325
-
326
- // replace all // except the one in proto with /
327
- url = url.replace(reDoubleSlash, "$1/");
328
-
329
- // If the url is a valid url we do nothing
330
- if (!url.match(/^(http||https):\/\//)) {
331
- // If this is a relative path
332
- var path = (url.substring(0, 1) === "/") ? "" : location.pathname;
333
- if (path.substring(path.length - 1) !== "/") {
334
- path = path.substring(0, path.lastIndexOf("/") + 1);
335
- }
336
-
337
- url = location.protocol + "//" + location.host + path + url;
338
- }
339
-
340
- // reduce all 'xyz/../' to just ''
341
- while (reParent.test(url)) {
342
- url = url.replace(reParent, "");
343
- }
344
-
345
- _trace("resolved url '" + url + "'");
346
- return url;
347
- }
348
-
349
- /**
350
- * Appends the parameters to the given url.<br/>
351
- * The base url can contain existing query parameters.
352
- * @param {String} url The base url.
353
- * @param {Object} parameters The parameters to add.
354
- * @return {String} A new valid url with the parameters appended.
355
- */
356
- function appendQueryParameters(url, parameters){
357
- if (!parameters) {
358
- throw new Error("parameters is undefined or null");
359
- }
360
-
361
- var hash = "", indexOf = url.indexOf("#");
362
- if (indexOf !== -1) {
363
- hash = url.substring(indexOf);
364
- url = url.substring(0, indexOf);
365
- }
366
- var q = [];
367
- for (var key in parameters) {
368
- if (parameters.hasOwnProperty(key)) {
369
- q.push(key + "=" + encodeURIComponent(parameters[key]));
370
- }
371
- }
372
- return url + (useHash ? "#" : (url.indexOf("?") == -1 ? "?" : "&")) + q.join("&") + hash;
373
- }
374
-
375
-
376
- // build the query object either from location.query, if it contains the xdm_e argument, or from location.hash
377
- var query = (function(input){
378
- input = input.substring(1).split("&");
379
- var data = {}, pair, i = input.length;
380
- while (i--) {
381
- pair = input[i].split("=");
382
- data[pair[0]] = decodeURIComponent(pair[1]);
383
- }
384
- return data;
385
- }(/xdm_e=/.test(location.search) ? location.search : location.hash));
386
-
387
- /*
388
- * Helper methods
389
- */
390
- /**
391
- * Helper for checking if a variable/property is undefined
392
- * @param {Object} v The variable to test
393
- * @return {Boolean} True if the passed variable is undefined
394
- */
395
- function undef(v){
396
- return typeof v === "undefined";
397
- }
398
-
399
- /**
400
- * A safe implementation of HTML5 JSON. Feature testing is used to make sure the implementation works.
401
- * @return {JSON} A valid JSON conforming object, or null if not found.
402
- */
403
- var getJSON = function(){
404
- var cached = {};
405
- var obj = {
406
- a: [1, 2, 3]
407
- }, json = "{\"a\":[1,2,3]}";
408
-
409
- if (typeof JSON != "undefined" && typeof JSON.stringify === "function" && JSON.stringify(obj).replace((/\s/g), "") === json) {
410
- // this is a working JSON instance
411
- return JSON;
412
- }
413
- if (Object.toJSON) {
414
- if (Object.toJSON(obj).replace((/\s/g), "") === json) {
415
- // this is a working stringify method
416
- cached.stringify = Object.toJSON;
417
- }
418
- }
419
-
420
- if (typeof String.prototype.evalJSON === "function") {
421
- obj = json.evalJSON();
422
- if (obj.a && obj.a.length === 3 && obj.a[2] === 3) {
423
- // this is a working parse method
424
- cached.parse = function(str){
425
- return str.evalJSON();
426
- };
427
- }
428
- }
429
-
430
- if (cached.stringify && cached.parse) {
431
- // Only memoize the result if we have valid instance
432
- getJSON = function(){
433
- return cached;
434
- };
435
- return cached;
436
- }
437
- return null;
438
- };
439
-
440
- /**
441
- * Applies properties from the source object to the target object.<br/>
442
- * @param {Object} target The target of the properties.
443
- * @param {Object} source The source of the properties.
444
- * @param {Boolean} noOverwrite Set to True to only set non-existing properties.
445
- */
446
- function apply(destination, source, noOverwrite){
447
- var member;
448
- for (var prop in source) {
449
- if (source.hasOwnProperty(prop)) {
450
- if (prop in destination) {
451
- member = source[prop];
452
- if (typeof member === "object") {
453
- apply(destination[prop], member, noOverwrite);
454
- }
455
- else if (!noOverwrite) {
456
- destination[prop] = source[prop];
457
- }
458
- }
459
- else {
460
- destination[prop] = source[prop];
461
- }
462
- }
463
- }
464
- return destination;
465
- }
466
-
467
- // This tests for the bug in IE where setting the [name] property using javascript causes the value to be redirected into [submitName].
468
- function testForNamePropertyBug(){
469
- var form = document.body.appendChild(document.createElement("form")), input = form.appendChild(document.createElement("input"));
470
- input.name = IFRAME_PREFIX + "TEST" + channelId; // append channelId in order to avoid caching issues
471
- HAS_NAME_PROPERTY_BUG = input !== form.elements[input.name];
472
- document.body.removeChild(form);
473
- _trace("HAS_NAME_PROPERTY_BUG: " + HAS_NAME_PROPERTY_BUG);
474
- }
475
-
476
- /**
477
- * Creates a frame and appends it to the DOM.
478
- * @param config {object} This object can have the following properties
479
- * <ul>
480
- * <li> {object} prop The properties that should be set on the frame. This should include the 'src' property.</li>
481
- * <li> {object} attr The attributes that should be set on the frame.</li>
482
- * <li> {DOMElement} container Its parent element (Optional).</li>
483
- * <li> {function} onLoad A method that should be called with the frames contentWindow as argument when the frame is fully loaded. (Optional)</li>
484
- * </ul>
485
- * @return The frames DOMElement
486
- * @type DOMElement
487
- */
488
- function createFrame(config){
489
- _trace("creating frame: " + config.props.src);
490
- if (undef(HAS_NAME_PROPERTY_BUG)) {
491
- testForNamePropertyBug();
492
- }
493
- var frame;
494
- // This is to work around the problems in IE6/7 with setting the name property.
495
- // Internally this is set as 'submitName' instead when using 'iframe.name = ...'
496
- // This is not required by easyXDM itself, but is to facilitate other use cases
497
- if (HAS_NAME_PROPERTY_BUG) {
498
- frame = document.createElement("<iframe name=\"" + config.props.name + "\"/>");
499
- }
500
- else {
501
- frame = document.createElement("IFRAME");
502
- frame.name = config.props.name;
503
- }
504
-
505
- frame.id = frame.name = config.props.name;
506
- delete config.props.name;
507
-
508
- if (typeof config.container == "string") {
509
- config.container = document.getElementById(config.container);
510
- }
511
-
512
- if (!config.container) {
513
- // This needs to be hidden like this, simply setting display:none and the like will cause failures in some browsers.
514
- apply(frame.style, {
515
- position: "absolute",
516
- top: "-2000px",
517
- // Avoid potential horizontal scrollbar
518
- left: "0px"
519
- });
520
- config.container = document.body;
521
- }
522
-
523
- // HACK: IE cannot have the src attribute set when the frame is appended
524
- // into the container, so we set it to "javascript:false" as a
525
- // placeholder for now. If we left the src undefined, it would
526
- // instead default to "about:blank", which causes SSL mixed-content
527
- // warnings in IE6 when on an SSL parent page.
528
- var src = config.props.src;
529
- config.props.src = "javascript:false";
530
-
531
- // transfer properties to the frame
532
- apply(frame, config.props);
533
-
534
- frame.border = frame.frameBorder = 0;
535
- frame.allowTransparency = true;
536
- config.container.appendChild(frame);
537
-
538
- if (config.onLoad) {
539
- on(frame, "load", config.onLoad);
540
- }
541
-
542
- // set the frame URL to the proper value (we previously set it to
543
- // "javascript:false" to work around the IE issue mentioned above)
544
- if(config.usePost) {
545
- var form = config.container.appendChild(document.createElement('form')), input;
546
- form.target = frame.name;
547
- form.action = src;
548
- form.method = 'POST';
549
- if (typeof(config.usePost) === 'object') {
550
- for (var i in config.usePost) {
551
- if (config.usePost.hasOwnProperty(i)) {
552
- if (HAS_NAME_PROPERTY_BUG) {
553
- input = document.createElement('<input name="' + i + '"/>');
554
- } else {
555
- input = document.createElement("INPUT");
556
- input.name = i;
557
- }
558
- input.value = config.usePost[i];
559
- form.appendChild(input);
560
- }
561
- }
562
- }
563
- form.submit();
564
- form.parentNode.removeChild(form);
565
- } else {
566
- frame.src = src;
567
- }
568
- config.props.src = src;
569
-
570
- return frame;
571
- }
572
-
573
- /**
574
- * Check whether a domain is allowed using an Access Control List.
575
- * The ACL can contain * and ? as wildcards, or can be regular expressions.
576
- * If regular expressions they need to begin with ^ and end with $.
577
- * @param {Array/String} acl The list of allowed domains
578
- * @param {String} domain The domain to test.
579
- * @return {Boolean} True if the domain is allowed, false if not.
580
- */
581
- function checkAcl(acl, domain){
582
- // normalize into an array
583
- if (typeof acl == "string") {
584
- acl = [acl];
585
- }
586
- var re, i = acl.length;
587
- while (i--) {
588
- re = acl[i];
589
- re = new RegExp(re.substr(0, 1) == "^" ? re : ("^" + re.replace(/(\*)/g, ".$1").replace(/\?/g, ".") + "$"));
590
- if (re.test(domain)) {
591
- return true;
592
- }
593
- }
594
- return false;
595
- }
596
-
597
- /*
598
- * Functions related to stacks
599
- */
600
- /**
601
- * Prepares an array of stack-elements suitable for the current configuration
602
- * @param {Object} config The Transports configuration. See easyXDM.Socket for more.
603
- * @return {Array} An array of stack-elements with the TransportElement at index 0.
604
- */
605
- function prepareTransportStack(config){
606
- var protocol = config.protocol, stackEls;
607
- config.isHost = config.isHost || undef(query.xdm_p);
608
- useHash = config.hash || false;
609
- _trace("preparing transport stack");
610
-
611
- if (!config.props) {
612
- config.props = {};
613
- }
614
- if (!config.isHost) {
615
- _trace("using parameters from query");
616
- config.channel = query.xdm_c.replace(/["'<>\\]/g, "");
617
- config.secret = query.xdm_s;
618
- config.remote = query.xdm_e.replace(/["'<>\\]/g, "");
619
- ;
620
- protocol = query.xdm_p;
621
- if (config.acl && !checkAcl(config.acl, config.remote)) {
622
- throw new Error("Access denied for " + config.remote);
623
- }
624
- }
625
- else {
626
- config.remote = resolveUrl(config.remote);
627
- config.channel = config.channel || "default" + channelId++;
628
- config.secret = Math.random().toString(16).substring(2);
629
- if (undef(protocol)) {
630
- if (getLocation(location.href) == getLocation(config.remote)) {
631
- /*
632
- * Both documents has the same origin, lets use direct access.
633
- */
634
- protocol = "4";
635
- }
636
- else if (isHostMethod(window, "postMessage") || isHostMethod(document, "postMessage")) {
637
- /*
638
- * This is supported in IE8+, Firefox 3+, Opera 9+, Chrome 2+ and Safari 4+
639
- */
640
- protocol = "1";
641
- }
642
- else if (config.swf && isHostMethod(window, "ActiveXObject") && hasFlash()) {
643
- /*
644
- * The Flash transport superseedes the NixTransport as the NixTransport has been blocked by MS
645
- */
646
- protocol = "6";
647
- }
648
- else if (navigator.product === "Gecko" && "frameElement" in window && navigator.userAgent.indexOf('WebKit') == -1) {
649
- /*
650
- * This is supported in Gecko (Firefox 1+)
651
- */
652
- protocol = "5";
653
- }
654
- else if (config.remoteHelper) {
655
- /*
656
- * This is supported in all browsers that retains the value of window.name when
657
- * navigating from one domain to another, and where parent.frames[foo] can be used
658
- * to get access to a frame from the same domain
659
- */
660
- protocol = "2";
661
- }
662
- else {
663
- /*
664
- * This is supported in all browsers where [window].location is writable for all
665
- * The resize event will be used if resize is supported and the iframe is not put
666
- * into a container, else polling will be used.
667
- */
668
- protocol = "0";
669
- }
670
- _trace("selecting protocol: " + protocol);
671
- }
672
- else {
673
- _trace("using protocol: " + protocol);
674
- }
675
- }
676
- config.protocol = protocol; // for conditional branching
677
- switch (protocol) {
678
- case "0":// 0 = HashTransport
679
- apply(config, {
680
- interval: 100,
681
- delay: 2000,
682
- useResize: true,
683
- useParent: false,
684
- usePolling: false
685
- }, true);
686
- if (config.isHost) {
687
- if (!config.local) {
688
- _trace("looking for image to use as local");
689
- // If no local is set then we need to find an image hosted on the current domain
690
- var domain = location.protocol + "//" + location.host, images = document.body.getElementsByTagName("img"), image;
691
- var i = images.length;
692
- while (i--) {
693
- image = images[i];
694
- if (image.src.substring(0, domain.length) === domain) {
695
- config.local = image.src;
696
- break;
697
- }
698
- }
699
- if (!config.local) {
700
- _trace("no image found, defaulting to using the window");
701
- // If no local was set, and we are unable to find a suitable file, then we resort to using the current window
702
- config.local = window;
703
- }
704
- }
705
-
706
- var parameters = {
707
- xdm_c: config.channel,
708
- xdm_p: 0
709
- };
710
-
711
- if (config.local === window) {
712
- // We are using the current window to listen to
713
- config.usePolling = true;
714
- config.useParent = true;
715
- config.local = location.protocol + "//" + location.host + location.pathname + location.search;
716
- parameters.xdm_e = config.local;
717
- parameters.xdm_pa = 1; // use parent
718
- }
719
- else {
720
- parameters.xdm_e = resolveUrl(config.local);
721
- }
722
-
723
- if (config.container) {
724
- config.useResize = false;
725
- parameters.xdm_po = 1; // use polling
726
- }
727
- config.remote = appendQueryParameters(config.remote, parameters);
728
- }
729
- else {
730
- apply(config, {
731
- channel: query.xdm_c,
732
- remote: query.xdm_e,
733
- useParent: !undef(query.xdm_pa),
734
- usePolling: !undef(query.xdm_po),
735
- useResize: config.useParent ? false : config.useResize
736
- });
737
- }
738
- stackEls = [new easyXDM.stack.HashTransport(config), new easyXDM.stack.ReliableBehavior({}), new easyXDM.stack.QueueBehavior({
739
- encode: true,
740
- maxLength: 4000 - config.remote.length
741
- }), new easyXDM.stack.VerifyBehavior({
742
- initiate: config.isHost
743
- })];
744
- break;
745
- case "1":
746
- stackEls = [new easyXDM.stack.PostMessageTransport(config)];
747
- break;
748
- case "2":
749
- config.remoteHelper = resolveUrl(config.remoteHelper);
750
- stackEls = [new easyXDM.stack.NameTransport(config), new easyXDM.stack.QueueBehavior(), new easyXDM.stack.VerifyBehavior({
751
- initiate: config.isHost
752
- })];
753
- break;
754
- case "3":
755
- stackEls = [new easyXDM.stack.NixTransport(config)];
756
- break;
757
- case "4":
758
- stackEls = [new easyXDM.stack.SameOriginTransport(config)];
759
- break;
760
- case "5":
761
- stackEls = [new easyXDM.stack.FrameElementTransport(config)];
762
- break;
763
- case "6":
764
- if (!flashVersion) {
765
- hasFlash();
766
- }
767
- stackEls = [new easyXDM.stack.FlashTransport(config)];
768
- break;
769
- }
770
- // this behavior is responsible for buffering outgoing messages, and for performing lazy initialization
771
- stackEls.push(new easyXDM.stack.QueueBehavior({
772
- lazy: config.lazy,
773
- remove: true
774
- }));
775
- return stackEls;
776
- }
777
-
778
- /**
779
- * Chains all the separate stack elements into a single usable stack.<br/>
780
- * If an element is missing a necessary method then it will have a pass-through method applied.
781
- * @param {Array} stackElements An array of stack elements to be linked.
782
- * @return {easyXDM.stack.StackElement} The last element in the chain.
783
- */
784
- function chainStack(stackElements){
785
- var stackEl, defaults = {
786
- incoming: function(message, origin){
787
- this.up.incoming(message, origin);
788
- },
789
- outgoing: function(message, recipient){
790
- this.down.outgoing(message, recipient);
791
- },
792
- callback: function(success){
793
- this.up.callback(success);
794
- },
795
- init: function(){
796
- this.down.init();
797
- },
798
- destroy: function(){
799
- this.down.destroy();
800
- }
801
- };
802
- for (var i = 0, len = stackElements.length; i < len; i++) {
803
- stackEl = stackElements[i];
804
- apply(stackEl, defaults, true);
805
- if (i !== 0) {
806
- stackEl.down = stackElements[i - 1];
807
- }
808
- if (i !== len - 1) {
809
- stackEl.up = stackElements[i + 1];
810
- }
811
- }
812
- return stackEl;
813
- }
814
-
815
- /**
816
- * This will remove a stackelement from its stack while leaving the stack functional.
817
- * @param {Object} element The elment to remove from the stack.
818
- */
819
- function removeFromStack(element){
820
- element.up.down = element.down;
821
- element.down.up = element.up;
822
- element.up = element.down = null;
823
- }
824
-
825
- /*
826
- * Export the main object and any other methods applicable
827
- */
828
- /**
829
- * @class easyXDM
830
- * A javascript library providing cross-browser, cross-domain messaging/RPC.
831
- * @version 2.4.16.3
832
- * @singleton
833
- */
834
- apply(easyXDM, {
835
- /**
836
- * The version of the library
837
- * @type {string}
838
- */
839
- version: "2.4.16.3",
840
- /**
841
- * This is a map containing all the query parameters passed to the document.
842
- * All the values has been decoded using decodeURIComponent.
843
- * @type {object}
844
- */
845
- query: query,
846
- /**
847
- * @private
848
- */
849
- stack: {},
850
- /**
851
- * Applies properties from the source object to the target object.<br/>
852
- * @param {object} target The target of the properties.
853
- * @param {object} source The source of the properties.
854
- * @param {boolean} noOverwrite Set to True to only set non-existing properties.
855
- */
856
- apply: apply,
857
-
858
- /**
859
- * A safe implementation of HTML5 JSON. Feature testing is used to make sure the implementation works.
860
- * @return {JSON} A valid JSON conforming object, or null if not found.
861
- */
862
- getJSONObject: getJSON,
863
- /**
864
- * This will add a function to the queue of functions to be run once the DOM reaches a ready state.
865
- * If functions are added after this event then they will be executed immediately.
866
- * @param {function} fn The function to add
867
- * @param {object} scope An optional scope for the function to be called with.
868
- */
869
- whenReady: whenReady,
870
- /**
871
- * Removes easyXDM variable from the global scope. It also returns control
872
- * of the easyXDM variable to whatever code used it before.
873
- *
874
- * @param {String} ns A string representation of an object that will hold
875
- * an instance of easyXDM.
876
- * @return An instance of easyXDM
877
- */
878
- noConflict: noConflict
879
- });
880
-
881
- // Expose helper functions so we can test them
882
- apply(easyXDM, {
883
- checkAcl: checkAcl,
884
- getDomainName: getDomainName,
885
- getLocation: getLocation,
886
- appendQueryParameters: appendQueryParameters
887
- });
888
- /*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
889
- /*global console, _FirebugCommandLine, easyXDM, window, escape, unescape, isHostObject, undef, _trace, domIsReady, emptyFn, namespace */
890
- //
891
- // easyXDM
892
- // http://easyxdm.net/
893
- // Copyright(c) 2009-2011, Øyvind Sean Kinsey, oyvind@kinsey.no.
894
- //
895
- // Permission is hereby granted, free of charge, to any person obtaining a copy
896
- // of this software and associated documentation files (the "Software"), to deal
897
- // in the Software without restriction, including without limitation the rights
898
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
899
- // copies of the Software, and to permit persons to whom the Software is
900
- // furnished to do so, subject to the following conditions:
901
- //
902
- // The above copyright notice and this permission notice shall be included in
903
- // all copies or substantial portions of the Software.
904
- //
905
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
906
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
907
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
908
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
909
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
910
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
911
- // THE SOFTWARE.
912
- //
913
-
914
- var debug = {
915
- _deferred: [],
916
- flush: function(){
917
- this.trace("... deferred messages ...");
918
- for (var i = 0, len = this._deferred.length; i < len; i++) {
919
- this.trace(this._deferred[i]);
920
- }
921
- this._deferred.length = 0;
922
- this.trace("... end of deferred messages ...");
923
- },
924
- getTime: function(){
925
- var d = new Date(), h = d.getHours() + "", m = d.getMinutes() + "", s = d.getSeconds() + "", ms = d.getMilliseconds() + "", zeros = "000";
926
- if (h.length == 1) {
927
- h = "0" + h;
928
- }
929
- if (m.length == 1) {
930
- m = "0" + m;
931
- }
932
- if (s.length == 1) {
933
- s = "0" + s;
934
- }
935
- ms = zeros.substring(ms.length) + ms;
936
- return h + ":" + m + ":" + s + "." + ms;
937
- },
938
- /**
939
- * Logs the message to console.log if available
940
- * @param {String} msg The message to log
941
- */
942
- log: function(msg){
943
- // Uses memoizing to cache the implementation
944
- if (!isHostObject(window, "console") || undef(console.log)) {
945
- /**
946
- * Sets log to be an empty function since we have no output available
947
- * @ignore
948
- */
949
- this.log = emptyFn;
950
- }
951
- else {
952
- /**
953
- * Sets log to be a wrapper around console.log
954
- * @ignore
955
- * @param {String} msg
956
- */
957
- this.log = function(msg){
958
- console.log(location.host + (namespace ? ":" + namespace : "") + " - " + this.getTime() + ": " + msg);
959
- };
960
- }
961
- this.log(msg);
962
- },
963
- /**
964
- * Will try to trace the given message either to a DOMElement with the id "log",
965
- * or by using console.info.
966
- * @param {String} msg The message to trace
967
- */
968
- trace: function(msg){
969
- // Uses memoizing to cache the implementation
970
- if (!domIsReady) {
971
- if (this._deferred.length === 0) {
972
- easyXDM.whenReady(debug.flush, debug);
973
- }
974
- this._deferred.push(msg);
975
- this.log(msg);
976
- }
977
- else {
978
- var el = document.getElementById("log");
979
- // is there a log element present?
980
- if (el) {
981
- /**
982
- * Sets trace to be a function that outputs the messages to the DOMElement with id "log"
983
- * @ignore
984
- * @param {String} msg
985
- */
986
- this.trace = function(msg){
987
- try {
988
- el.appendChild(document.createElement("div")).appendChild(document.createTextNode(location.host + (namespace ? ":" + namespace : "") + " - " + this.getTime() + ":" + msg));
989
- el.scrollTop = el.scrollHeight;
990
- }
991
- catch (e) {
992
- //In case we are unloading
993
- }
994
- };
995
- }
996
- else if (isHostObject(window, "console") && !undef(console.info)) {
997
- /**
998
- * Sets trace to be a wrapper around console.info
999
- * @ignore
1000
- * @param {String} msg
1001
- */
1002
- this.trace = function(msg){
1003
- console.info(location.host + (namespace ? ":" + namespace : "") + " - " + this.getTime() + ":" + msg);
1004
- };
1005
- }
1006
- else {
1007
- /**
1008
- * Create log window
1009
- * @ignore
1010
- */
1011
- var domain = location.host, windowname = domain.replace(/[\-.:]/g, "") + "easyxdm_log", logWin;
1012
- try {
1013
- logWin = window.open("", windowname, "width=800,height=200,status=0,navigation=0,scrollbars=1");
1014
- }
1015
- catch (e) {
1016
- }
1017
- if (logWin) {
1018
- var doc = logWin.document;
1019
- el = doc.getElementById("log");
1020
- if (!el) {
1021
- doc.write("<html><head><title>easyXDM log " + domain + "</title></head>");
1022
- doc.write("<body><div id=\"log\"></div></body></html>");
1023
- doc.close();
1024
- el = doc.getElementById("log");
1025
- }
1026
- this.trace = function(msg){
1027
- try {
1028
- el.appendChild(doc.createElement("div")).appendChild(doc.createTextNode(location.host + (namespace ? ":" + namespace : "") + " - " + this.getTime() + ":" + msg));
1029
- el.scrollTop = el.scrollHeight;
1030
- }
1031
- catch (e) {
1032
- //In case we are unloading
1033
- }
1034
- };
1035
- this.trace("---- new logger at " + location.href);
1036
- }
1037
-
1038
- if (!el) {
1039
- // We are unable to use any logging
1040
- this.trace = emptyFn;
1041
- }
1042
- }
1043
- this.trace(msg);
1044
- }
1045
- },
1046
- /**
1047
- * Creates a method usable for tracing.
1048
- * @param {String} name The name the messages should be marked with
1049
- * @return {Function} A function that accepts a single string as argument.
1050
- */
1051
- getTracer: function(name){
1052
- return function(msg){
1053
- debug.trace(name + ": " + msg);
1054
- };
1055
- }
1056
- };
1057
- debug.log("easyXDM present on '" + location.href);
1058
- easyXDM.Debug = debug;
1059
- _trace = debug.getTracer("{Private}");
1060
- /*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
1061
- /*global easyXDM, window, escape, unescape, isHostObject, isHostMethod, un, on, createFrame, debug */
1062
- //
1063
- // easyXDM
1064
- // http://easyxdm.net/
1065
- // Copyright(c) 2009-2011, Øyvind Sean Kinsey, oyvind@kinsey.no.
1066
- //
1067
- // Permission is hereby granted, free of charge, to any person obtaining a copy
1068
- // of this software and associated documentation files (the "Software"), to deal
1069
- // in the Software without restriction, including without limitation the rights
1070
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1071
- // copies of the Software, and to permit persons to whom the Software is
1072
- // furnished to do so, subject to the following conditions:
1073
- //
1074
- // The above copyright notice and this permission notice shall be included in
1075
- // all copies or substantial portions of the Software.
1076
- //
1077
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1078
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1079
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1080
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1081
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1082
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1083
- // THE SOFTWARE.
1084
- //
1085
-
1086
- /**
1087
- * @class easyXDM.DomHelper
1088
- * Contains methods for dealing with the DOM
1089
- * @singleton
1090
- */
1091
- easyXDM.DomHelper = {
1092
- /**
1093
- * Provides a consistent interface for adding eventhandlers
1094
- * @param {Object} target The target to add the event to
1095
- * @param {String} type The name of the event
1096
- * @param {Function} listener The listener
1097
- */
1098
- on: on,
1099
- /**
1100
- * Provides a consistent interface for removing eventhandlers
1101
- * @param {Object} target The target to remove the event from
1102
- * @param {String} type The name of the event
1103
- * @param {Function} listener The listener
1104
- */
1105
- un: un,
1106
- /**
1107
- * Checks for the presence of the JSON object.
1108
- * If it is not present it will use the supplied path to load the JSON2 library.
1109
- * This should be called in the documents head right after the easyXDM script tag.
1110
- * http://json.org/json2.js
1111
- * @param {String} path A valid path to json2.js
1112
- */
1113
- requiresJSON: function(path){
1114
- if (!isHostObject(window, "JSON")) {
1115
- debug.log("loading external JSON");
1116
- // we need to encode the < in order to avoid an illegal token error
1117
- // when the script is inlined in a document.
1118
- document.write('<' + 'script type="text/javascript" src="' + path + '"><' + '/script>');
1119
- }
1120
- else {
1121
- debug.log("native JSON found");
1122
- }
1123
- }
1124
- };
1125
- /*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
1126
- /*global easyXDM, window, escape, unescape, debug */
1127
- //
1128
- // easyXDM
1129
- // http://easyxdm.net/
1130
- // Copyright(c) 2009-2011, Øyvind Sean Kinsey, oyvind@kinsey.no.
1131
- //
1132
- // Permission is hereby granted, free of charge, to any person obtaining a copy
1133
- // of this software and associated documentation files (the "Software"), to deal
1134
- // in the Software without restriction, including without limitation the rights
1135
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1136
- // copies of the Software, and to permit persons to whom the Software is
1137
- // furnished to do so, subject to the following conditions:
1138
- //
1139
- // The above copyright notice and this permission notice shall be included in
1140
- // all copies or substantial portions of the Software.
1141
- //
1142
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1143
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1144
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1145
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1146
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1147
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1148
- // THE SOFTWARE.
1149
- //
1150
-
1151
- (function(){
1152
- // The map containing the stored functions
1153
- var _map = {};
1154
-
1155
- /**
1156
- * @class easyXDM.Fn
1157
- * This contains methods related to function handling, such as storing callbacks.
1158
- * @singleton
1159
- * @namespace easyXDM
1160
- */
1161
- easyXDM.Fn = {
1162
- /**
1163
- * Stores a function using the given name for reference
1164
- * @param {String} name The name that the function should be referred by
1165
- * @param {Function} fn The function to store
1166
- * @namespace easyXDM.fn
1167
- */
1168
- set: function(name, fn){
1169
- this._trace("storing function " + name);
1170
- _map[name] = fn;
1171
- },
1172
- /**
1173
- * Retrieves the function referred to by the given name
1174
- * @param {String} name The name of the function to retrieve
1175
- * @param {Boolean} del If the function should be deleted after retrieval
1176
- * @return {Function} The stored function
1177
- * @namespace easyXDM.fn
1178
- */
1179
- get: function(name, del){
1180
- this._trace("retrieving function " + name);
1181
- var fn = _map[name];
1182
- if (!fn) {
1183
- this._trace(name + " not found");
1184
- }
1185
-
1186
- if (del) {
1187
- delete _map[name];
1188
- }
1189
- return fn;
1190
- }
1191
- };
1192
-
1193
- easyXDM.Fn._trace = debug.getTracer("easyXDM.Fn");
1194
- }());
1195
- /*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
1196
- /*global easyXDM, window, escape, unescape, chainStack, prepareTransportStack, getLocation, debug */
1197
- //
1198
- // easyXDM
1199
- // http://easyxdm.net/
1200
- // Copyright(c) 2009-2011, Øyvind Sean Kinsey, oyvind@kinsey.no.
1201
- //
1202
- // Permission is hereby granted, free of charge, to any person obtaining a copy
1203
- // of this software and associated documentation files (the "Software"), to deal
1204
- // in the Software without restriction, including without limitation the rights
1205
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1206
- // copies of the Software, and to permit persons to whom the Software is
1207
- // furnished to do so, subject to the following conditions:
1208
- //
1209
- // The above copyright notice and this permission notice shall be included in
1210
- // all copies or substantial portions of the Software.
1211
- //
1212
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1213
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1214
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1215
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1216
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1217
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1218
- // THE SOFTWARE.
1219
- //
1220
-
1221
- /**
1222
- * @class easyXDM.Socket
1223
- * This class creates a transport channel between two domains that is usable for sending and receiving string-based messages.<br/>
1224
- * The channel is reliable, supports queueing, and ensures that the message originates from the expected domain.<br/>
1225
- * Internally different stacks will be used depending on the browsers features and the available parameters.
1226
- * <h2>How to set up</h2>
1227
- * Setting up the provider:
1228
- * <pre><code>
1229
- * var socket = new easyXDM.Socket({
1230
- * &nbsp; local: "name.html",
1231
- * &nbsp; onReady: function(){
1232
- * &nbsp; &nbsp; &#47;&#47; you need to wait for the onReady callback before using the socket
1233
- * &nbsp; &nbsp; socket.postMessage("foo-message");
1234
- * &nbsp; },
1235
- * &nbsp; onMessage: function(message, origin) {
1236
- * &nbsp;&nbsp; alert("received " + message + " from " + origin);
1237
- * &nbsp; }
1238
- * });
1239
- * </code></pre>
1240
- * Setting up the consumer:
1241
- * <pre><code>
1242
- * var socket = new easyXDM.Socket({
1243
- * &nbsp; remote: "http:&#47;&#47;remotedomain/page.html",
1244
- * &nbsp; remoteHelper: "http:&#47;&#47;remotedomain/name.html",
1245
- * &nbsp; onReady: function(){
1246
- * &nbsp; &nbsp; &#47;&#47; you need to wait for the onReady callback before using the socket
1247
- * &nbsp; &nbsp; socket.postMessage("foo-message");
1248
- * &nbsp; },
1249
- * &nbsp; onMessage: function(message, origin) {
1250
- * &nbsp;&nbsp; alert("received " + message + " from " + origin);
1251
- * &nbsp; }
1252
- * });
1253
- * </code></pre>
1254
- * If you are unable to upload the <code>name.html</code> file to the consumers domain then remove the <code>remoteHelper</code> property
1255
- * and easyXDM will fall back to using the HashTransport instead of the NameTransport when not able to use any of the primary transports.
1256
- * @namespace easyXDM
1257
- * @constructor
1258
- * @cfg {String/Window} local The url to the local name.html document, a local static file, or a reference to the local window.
1259
- * @cfg {Boolean} lazy (Consumer only) Set this to true if you want easyXDM to defer creating the transport until really needed.
1260
- * @cfg {String} remote (Consumer only) The url to the providers document.
1261
- * @cfg {String} remoteHelper (Consumer only) The url to the remote name.html file. This is to support NameTransport as a fallback. Optional.
1262
- * @cfg {Number} delay The number of milliseconds easyXDM should try to get a reference to the local window. Optional, defaults to 2000.
1263
- * @cfg {Number} interval The interval used when polling for messages. Optional, defaults to 300.
1264
- * @cfg {String} channel (Consumer only) The name of the channel to use. Can be used to set consistent iframe names. Must be unique. Optional.
1265
- * @cfg {Function} onMessage The method that should handle incoming messages.<br/> This method should accept two arguments, the message as a string, and the origin as a string. Optional.
1266
- * @cfg {Function} onReady A method that should be called when the transport is ready. Optional.
1267
- * @cfg {DOMElement|String} container (Consumer only) The element, or the id of the element that the primary iframe should be inserted into. If not set then the iframe will be positioned off-screen. Optional.
1268
- * @cfg {Array/String} acl (Provider only) Here you can specify which '[protocol]://[domain]' patterns that should be allowed to act as the consumer towards this provider.<br/>
1269
- * This can contain the wildcards ? and *. Examples are 'http://example.com', '*.foo.com' and '*dom?.com'. If you want to use reqular expressions then you pattern needs to start with ^ and end with $.
1270
- * If none of the patterns match an Error will be thrown.
1271
- * @cfg {Object} props (Consumer only) Additional properties that should be applied to the iframe. This can also contain nested objects e.g: <code>{style:{width:"100px", height:"100px"}}</code>.
1272
- * Properties such as 'name' and 'src' will be overrided. Optional.
1273
- */
1274
- easyXDM.Socket = function(config){
1275
- var trace = debug.getTracer("easyXDM.Socket");
1276
- trace("constructor");
1277
-
1278
- // create the stack
1279
- var stack = chainStack(prepareTransportStack(config).concat([{
1280
- incoming: function(message, origin){
1281
- config.onMessage(message, origin);
1282
- },
1283
- callback: function(success){
1284
- if (config.onReady) {
1285
- config.onReady(success);
1286
- }
1287
- }
1288
- }])), recipient = getLocation(config.remote);
1289
-
1290
- // set the origin
1291
- this.origin = getLocation(config.remote);
1292
-
1293
- /**
1294
- * Initiates the destruction of the stack.
1295
- */
1296
- this.destroy = function(){
1297
- stack.destroy();
1298
- };
1299
-
1300
- /**
1301
- * Posts a message to the remote end of the channel
1302
- * @param {String} message The message to send
1303
- */
1304
- this.postMessage = function(message){
1305
- stack.outgoing(message, recipient);
1306
- };
1307
-
1308
- stack.init();
1309
- };
1310
- /*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
1311
- /*global easyXDM, window, escape, unescape, undef,, chainStack, prepareTransportStack, debug, getLocation */
1312
- //
1313
- // easyXDM
1314
- // http://easyxdm.net/
1315
- // Copyright(c) 2009-2011, Øyvind Sean Kinsey, oyvind@kinsey.no.
1316
- //
1317
- // Permission is hereby granted, free of charge, to any person obtaining a copy
1318
- // of this software and associated documentation files (the "Software"), to deal
1319
- // in the Software without restriction, including without limitation the rights
1320
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1321
- // copies of the Software, and to permit persons to whom the Software is
1322
- // furnished to do so, subject to the following conditions:
1323
- //
1324
- // The above copyright notice and this permission notice shall be included in
1325
- // all copies or substantial portions of the Software.
1326
- //
1327
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1328
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1329
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1330
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1331
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1332
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1333
- // THE SOFTWARE.
1334
- //
1335
-
1336
- /**
1337
- * @class easyXDM.Rpc
1338
- * Creates a proxy object that can be used to call methods implemented on the remote end of the channel, and also to provide the implementation
1339
- * of methods to be called from the remote end.<br/>
1340
- * The instantiated object will have methods matching those specified in <code>config.remote</code>.<br/>
1341
- * This requires the JSON object present in the document, either natively, using json.org's json2 or as a wrapper around library spesific methods.
1342
- * <h2>How to set up</h2>
1343
- * <pre><code>
1344
- * var rpc = new easyXDM.Rpc({
1345
- * &nbsp; &#47;&#47; this configuration is equal to that used by the Socket.
1346
- * &nbsp; remote: "http:&#47;&#47;remotedomain/...",
1347
- * &nbsp; onReady: function(){
1348
- * &nbsp; &nbsp; &#47;&#47; you need to wait for the onReady callback before using the proxy
1349
- * &nbsp; &nbsp; rpc.foo(...
1350
- * &nbsp; }
1351
- * },{
1352
- * &nbsp; local: {..},
1353
- * &nbsp; remote: {..}
1354
- * });
1355
- * </code></pre>
1356
- *
1357
- * <h2>Exposing functions (procedures)</h2>
1358
- * <pre><code>
1359
- * var rpc = new easyXDM.Rpc({
1360
- * &nbsp; ...
1361
- * },{
1362
- * &nbsp; local: {
1363
- * &nbsp; &nbsp; nameOfMethod: {
1364
- * &nbsp; &nbsp; &nbsp; method: function(arg1, arg2, success, error){
1365
- * &nbsp; &nbsp; &nbsp; &nbsp; ...
1366
- * &nbsp; &nbsp; &nbsp; }
1367
- * &nbsp; &nbsp; },
1368
- * &nbsp; &nbsp; &#47;&#47; with shorthand notation
1369
- * &nbsp; &nbsp; nameOfAnotherMethod: function(arg1, arg2, success, error){
1370
- * &nbsp; &nbsp; }
1371
- * &nbsp; },
1372
- * &nbsp; remote: {...}
1373
- * });
1374
- * </code></pre>
1375
-
1376
- * The function referenced by [method] will receive the passed arguments followed by the callback functions <code>success</code> and <code>error</code>.<br/>
1377
- * To send a successfull result back you can use
1378
- * <pre><code>
1379
- * return foo;
1380
- * </pre></code>
1381
- * or
1382
- * <pre><code>
1383
- * success(foo);
1384
- * </pre></code>
1385
- * To return an error you can use
1386
- * <pre><code>
1387
- * throw new Error("foo error");
1388
- * </code></pre>
1389
- * or
1390
- * <pre><code>
1391
- * error("foo error");
1392
- * </code></pre>
1393
- *
1394
- * <h2>Defining remotely exposed methods (procedures/notifications)</h2>
1395
- * The definition of the remote end is quite similar:
1396
- * <pre><code>
1397
- * var rpc = new easyXDM.Rpc({
1398
- * &nbsp; ...
1399
- * },{
1400
- * &nbsp; local: {...},
1401
- * &nbsp; remote: {
1402
- * &nbsp; &nbsp; nameOfMethod: {}
1403
- * &nbsp; }
1404
- * });
1405
- * </code></pre>
1406
- * To call a remote method use
1407
- * <pre><code>
1408
- * rpc.nameOfMethod("arg1", "arg2", function(value) {
1409
- * &nbsp; alert("success: " + value);
1410
- * }, function(message) {
1411
- * &nbsp; alert("error: " + message + );
1412
- * });
1413
- * </code></pre>
1414
- * Both the <code>success</code> and <code>errror</code> callbacks are optional.<br/>
1415
- * When called with no callback a JSON-RPC 2.0 notification will be executed.
1416
- * Be aware that you will not be notified of any errors with this method.
1417
- * <br/>
1418
- * <h2>Specifying a custom serializer</h2>
1419
- * If you do not want to use the JSON2 library for non-native JSON support, but instead capabilities provided by some other library
1420
- * then you can specify a custom serializer using <code>serializer: foo</code>
1421
- * <pre><code>
1422
- * var rpc = new easyXDM.Rpc({
1423
- * &nbsp; ...
1424
- * },{
1425
- * &nbsp; local: {...},
1426
- * &nbsp; remote: {...},
1427
- * &nbsp; serializer : {
1428
- * &nbsp; &nbsp; parse: function(string){ ... },
1429
- * &nbsp; &nbsp; stringify: function(object) {...}
1430
- * &nbsp; }
1431
- * });
1432
- * </code></pre>
1433
- * If <code>serializer</code> is set then the class will not attempt to use the native implementation.
1434
- * @namespace easyXDM
1435
- * @constructor
1436
- * @param {Object} config The underlying transports configuration. See easyXDM.Socket for available parameters.
1437
- * @param {Object} jsonRpcConfig The description of the interface to implement.
1438
- */
1439
- easyXDM.Rpc = function(config, jsonRpcConfig){
1440
- var trace = debug.getTracer("easyXDM.Rpc");
1441
- trace("constructor");
1442
-
1443
- // expand shorthand notation
1444
- if (jsonRpcConfig.local) {
1445
- for (var method in jsonRpcConfig.local) {
1446
- if (jsonRpcConfig.local.hasOwnProperty(method)) {
1447
- var member = jsonRpcConfig.local[method];
1448
- if (typeof member === "function") {
1449
- jsonRpcConfig.local[method] = {
1450
- method: member
1451
- };
1452
- }
1453
- }
1454
- }
1455
- }
1456
-
1457
- // create the stack
1458
- var stack = chainStack(prepareTransportStack(config).concat([new easyXDM.stack.RpcBehavior(this, jsonRpcConfig), {
1459
- callback: function(success){
1460
- if (config.onReady) {
1461
- config.onReady(success);
1462
- }
1463
- }
1464
- }]));
1465
-
1466
- // set the origin
1467
- this.origin = getLocation(config.remote);
1468
-
1469
-
1470
- /**
1471
- * Initiates the destruction of the stack.
1472
- */
1473
- this.destroy = function(){
1474
- stack.destroy();
1475
- };
1476
-
1477
- stack.init();
1478
- };
1479
- /*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
1480
- /*global easyXDM, window, escape, unescape, getLocation, appendQueryParameters, createFrame, debug, un, on, apply, whenReady, getParentObject, IFRAME_PREFIX*/
1481
- //
1482
- // easyXDM
1483
- // http://easyxdm.net/
1484
- // Copyright(c) 2009-2011, Øyvind Sean Kinsey, oyvind@kinsey.no.
1485
- //
1486
- // Permission is hereby granted, free of charge, to any person obtaining a copy
1487
- // of this software and associated documentation files (the "Software"), to deal
1488
- // in the Software without restriction, including without limitation the rights
1489
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1490
- // copies of the Software, and to permit persons to whom the Software is
1491
- // furnished to do so, subject to the following conditions:
1492
- //
1493
- // The above copyright notice and this permission notice shall be included in
1494
- // all copies or substantial portions of the Software.
1495
- //
1496
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1497
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1498
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1499
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1500
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1501
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1502
- // THE SOFTWARE.
1503
- //
1504
-
1505
- /**
1506
- * @class easyXDM.stack.SameOriginTransport
1507
- * SameOriginTransport is a transport class that can be used when both domains have the same origin.<br/>
1508
- * This can be useful for testing and for when the main application supports both internal and external sources.
1509
- * @namespace easyXDM.stack
1510
- * @constructor
1511
- * @param {Object} config The transports configuration.
1512
- * @cfg {String} remote The remote document to communicate with.
1513
- */
1514
- easyXDM.stack.SameOriginTransport = function(config){
1515
- var trace = debug.getTracer("easyXDM.stack.SameOriginTransport");
1516
- trace("constructor");
1517
- var pub, frame, send, targetOrigin;
1518
-
1519
- return (pub = {
1520
- outgoing: function(message, domain, fn){
1521
- send(message);
1522
- if (fn) {
1523
- fn();
1524
- }
1525
- },
1526
- destroy: function(){
1527
- trace("destroy");
1528
- if (frame) {
1529
- frame.parentNode.removeChild(frame);
1530
- frame = null;
1531
- }
1532
- },
1533
- onDOMReady: function(){
1534
- trace("init");
1535
- targetOrigin = getLocation(config.remote);
1536
-
1537
- if (config.isHost) {
1538
- // set up the iframe
1539
- apply(config.props, {
1540
- src: appendQueryParameters(config.remote, {
1541
- xdm_e: location.protocol + "//" + location.host + location.pathname,
1542
- xdm_c: config.channel,
1543
- xdm_p: 4 // 4 = SameOriginTransport
1544
- }),
1545
- name: IFRAME_PREFIX + config.channel + "_provider"
1546
- });
1547
- frame = createFrame(config);
1548
- easyXDM.Fn.set(config.channel, function(sendFn){
1549
- send = sendFn;
1550
- setTimeout(function(){
1551
- pub.up.callback(true);
1552
- }, 0);
1553
- return function(msg){
1554
- pub.up.incoming(msg, targetOrigin);
1555
- };
1556
- });
1557
- }
1558
- else {
1559
- send = getParentObject().Fn.get(config.channel, true)(function(msg){
1560
- pub.up.incoming(msg, targetOrigin);
1561
- });
1562
- setTimeout(function(){
1563
- pub.up.callback(true);
1564
- }, 0);
1565
- }
1566
- },
1567
- init: function(){
1568
- whenReady(pub.onDOMReady, pub);
1569
- }
1570
- });
1571
- };
1572
- /*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
1573
- /*global global, easyXDM, window, getLocation, appendQueryParameters, createFrame, debug, apply, whenReady, IFRAME_PREFIX, namespace, resolveUrl, getDomainName, HAS_FLASH_THROTTLED_BUG, getPort, query*/
1574
- //
1575
- // easyXDM
1576
- // http://easyxdm.net/
1577
- // Copyright(c) 2009-2011, Øyvind Sean Kinsey, oyvind@kinsey.no.
1578
- //
1579
- // Permission is hereby granted, free of charge, to any person obtaining a copy
1580
- // of this software and associated documentation files (the "Software"), to deal
1581
- // in the Software without restriction, including without limitation the rights
1582
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1583
- // copies of the Software, and to permit persons to whom the Software is
1584
- // furnished to do so, subject to the following conditions:
1585
- //
1586
- // The above copyright notice and this permission notice shall be included in
1587
- // all copies or substantial portions of the Software.
1588
- //
1589
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1590
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1591
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1592
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1593
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1594
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1595
- // THE SOFTWARE.
1596
- //
1597
-
1598
- /**
1599
- * @class easyXDM.stack.FlashTransport
1600
- * FlashTransport is a transport class that uses an SWF with LocalConnection to pass messages back and forth.
1601
- * @namespace easyXDM.stack
1602
- * @constructor
1603
- * @param {Object} config The transports configuration.
1604
- * @cfg {String} remote The remote domain to communicate with.
1605
- * @cfg {String} secret the pre-shared secret used to secure the communication.
1606
- * @cfg {String} swf The path to the swf file
1607
- * @cfg {Boolean} swfNoThrottle Set this to true if you want to take steps to avoid beeing throttled when hidden.
1608
- * @cfg {String || DOMElement} swfContainer Set this if you want to control where the swf is placed
1609
- */
1610
- easyXDM.stack.FlashTransport = function(config){
1611
- var trace = debug.getTracer("easyXDM.stack.FlashTransport");
1612
- trace("constructor");
1613
- if (!config.swf) {
1614
- throw new Error("Path to easyxdm.swf is missing");
1615
- }
1616
- var pub, // the public interface
1617
- frame, send, targetOrigin, swf, swfContainer;
1618
-
1619
- function onMessage(message, origin){
1620
- setTimeout(function(){
1621
- trace("received message");
1622
- pub.up.incoming(message, targetOrigin);
1623
- }, 0);
1624
- }
1625
-
1626
- /**
1627
- * This method adds the SWF to the DOM and prepares the initialization of the channel
1628
- */
1629
- function addSwf(domain){
1630
- trace("creating factory with SWF from " + domain);
1631
- // the differentiating query argument is needed in Flash9 to avoid a caching issue where LocalConnection would throw an error.
1632
- var url = config.swf + "?host=" + config.isHost;
1633
- var id = "easyXDM_swf_" + Math.floor(Math.random() * 10000);
1634
-
1635
- // prepare the init function that will fire once the swf is ready
1636
- easyXDM.Fn.set("flash_loaded" + domain.replace(/[\-.]/g, "_"), function(){
1637
- easyXDM.stack.FlashTransport[domain].swf = swf = swfContainer.firstChild;
1638
- var queue = easyXDM.stack.FlashTransport[domain].queue;
1639
- for (var i = 0; i < queue.length; i++) {
1640
- queue[i]();
1641
- }
1642
- queue.length = 0;
1643
- });
1644
-
1645
- if (config.swfContainer) {
1646
- swfContainer = (typeof config.swfContainer == "string") ? document.getElementById(config.swfContainer) : config.swfContainer;
1647
- }
1648
- else {
1649
- // create the container that will hold the swf
1650
- swfContainer = document.createElement('div');
1651
-
1652
- // http://bugs.adobe.com/jira/browse/FP-4796
1653
- // http://tech.groups.yahoo.com/group/flexcoders/message/162365
1654
- // https://groups.google.com/forum/#!topic/easyxdm/mJZJhWagoLc
1655
- apply(swfContainer.style, HAS_FLASH_THROTTLED_BUG && config.swfNoThrottle ? {
1656
- height: "20px",
1657
- width: "20px",
1658
- position: "fixed",
1659
- right: 0,
1660
- top: 0
1661
- } : {
1662
- height: "1px",
1663
- width: "1px",
1664
- position: "absolute",
1665
- overflow: "hidden",
1666
- right: 0,
1667
- top: 0
1668
- });
1669
- document.body.appendChild(swfContainer);
1670
- }
1671
-
1672
- // create the object/embed
1673
- var flashVars = "callback=flash_loaded" + domain.replace(/[\-.]/g, "_") + "&proto=" + global.location.protocol + "&domain=" + getDomainName(global.location.href) + "&port=" + getPort(global.location.href) + "&ns=" + namespace;
1674
- flashVars += "&log=true";
1675
- swfContainer.innerHTML = "<object height='20' width='20' type='application/x-shockwave-flash' id='" + id + "' data='" + url + "'>" +
1676
- "<param name='allowScriptAccess' value='always'></param>" +
1677
- "<param name='wmode' value='transparent'>" +
1678
- "<param name='movie' value='" +
1679
- url +
1680
- "'></param>" +
1681
- "<param name='flashvars' value='" +
1682
- flashVars +
1683
- "'></param>" +
1684
- "<embed type='application/x-shockwave-flash' FlashVars='" +
1685
- flashVars +
1686
- "' allowScriptAccess='always' wmode='transparent' src='" +
1687
- url +
1688
- "' height='1' width='1'></embed>" +
1689
- "</object>";
1690
- }
1691
-
1692
- return (pub = {
1693
- outgoing: function(message, domain, fn){
1694
- swf.postMessage(config.channel, message.toString());
1695
- if (fn) {
1696
- fn();
1697
- }
1698
- },
1699
- destroy: function(){
1700
- trace("destroy");
1701
- try {
1702
- swf.destroyChannel(config.channel);
1703
- }
1704
- catch (e) {
1705
- }
1706
- swf = null;
1707
- if (frame) {
1708
- frame.parentNode.removeChild(frame);
1709
- frame = null;
1710
- }
1711
- },
1712
- onDOMReady: function(){
1713
- trace("init");
1714
-
1715
- targetOrigin = config.remote;
1716
-
1717
- // Prepare the code that will be run after the swf has been intialized
1718
- easyXDM.Fn.set("flash_" + config.channel + "_init", function(){
1719
- setTimeout(function(){
1720
- trace("firing onReady");
1721
- pub.up.callback(true);
1722
- });
1723
- });
1724
-
1725
- // set up the omMessage handler
1726
- easyXDM.Fn.set("flash_" + config.channel + "_onMessage", onMessage);
1727
-
1728
- config.swf = resolveUrl(config.swf); // reports have been made of requests gone rogue when using relative paths
1729
- var swfdomain = getDomainName(config.swf);
1730
- var fn = function(){
1731
- // set init to true in case the fn was called was invoked from a separate instance
1732
- easyXDM.stack.FlashTransport[swfdomain].init = true;
1733
- swf = easyXDM.stack.FlashTransport[swfdomain].swf;
1734
- // create the channel
1735
- swf.createChannel(config.channel, config.secret, getLocation(config.remote), config.isHost);
1736
-
1737
- if (config.isHost) {
1738
- // if Flash is going to be throttled and we want to avoid this
1739
- if (HAS_FLASH_THROTTLED_BUG && config.swfNoThrottle) {
1740
- apply(config.props, {
1741
- position: "fixed",
1742
- right: 0,
1743
- top: 0,
1744
- height: "20px",
1745
- width: "20px"
1746
- });
1747
- }
1748
- // set up the iframe
1749
- apply(config.props, {
1750
- src: appendQueryParameters(config.remote, {
1751
- xdm_e: getLocation(location.href),
1752
- xdm_c: config.channel,
1753
- xdm_p: 6, // 6 = FlashTransport
1754
- xdm_s: config.secret
1755
- }),
1756
- name: IFRAME_PREFIX + config.channel + "_provider"
1757
- });
1758
- frame = createFrame(config);
1759
- }
1760
- };
1761
-
1762
- if (easyXDM.stack.FlashTransport[swfdomain] && easyXDM.stack.FlashTransport[swfdomain].init) {
1763
- // if the swf is in place and we are the consumer
1764
- fn();
1765
- }
1766
- else {
1767
- // if the swf does not yet exist
1768
- if (!easyXDM.stack.FlashTransport[swfdomain]) {
1769
- // add the queue to hold the init fn's
1770
- easyXDM.stack.FlashTransport[swfdomain] = {
1771
- queue: [fn]
1772
- };
1773
- addSwf(swfdomain);
1774
- }
1775
- else {
1776
- easyXDM.stack.FlashTransport[swfdomain].queue.push(fn);
1777
- }
1778
- }
1779
- },
1780
- init: function(){
1781
- whenReady(pub.onDOMReady, pub);
1782
- }
1783
- });
1784
- };
1785
- /*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
1786
- /*global easyXDM, window, escape, unescape, getLocation, appendQueryParameters, createFrame, debug, un, on, apply, whenReady, IFRAME_PREFIX*/
1787
- //
1788
- // easyXDM
1789
- // http://easyxdm.net/
1790
- // Copyright(c) 2009-2011, Øyvind Sean Kinsey, oyvind@kinsey.no.
1791
- //
1792
- // Permission is hereby granted, free of charge, to any person obtaining a copy
1793
- // of this software and associated documentation files (the "Software"), to deal
1794
- // in the Software without restriction, including without limitation the rights
1795
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1796
- // copies of the Software, and to permit persons to whom the Software is
1797
- // furnished to do so, subject to the following conditions:
1798
- //
1799
- // The above copyright notice and this permission notice shall be included in
1800
- // all copies or substantial portions of the Software.
1801
- //
1802
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1803
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1804
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1805
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1806
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1807
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1808
- // THE SOFTWARE.
1809
- //
1810
-
1811
- /**
1812
- * @class easyXDM.stack.PostMessageTransport
1813
- * PostMessageTransport is a transport class that uses HTML5 postMessage for communication.<br/>
1814
- * <a href="http://msdn.microsoft.com/en-us/library/ms644944(VS.85).aspx">http://msdn.microsoft.com/en-us/library/ms644944(VS.85).aspx</a><br/>
1815
- * <a href="https://developer.mozilla.org/en/DOM/window.postMessage">https://developer.mozilla.org/en/DOM/window.postMessage</a>
1816
- * @namespace easyXDM.stack
1817
- * @constructor
1818
- * @param {Object} config The transports configuration.
1819
- * @cfg {String} remote The remote domain to communicate with.
1820
- */
1821
- easyXDM.stack.PostMessageTransport = function(config){
1822
- var trace = debug.getTracer("easyXDM.stack.PostMessageTransport");
1823
- trace("constructor");
1824
- var pub, // the public interface
1825
- frame, // the remote frame, if any
1826
- callerWindow, // the window that we will call with
1827
- targetOrigin; // the domain to communicate with
1828
- /**
1829
- * Resolves the origin from the event object
1830
- * @private
1831
- * @param {Object} event The messageevent
1832
- * @return {String} The scheme, host and port of the origin
1833
- */
1834
- function _getOrigin(event){
1835
- if (event.origin) {
1836
- // This is the HTML5 property
1837
- return getLocation(event.origin);
1838
- }
1839
- if (event.uri) {
1840
- // From earlier implementations
1841
- return getLocation(event.uri);
1842
- }
1843
- if (event.domain) {
1844
- // This is the last option and will fail if the
1845
- // origin is not using the same schema as we are
1846
- return location.protocol + "//" + event.domain;
1847
- }
1848
- throw "Unable to retrieve the origin of the event";
1849
- }
1850
-
1851
- /**
1852
- * This is the main implementation for the onMessage event.<br/>
1853
- * It checks the validity of the origin and passes the message on if appropriate.
1854
- * @private
1855
- * @param {Object} event The messageevent
1856
- */
1857
- function _window_onMessage(event){
1858
- var origin = _getOrigin(event);
1859
- trace("received message '" + event.data + "' from " + origin);
1860
- if (origin == targetOrigin && event.data.substring(0, config.channel.length + 1) == config.channel + " ") {
1861
- pub.up.incoming(event.data.substring(config.channel.length + 1), origin);
1862
- }
1863
- }
1864
-
1865
- return (pub = {
1866
- outgoing: function(message, domain, fn){
1867
- callerWindow.postMessage(config.channel + " " + message, domain || targetOrigin);
1868
- if (fn) {
1869
- fn();
1870
- }
1871
- },
1872
- destroy: function(){
1873
- trace("destroy");
1874
- un(window, "message", _window_onMessage);
1875
- if (frame) {
1876
- callerWindow = null;
1877
- frame.parentNode.removeChild(frame);
1878
- frame = null;
1879
- }
1880
- },
1881
- onDOMReady: function(){
1882
- trace("init");
1883
- targetOrigin = getLocation(config.remote);
1884
- if (config.isHost) {
1885
- // add the event handler for listening
1886
- var waitForReady = function(event){
1887
- if (event.data == config.channel + "-ready") {
1888
- trace("firing onReady");
1889
- // replace the eventlistener
1890
- callerWindow = ("postMessage" in frame.contentWindow) ? frame.contentWindow : frame.contentWindow.document;
1891
- un(window, "message", waitForReady);
1892
- on(window, "message", _window_onMessage);
1893
- setTimeout(function(){
1894
- pub.up.callback(true);
1895
- }, 0);
1896
- }
1897
- };
1898
- on(window, "message", waitForReady);
1899
-
1900
- // set up the iframe
1901
- apply(config.props, {
1902
- src: appendQueryParameters(config.remote, {
1903
- xdm_e: getLocation(location.href),
1904
- xdm_c: config.channel,
1905
- xdm_p: 1 // 1 = PostMessage
1906
- }),
1907
- name: IFRAME_PREFIX + config.channel + "_provider"
1908
- });
1909
- frame = createFrame(config);
1910
- }
1911
- else {
1912
- // add the event handler for listening
1913
- on(window, "message", _window_onMessage);
1914
- callerWindow = ("postMessage" in window.parent) ? window.parent : window.parent.document;
1915
- callerWindow.postMessage(config.channel + "-ready", targetOrigin);
1916
-
1917
- setTimeout(function(){
1918
- pub.up.callback(true);
1919
- }, 0);
1920
- }
1921
- },
1922
- init: function(){
1923
- whenReady(pub.onDOMReady, pub);
1924
- }
1925
- });
1926
- };
1927
- /*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
1928
- /*global easyXDM, window, escape, unescape, getLocation, appendQueryParameters, createFrame, debug, apply, query, whenReady, IFRAME_PREFIX*/
1929
- //
1930
- // easyXDM
1931
- // http://easyxdm.net/
1932
- // Copyright(c) 2009-2011, Øyvind Sean Kinsey, oyvind@kinsey.no.
1933
- //
1934
- // Permission is hereby granted, free of charge, to any person obtaining a copy
1935
- // of this software and associated documentation files (the "Software"), to deal
1936
- // in the Software without restriction, including without limitation the rights
1937
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1938
- // copies of the Software, and to permit persons to whom the Software is
1939
- // furnished to do so, subject to the following conditions:
1940
- //
1941
- // The above copyright notice and this permission notice shall be included in
1942
- // all copies or substantial portions of the Software.
1943
- //
1944
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1945
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1946
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1947
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1948
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1949
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1950
- // THE SOFTWARE.
1951
- //
1952
-
1953
- /**
1954
- * @class easyXDM.stack.FrameElementTransport
1955
- * FrameElementTransport is a transport class that can be used with Gecko-browser as these allow passing variables using the frameElement property.<br/>
1956
- * Security is maintained as Gecho uses Lexical Authorization to determine under which scope a function is running.
1957
- * @namespace easyXDM.stack
1958
- * @constructor
1959
- * @param {Object} config The transports configuration.
1960
- * @cfg {String} remote The remote document to communicate with.
1961
- */
1962
- easyXDM.stack.FrameElementTransport = function(config){
1963
- var trace = debug.getTracer("easyXDM.stack.FrameElementTransport");
1964
- trace("constructor");
1965
- var pub, frame, send, targetOrigin;
1966
-
1967
- return (pub = {
1968
- outgoing: function(message, domain, fn){
1969
- send.call(this, message);
1970
- if (fn) {
1971
- fn();
1972
- }
1973
- },
1974
- destroy: function(){
1975
- trace("destroy");
1976
- if (frame) {
1977
- frame.parentNode.removeChild(frame);
1978
- frame = null;
1979
- }
1980
- },
1981
- onDOMReady: function(){
1982
- trace("init");
1983
- targetOrigin = getLocation(config.remote);
1984
-
1985
- if (config.isHost) {
1986
- // set up the iframe
1987
- apply(config.props, {
1988
- src: appendQueryParameters(config.remote, {
1989
- xdm_e: getLocation(location.href),
1990
- xdm_c: config.channel,
1991
- xdm_p: 5 // 5 = FrameElementTransport
1992
- }),
1993
- name: IFRAME_PREFIX + config.channel + "_provider"
1994
- });
1995
- frame = createFrame(config);
1996
- frame.fn = function(sendFn){
1997
- delete frame.fn;
1998
- send = sendFn;
1999
- setTimeout(function(){
2000
- pub.up.callback(true);
2001
- }, 0);
2002
- // remove the function so that it cannot be used to overwrite the send function later on
2003
- return function(msg){
2004
- pub.up.incoming(msg, targetOrigin);
2005
- };
2006
- };
2007
- }
2008
- else {
2009
- // This is to mitigate origin-spoofing
2010
- if (document.referrer && getLocation(document.referrer) != query.xdm_e) {
2011
- window.top.location = query.xdm_e;
2012
- }
2013
- send = window.frameElement.fn(function(msg){
2014
- pub.up.incoming(msg, targetOrigin);
2015
- });
2016
- pub.up.callback(true);
2017
- }
2018
- },
2019
- init: function(){
2020
- whenReady(pub.onDOMReady, pub);
2021
- }
2022
- });
2023
- };
2024
- /*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
2025
- /*global easyXDM, window, escape, unescape, undef, getLocation, appendQueryParameters, resolveUrl, createFrame, debug, un, apply, whenReady, IFRAME_PREFIX*/
2026
- //
2027
- // easyXDM
2028
- // http://easyxdm.net/
2029
- // Copyright(c) 2009-2011, Øyvind Sean Kinsey, oyvind@kinsey.no.
2030
- //
2031
- // Permission is hereby granted, free of charge, to any person obtaining a copy
2032
- // of this software and associated documentation files (the "Software"), to deal
2033
- // in the Software without restriction, including without limitation the rights
2034
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2035
- // copies of the Software, and to permit persons to whom the Software is
2036
- // furnished to do so, subject to the following conditions:
2037
- //
2038
- // The above copyright notice and this permission notice shall be included in
2039
- // all copies or substantial portions of the Software.
2040
- //
2041
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2042
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2043
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2044
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2045
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2046
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2047
- // THE SOFTWARE.
2048
- //
2049
-
2050
- /**
2051
- * @class easyXDM.stack.NameTransport
2052
- * NameTransport uses the window.name property to relay data.
2053
- * The <code>local</code> parameter needs to be set on both the consumer and provider,<br/>
2054
- * and the <code>remoteHelper</code> parameter needs to be set on the consumer.
2055
- * @constructor
2056
- * @param {Object} config The transports configuration.
2057
- * @cfg {String} remoteHelper The url to the remote instance of hash.html - this is only needed for the host.
2058
- * @namespace easyXDM.stack
2059
- */
2060
- easyXDM.stack.NameTransport = function(config){
2061
- var trace = debug.getTracer("easyXDM.stack.NameTransport");
2062
- trace("constructor");
2063
- if (config.isHost && undef(config.remoteHelper)) {
2064
- trace("missing remoteHelper");
2065
- throw new Error("missing remoteHelper");
2066
- }
2067
-
2068
- var pub; // the public interface
2069
- var isHost, callerWindow, remoteWindow, readyCount, callback, remoteOrigin, remoteUrl;
2070
-
2071
- function _sendMessage(message){
2072
- var url = config.remoteHelper + (isHost ? "#_3" : "#_2") + config.channel;
2073
- trace("sending message " + message);
2074
- trace("navigating to '" + url + "'");
2075
- callerWindow.contentWindow.sendMessage(message, url);
2076
- }
2077
-
2078
- function _onReady(){
2079
- if (isHost) {
2080
- if (++readyCount === 2 || !isHost) {
2081
- pub.up.callback(true);
2082
- }
2083
- }
2084
- else {
2085
- _sendMessage("ready");
2086
- trace("calling onReady");
2087
- pub.up.callback(true);
2088
- }
2089
- }
2090
-
2091
- function _onMessage(message){
2092
- trace("received message " + message);
2093
- pub.up.incoming(message, remoteOrigin);
2094
- }
2095
-
2096
- function _onLoad(){
2097
- if (callback) {
2098
- setTimeout(function(){
2099
- callback(true);
2100
- }, 0);
2101
- }
2102
- }
2103
-
2104
- return (pub = {
2105
- outgoing: function(message, domain, fn){
2106
- callback = fn;
2107
- _sendMessage(message);
2108
- },
2109
- destroy: function(){
2110
- trace("destroy");
2111
- callerWindow.parentNode.removeChild(callerWindow);
2112
- callerWindow = null;
2113
- if (isHost) {
2114
- remoteWindow.parentNode.removeChild(remoteWindow);
2115
- remoteWindow = null;
2116
- }
2117
- },
2118
- onDOMReady: function(){
2119
- trace("init");
2120
- isHost = config.isHost;
2121
- readyCount = 0;
2122
- remoteOrigin = getLocation(config.remote);
2123
- config.local = resolveUrl(config.local);
2124
-
2125
- if (isHost) {
2126
- // Register the callback
2127
- easyXDM.Fn.set(config.channel, function(message){
2128
- trace("received initial message " + message);
2129
- if (isHost && message === "ready") {
2130
- // Replace the handler
2131
- easyXDM.Fn.set(config.channel, _onMessage);
2132
- _onReady();
2133
- }
2134
- });
2135
-
2136
- // Set up the frame that points to the remote instance
2137
- remoteUrl = appendQueryParameters(config.remote, {
2138
- xdm_e: config.local,
2139
- xdm_c: config.channel,
2140
- xdm_p: 2
2141
- });
2142
- apply(config.props, {
2143
- src: remoteUrl + '#' + config.channel,
2144
- name: IFRAME_PREFIX + config.channel + "_provider"
2145
- });
2146
- remoteWindow = createFrame(config);
2147
- }
2148
- else {
2149
- config.remoteHelper = config.remote;
2150
- easyXDM.Fn.set(config.channel, _onMessage);
2151
- }
2152
-
2153
- // Set up the iframe that will be used for the transport
2154
- var onLoad = function(){
2155
- // Remove the handler
2156
- var w = callerWindow || this;
2157
- un(w, "load", onLoad);
2158
- easyXDM.Fn.set(config.channel + "_load", _onLoad);
2159
- (function test(){
2160
- if (typeof w.contentWindow.sendMessage == "function") {
2161
- _onReady();
2162
- }
2163
- else {
2164
- setTimeout(test, 50);
2165
- }
2166
- }());
2167
- };
2168
-
2169
- callerWindow = createFrame({
2170
- props: {
2171
- src: config.local + "#_4" + config.channel
2172
- },
2173
- onLoad: onLoad
2174
- });
2175
- },
2176
- init: function(){
2177
- whenReady(pub.onDOMReady, pub);
2178
- }
2179
- });
2180
- };
2181
- /*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
2182
- /*global easyXDM, window, escape, unescape, getLocation, createFrame, debug, un, on, apply, whenReady, IFRAME_PREFIX*/
2183
- //
2184
- // easyXDM
2185
- // http://easyxdm.net/
2186
- // Copyright(c) 2009-2011, Øyvind Sean Kinsey, oyvind@kinsey.no.
2187
- //
2188
- // Permission is hereby granted, free of charge, to any person obtaining a copy
2189
- // of this software and associated documentation files (the "Software"), to deal
2190
- // in the Software without restriction, including without limitation the rights
2191
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2192
- // copies of the Software, and to permit persons to whom the Software is
2193
- // furnished to do so, subject to the following conditions:
2194
- //
2195
- // The above copyright notice and this permission notice shall be included in
2196
- // all copies or substantial portions of the Software.
2197
- //
2198
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2199
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2200
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2201
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2202
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2203
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2204
- // THE SOFTWARE.
2205
- //
2206
-
2207
- /**
2208
- * @class easyXDM.stack.HashTransport
2209
- * HashTransport is a transport class that uses the IFrame URL Technique for communication.<br/>
2210
- * <a href="http://msdn.microsoft.com/en-us/library/bb735305.aspx">http://msdn.microsoft.com/en-us/library/bb735305.aspx</a><br/>
2211
- * @namespace easyXDM.stack
2212
- * @constructor
2213
- * @param {Object} config The transports configuration.
2214
- * @cfg {String/Window} local The url to the local file used for proxying messages, or the local window.
2215
- * @cfg {Number} delay The number of milliseconds easyXDM should try to get a reference to the local window.
2216
- * @cfg {Number} interval The interval used when polling for messages.
2217
- */
2218
- easyXDM.stack.HashTransport = function(config){
2219
- var trace = debug.getTracer("easyXDM.stack.HashTransport");
2220
- trace("constructor");
2221
- var pub;
2222
- var me = this, isHost, _timer, pollInterval, _lastMsg, _msgNr, _listenerWindow, _callerWindow;
2223
- var useParent, _remoteOrigin;
2224
-
2225
- function _sendMessage(message){
2226
- trace("sending message '" + (_msgNr + 1) + " " + message + "' to " + _remoteOrigin);
2227
- if (!_callerWindow) {
2228
- trace("no caller window");
2229
- return;
2230
- }
2231
- var url = config.remote + "#" + (_msgNr++) + "_" + message;
2232
- ((isHost || !useParent) ? _callerWindow.contentWindow : _callerWindow).location = url;
2233
- }
2234
-
2235
- function _handleHash(hash){
2236
- _lastMsg = hash;
2237
- trace("received message '" + _lastMsg + "' from " + _remoteOrigin);
2238
- pub.up.incoming(_lastMsg.substring(_lastMsg.indexOf("_") + 1), _remoteOrigin);
2239
- }
2240
-
2241
- /**
2242
- * Checks location.hash for a new message and relays this to the receiver.
2243
- * @private
2244
- */
2245
- function _pollHash(){
2246
- if (!_listenerWindow) {
2247
- return;
2248
- }
2249
- var href = _listenerWindow.location.href, hash = "", indexOf = href.indexOf("#");
2250
- if (indexOf != -1) {
2251
- hash = href.substring(indexOf);
2252
- }
2253
- if (hash && hash != _lastMsg) {
2254
- trace("poll: new message");
2255
- _handleHash(hash);
2256
- }
2257
- }
2258
-
2259
- function _attachListeners(){
2260
- trace("starting polling");
2261
- _timer = setInterval(_pollHash, pollInterval);
2262
- }
2263
-
2264
- return (pub = {
2265
- outgoing: function(message, domain){
2266
- _sendMessage(message);
2267
- },
2268
- destroy: function(){
2269
- window.clearInterval(_timer);
2270
- if (isHost || !useParent) {
2271
- _callerWindow.parentNode.removeChild(_callerWindow);
2272
- }
2273
- _callerWindow = null;
2274
- },
2275
- onDOMReady: function(){
2276
- isHost = config.isHost;
2277
- pollInterval = config.interval;
2278
- _lastMsg = "#" + config.channel;
2279
- _msgNr = 0;
2280
- useParent = config.useParent;
2281
- _remoteOrigin = getLocation(config.remote);
2282
- if (isHost) {
2283
- apply(config.props, {
2284
- src: config.remote,
2285
- name: IFRAME_PREFIX + config.channel + "_provider"
2286
- });
2287
- if (useParent) {
2288
- config.onLoad = function(){
2289
- _listenerWindow = window;
2290
- _attachListeners();
2291
- pub.up.callback(true);
2292
- };
2293
- }
2294
- else {
2295
- var tries = 0, max = config.delay / 50;
2296
- (function getRef(){
2297
- if (++tries > max) {
2298
- trace("unable to get reference to _listenerWindow, giving up");
2299
- throw new Error("Unable to reference listenerwindow");
2300
- }
2301
- try {
2302
- _listenerWindow = _callerWindow.contentWindow.frames[IFRAME_PREFIX + config.channel + "_consumer"];
2303
- }
2304
- catch (ex) {
2305
- }
2306
- if (_listenerWindow) {
2307
- _attachListeners();
2308
- trace("got a reference to _listenerWindow");
2309
- pub.up.callback(true);
2310
- }
2311
- else {
2312
- setTimeout(getRef, 50);
2313
- }
2314
- }());
2315
- }
2316
- _callerWindow = createFrame(config);
2317
- }
2318
- else {
2319
- _listenerWindow = window;
2320
- _attachListeners();
2321
- if (useParent) {
2322
- _callerWindow = parent;
2323
- pub.up.callback(true);
2324
- }
2325
- else {
2326
- apply(config, {
2327
- props: {
2328
- src: config.remote + "#" + config.channel + new Date(),
2329
- name: IFRAME_PREFIX + config.channel + "_consumer"
2330
- },
2331
- onLoad: function(){
2332
- pub.up.callback(true);
2333
- }
2334
- });
2335
- _callerWindow = createFrame(config);
2336
- }
2337
- }
2338
- },
2339
- init: function(){
2340
- whenReady(pub.onDOMReady, pub);
2341
- }
2342
- });
2343
- };
2344
- /*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
2345
- /*global easyXDM, window, escape, unescape, debug */
2346
- //
2347
- // easyXDM
2348
- // http://easyxdm.net/
2349
- // Copyright(c) 2009-2011, Øyvind Sean Kinsey, oyvind@kinsey.no.
2350
- //
2351
- // Permission is hereby granted, free of charge, to any person obtaining a copy
2352
- // of this software and associated documentation files (the "Software"), to deal
2353
- // in the Software without restriction, including without limitation the rights
2354
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2355
- // copies of the Software, and to permit persons to whom the Software is
2356
- // furnished to do so, subject to the following conditions:
2357
- //
2358
- // The above copyright notice and this permission notice shall be included in
2359
- // all copies or substantial portions of the Software.
2360
- //
2361
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2362
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2363
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2364
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2365
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2366
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2367
- // THE SOFTWARE.
2368
- //
2369
-
2370
- /**
2371
- * @class easyXDM.stack.ReliableBehavior
2372
- * This is a behavior that tries to make the underlying transport reliable by using acknowledgements.
2373
- * @namespace easyXDM.stack
2374
- * @constructor
2375
- * @param {Object} config The behaviors configuration.
2376
- */
2377
- easyXDM.stack.ReliableBehavior = function(config){
2378
- var trace = debug.getTracer("easyXDM.stack.ReliableBehavior");
2379
- trace("constructor");
2380
- var pub, // the public interface
2381
- callback; // the callback to execute when we have a confirmed success/failure
2382
- var idOut = 0, idIn = 0, currentMessage = "";
2383
-
2384
- return (pub = {
2385
- incoming: function(message, origin){
2386
- trace("incoming: " + message);
2387
- var indexOf = message.indexOf("_"), ack = message.substring(0, indexOf).split(",");
2388
- message = message.substring(indexOf + 1);
2389
-
2390
- if (ack[0] == idOut) {
2391
- trace("message delivered");
2392
- currentMessage = "";
2393
- if (callback) {
2394
- callback(true);
2395
- callback = null;
2396
- }
2397
- }
2398
- if (message.length > 0) {
2399
- trace("sending ack, and passing on " + message);
2400
- pub.down.outgoing(ack[1] + "," + idOut + "_" + currentMessage, origin);
2401
- if (idIn != ack[1]) {
2402
- idIn = ack[1];
2403
- pub.up.incoming(message, origin);
2404
- }
2405
- }
2406
-
2407
- },
2408
- outgoing: function(message, origin, fn){
2409
- currentMessage = message;
2410
- callback = fn;
2411
- pub.down.outgoing(idIn + "," + (++idOut) + "_" + message, origin);
2412
- }
2413
- });
2414
- };
2415
- /*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
2416
- /*global easyXDM, window, escape, unescape, debug, undef, removeFromStack*/
2417
- //
2418
- // easyXDM
2419
- // http://easyxdm.net/
2420
- // Copyright(c) 2009-2011, Øyvind Sean Kinsey, oyvind@kinsey.no.
2421
- //
2422
- // Permission is hereby granted, free of charge, to any person obtaining a copy
2423
- // of this software and associated documentation files (the "Software"), to deal
2424
- // in the Software without restriction, including without limitation the rights
2425
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2426
- // copies of the Software, and to permit persons to whom the Software is
2427
- // furnished to do so, subject to the following conditions:
2428
- //
2429
- // The above copyright notice and this permission notice shall be included in
2430
- // all copies or substantial portions of the Software.
2431
- //
2432
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2433
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2434
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2435
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2436
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2437
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2438
- // THE SOFTWARE.
2439
- //
2440
-
2441
- /**
2442
- * @class easyXDM.stack.QueueBehavior
2443
- * This is a behavior that enables queueing of messages. <br/>
2444
- * It will buffer incoming messages and dispach these as fast as the underlying transport allows.
2445
- * This will also fragment/defragment messages so that the outgoing message is never bigger than the
2446
- * set length.
2447
- * @namespace easyXDM.stack
2448
- * @constructor
2449
- * @param {Object} config The behaviors configuration. Optional.
2450
- * @cfg {Number} maxLength The maximum length of each outgoing message. Set this to enable fragmentation.
2451
- */
2452
- easyXDM.stack.QueueBehavior = function(config){
2453
- var trace = debug.getTracer("easyXDM.stack.QueueBehavior");
2454
- trace("constructor");
2455
- var pub, queue = [], waiting = true, incoming = "", destroying, maxLength = 0, lazy = false, doFragment = false;
2456
-
2457
- function dispatch(){
2458
- if (config.remove && queue.length === 0) {
2459
- trace("removing myself from the stack");
2460
- removeFromStack(pub);
2461
- return;
2462
- }
2463
- if (waiting || queue.length === 0 || destroying) {
2464
- return;
2465
- }
2466
- trace("dispatching from queue");
2467
- waiting = true;
2468
- var message = queue.shift();
2469
-
2470
- pub.down.outgoing(message.data, message.origin, function(success){
2471
- waiting = false;
2472
- if (message.callback) {
2473
- setTimeout(function(){
2474
- message.callback(success);
2475
- }, 0);
2476
- }
2477
- dispatch();
2478
- });
2479
- }
2480
- return (pub = {
2481
- init: function(){
2482
- if (undef(config)) {
2483
- config = {};
2484
- }
2485
- if (config.maxLength) {
2486
- maxLength = config.maxLength;
2487
- doFragment = true;
2488
- }
2489
- if (config.lazy) {
2490
- lazy = true;
2491
- }
2492
- else {
2493
- pub.down.init();
2494
- }
2495
- },
2496
- callback: function(success){
2497
- waiting = false;
2498
- var up = pub.up; // in case dispatch calls removeFromStack
2499
- dispatch();
2500
- up.callback(success);
2501
- },
2502
- incoming: function(message, origin){
2503
- if (doFragment) {
2504
- var indexOf = message.indexOf("_"), seq = parseInt(message.substring(0, indexOf), 10);
2505
- incoming += message.substring(indexOf + 1);
2506
- if (seq === 0) {
2507
- trace("received the last fragment");
2508
- if (config.encode) {
2509
- incoming = decodeURIComponent(incoming);
2510
- }
2511
- pub.up.incoming(incoming, origin);
2512
- incoming = "";
2513
- }
2514
- else {
2515
- trace("waiting for more fragments, seq=" + message);
2516
- }
2517
- }
2518
- else {
2519
- pub.up.incoming(message, origin);
2520
- }
2521
- },
2522
- outgoing: function(message, origin, fn){
2523
- if (config.encode) {
2524
- message = encodeURIComponent(message);
2525
- }
2526
- var fragments = [], fragment;
2527
- if (doFragment) {
2528
- // fragment into chunks
2529
- while (message.length !== 0) {
2530
- fragment = message.substring(0, maxLength);
2531
- message = message.substring(fragment.length);
2532
- fragments.push(fragment);
2533
- }
2534
- // enqueue the chunks
2535
- while ((fragment = fragments.shift())) {
2536
- trace("enqueuing");
2537
- queue.push({
2538
- data: fragments.length + "_" + fragment,
2539
- origin: origin,
2540
- callback: fragments.length === 0 ? fn : null
2541
- });
2542
- }
2543
- }
2544
- else {
2545
- queue.push({
2546
- data: message,
2547
- origin: origin,
2548
- callback: fn
2549
- });
2550
- }
2551
- if (lazy) {
2552
- pub.down.init();
2553
- }
2554
- else {
2555
- dispatch();
2556
- }
2557
- },
2558
- destroy: function(){
2559
- trace("destroy");
2560
- destroying = true;
2561
- pub.down.destroy();
2562
- }
2563
- });
2564
- };
2565
- /*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
2566
- /*global easyXDM, window, escape, unescape, undef, debug */
2567
- //
2568
- // easyXDM
2569
- // http://easyxdm.net/
2570
- // Copyright(c) 2009-2011, Øyvind Sean Kinsey, oyvind@kinsey.no.
2571
- //
2572
- // Permission is hereby granted, free of charge, to any person obtaining a copy
2573
- // of this software and associated documentation files (the "Software"), to deal
2574
- // in the Software without restriction, including without limitation the rights
2575
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2576
- // copies of the Software, and to permit persons to whom the Software is
2577
- // furnished to do so, subject to the following conditions:
2578
- //
2579
- // The above copyright notice and this permission notice shall be included in
2580
- // all copies or substantial portions of the Software.
2581
- //
2582
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2583
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2584
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2585
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2586
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2587
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2588
- // THE SOFTWARE.
2589
- //
2590
-
2591
- /**
2592
- * @class easyXDM.stack.VerifyBehavior
2593
- * This behavior will verify that communication with the remote end is possible, and will also sign all outgoing,
2594
- * and verify all incoming messages. This removes the risk of someone hijacking the iframe to send malicious messages.
2595
- * @namespace easyXDM.stack
2596
- * @constructor
2597
- * @param {Object} config The behaviors configuration.
2598
- * @cfg {Boolean} initiate If the verification should be initiated from this end.
2599
- */
2600
- easyXDM.stack.VerifyBehavior = function(config){
2601
- var trace = debug.getTracer("easyXDM.stack.VerifyBehavior");
2602
- trace("constructor");
2603
- if (undef(config.initiate)) {
2604
- throw new Error("settings.initiate is not set");
2605
- }
2606
- var pub, mySecret, theirSecret, verified = false;
2607
-
2608
- function startVerification(){
2609
- trace("requesting verification");
2610
- mySecret = Math.random().toString(16).substring(2);
2611
- pub.down.outgoing(mySecret);
2612
- }
2613
-
2614
- return (pub = {
2615
- incoming: function(message, origin){
2616
- var indexOf = message.indexOf("_");
2617
- if (indexOf === -1) {
2618
- if (message === mySecret) {
2619
- trace("verified, calling callback");
2620
- pub.up.callback(true);
2621
- }
2622
- else if (!theirSecret) {
2623
- trace("returning secret");
2624
- theirSecret = message;
2625
- if (!config.initiate) {
2626
- startVerification();
2627
- }
2628
- pub.down.outgoing(message);
2629
- }
2630
- }
2631
- else {
2632
- if (message.substring(0, indexOf) === theirSecret) {
2633
- pub.up.incoming(message.substring(indexOf + 1), origin);
2634
- }
2635
- }
2636
- },
2637
- outgoing: function(message, origin, fn){
2638
- pub.down.outgoing(mySecret + "_" + message, origin, fn);
2639
- },
2640
- callback: function(success){
2641
- if (config.initiate) {
2642
- startVerification();
2643
- }
2644
- }
2645
- });
2646
- };
2647
- /*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
2648
- /*global easyXDM, window, escape, unescape, undef, getJSON, debug, emptyFn, isArray */
2649
- //
2650
- // easyXDM
2651
- // http://easyxdm.net/
2652
- // Copyright(c) 2009-2011, Øyvind Sean Kinsey, oyvind@kinsey.no.
2653
- //
2654
- // Permission is hereby granted, free of charge, to any person obtaining a copy
2655
- // of this software and associated documentation files (the "Software"), to deal
2656
- // in the Software without restriction, including without limitation the rights
2657
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2658
- // copies of the Software, and to permit persons to whom the Software is
2659
- // furnished to do so, subject to the following conditions:
2660
- //
2661
- // The above copyright notice and this permission notice shall be included in
2662
- // all copies or substantial portions of the Software.
2663
- //
2664
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2665
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2666
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2667
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2668
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2669
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2670
- // THE SOFTWARE.
2671
- //
2672
-
2673
- /**
2674
- * @class easyXDM.stack.RpcBehavior
2675
- * This uses JSON-RPC 2.0 to expose local methods and to invoke remote methods and have responses returned over the the string based transport stack.<br/>
2676
- * Exposed methods can return values synchronous, asyncronous, or bet set up to not return anything.
2677
- * @namespace easyXDM.stack
2678
- * @constructor
2679
- * @param {Object} proxy The object to apply the methods to.
2680
- * @param {Object} config The definition of the local and remote interface to implement.
2681
- * @cfg {Object} local The local interface to expose.
2682
- * @cfg {Object} remote The remote methods to expose through the proxy.
2683
- * @cfg {Object} serializer The serializer to use for serializing and deserializing the JSON. Should be compatible with the HTML5 JSON object. Optional, will default to JSON.
2684
- */
2685
- easyXDM.stack.RpcBehavior = function(proxy, config){
2686
- var trace = debug.getTracer("easyXDM.stack.RpcBehavior");
2687
- var pub, serializer = config.serializer || getJSON();
2688
- var _callbackCounter = 0, _callbacks = {};
2689
-
2690
- /**
2691
- * Serializes and sends the message
2692
- * @private
2693
- * @param {Object} data The JSON-RPC message to be sent. The jsonrpc property will be added.
2694
- */
2695
- function _send(data){
2696
- data.jsonrpc = "2.0";
2697
- pub.down.outgoing(serializer.stringify(data));
2698
- }
2699
-
2700
- /**
2701
- * Creates a method that implements the given definition
2702
- * @private
2703
- * @param {Object} The method configuration
2704
- * @param {String} method The name of the method
2705
- * @return {Function} A stub capable of proxying the requested method call
2706
- */
2707
- function _createMethod(definition, method){
2708
- var slice = Array.prototype.slice;
2709
-
2710
- trace("creating method " + method);
2711
- return function(){
2712
- trace("executing method " + method);
2713
- var l = arguments.length, callback, message = {
2714
- method: method
2715
- };
2716
-
2717
- if (l > 0 && typeof arguments[l - 1] === "function") {
2718
- //with callback, procedure
2719
- if (l > 1 && typeof arguments[l - 2] === "function") {
2720
- // two callbacks, success and error
2721
- callback = {
2722
- success: arguments[l - 2],
2723
- error: arguments[l - 1]
2724
- };
2725
- message.params = slice.call(arguments, 0, l - 2);
2726
- }
2727
- else {
2728
- // single callback, success
2729
- callback = {
2730
- success: arguments[l - 1]
2731
- };
2732
- message.params = slice.call(arguments, 0, l - 1);
2733
- }
2734
- _callbacks["" + (++_callbackCounter)] = callback;
2735
- message.id = _callbackCounter;
2736
- }
2737
- else {
2738
- // no callbacks, a notification
2739
- message.params = slice.call(arguments, 0);
2740
- }
2741
- if (definition.namedParams && message.params.length === 1) {
2742
- message.params = message.params[0];
2743
- }
2744
- // Send the method request
2745
- _send(message);
2746
- };
2747
- }
2748
-
2749
- /**
2750
- * Executes the exposed method
2751
- * @private
2752
- * @param {String} method The name of the method
2753
- * @param {Number} id The callback id to use
2754
- * @param {Function} method The exposed implementation
2755
- * @param {Array} params The parameters supplied by the remote end
2756
- */
2757
- function _executeMethod(method, id, fn, params){
2758
- if (!fn) {
2759
- trace("requested to execute non-existent procedure " + method);
2760
- if (id) {
2761
- _send({
2762
- id: id,
2763
- error: {
2764
- code: -32601,
2765
- message: "Procedure not found."
2766
- }
2767
- });
2768
- }
2769
- return;
2770
- }
2771
-
2772
- trace("requested to execute procedure " + method);
2773
- var success, error;
2774
- if (id) {
2775
- success = function(result){
2776
- success = emptyFn;
2777
- _send({
2778
- id: id,
2779
- result: result
2780
- });
2781
- };
2782
- error = function(message, data){
2783
- error = emptyFn;
2784
- var msg = {
2785
- id: id,
2786
- error: {
2787
- code: -32099,
2788
- message: message
2789
- }
2790
- };
2791
- if (data) {
2792
- msg.error.data = data;
2793
- }
2794
- _send(msg);
2795
- };
2796
- }
2797
- else {
2798
- success = error = emptyFn;
2799
- }
2800
- // Call local method
2801
- if (!isArray(params)) {
2802
- params = [params];
2803
- }
2804
- try {
2805
- var result = fn.method.apply(fn.scope, params.concat([success, error]));
2806
- if (!undef(result)) {
2807
- success(result);
2808
- }
2809
- }
2810
- catch (ex1) {
2811
- error(ex1.message);
2812
- }
2813
- }
2814
-
2815
- return (pub = {
2816
- incoming: function(message, origin){
2817
- var data = serializer.parse(message);
2818
- if (data.method) {
2819
- trace("received request to execute method " + data.method + (data.id ? (" using callback id " + data.id) : ""));
2820
- // A method call from the remote end
2821
- if (config.handle) {
2822
- config.handle(data, _send);
2823
- }
2824
- else {
2825
- _executeMethod(data.method, data.id, config.local[data.method], data.params);
2826
- }
2827
- }
2828
- else {
2829
- trace("received return value destined to callback with id " + data.id);
2830
- // A method response from the other end
2831
- var callback = _callbacks[data.id];
2832
- if (data.error) {
2833
- if (callback.error) {
2834
- callback.error(data.error);
2835
- }
2836
- else {
2837
- trace("unhandled error returned.");
2838
- }
2839
- }
2840
- else if (callback.success) {
2841
- callback.success(data.result);
2842
- }
2843
- delete _callbacks[data.id];
2844
- }
2845
- },
2846
- init: function(){
2847
- trace("init");
2848
- if (config.remote) {
2849
- trace("creating stubs");
2850
- // Implement the remote sides exposed methods
2851
- for (var method in config.remote) {
2852
- if (config.remote.hasOwnProperty(method)) {
2853
- proxy[method] = _createMethod(config.remote[method], method);
2854
- }
2855
- }
2856
- }
2857
- pub.down.init();
2858
- },
2859
- destroy: function(){
2860
- trace("destroy");
2861
- for (var method in config.remote) {
2862
- if (config.remote.hasOwnProperty(method) && proxy.hasOwnProperty(method)) {
2863
- delete proxy[method];
2864
- }
2865
- }
2866
- pub.down.destroy();
2867
- }
2868
- });
2869
- };
2870
- global.easyXDM = easyXDM;
2871
- })(window, document, location, window.setTimeout, decodeURIComponent, encodeURIComponent);