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