1 /**
  2 * Copyright (c) 2014, salesforce.com, inc.
  3 * All rights reserved.
  4 *
  5 * Redistribution and use in source and binary forms, with or without modification, are permitted provided
  6 * that the following conditions are met:
  7 *
  8 * Redistributions of source code must retain the above copyright notice, this list of conditions and the
  9 * following disclaimer.
 10 *
 11 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
 12 * the following disclaimer in the documentation and/or other materials provided with the distribution.
 13 *
 14 * Neither the name of salesforce.com, inc. nor the names of its contributors may be used to endorse or
 15 * promote products derived from this software without specific prior written permission.
 16 *
 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 19 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 21 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 23 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 24 * POSSIBILITY OF SUCH DAMAGE.
 25 */
 26 
 27 (function(global) {
 28   if(global.Sfdc && global.Sfdc.canvas && global.Sfdc.canvas.module) {
 29     return
 30   }
 31   var extmodules = {};
 32   if(global.Sfdc && global.Sfdc.canvas) {
 33     for(var key in global.Sfdc.canvas) {
 34       if(global.Sfdc.canvas.hasOwnProperty(key)) {
 35         extmodules[key] = global.Sfdc.canvas[key]
 36       }
 37     }
 38   }
 39   var oproto = Object.prototype, aproto = Array.prototype, doc = global.document, keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\x3d", $ = {hasOwn:function(obj, prop) {
 40     return oproto.hasOwnProperty.call(obj, prop)
 41   }, isUndefined:function(value) {
 42     var undef;
 43     return value === undef
 44   }, isNil:function(value) {
 45     return $.isUndefined(value) || value === null || value === ""
 46   }, isNumber:function(value) {
 47     return!!(value === 0 || value && value.toExponential && value.toFixed)
 48   }, isFunction:function(value) {
 49     return!!(value && value.constructor && value.call && value.apply)
 50   }, isArray:Array.isArray || function(value) {
 51     return oproto.toString.call(value) === "[object Array]"
 52   }, isArguments:function(value) {
 53     return!!(value && $.hasOwn(value, "callee"))
 54   }, isObject:function(value) {
 55     return value !== null && typeof value === "object"
 56   }, isString:function(value) {
 57     return value !== null && typeof value == "string"
 58   }, appearsJson:function(value) {
 59     return/^\{.*\}$/.test(value)
 60   }, nop:function() {
 61   }, invoker:function(fn) {
 62     if($.isFunction(fn)) {
 63       fn()
 64     }
 65   }, identity:function(obj) {
 66     return obj
 67   }, each:function(obj, it, ctx) {
 68     if($.isNil(obj)) {
 69       return
 70     }
 71     var nativ = aproto.forEach, i = 0, l, key;
 72     l = obj.length;
 73     ctx = ctx || obj;
 74     if(nativ && nativ === obj.forEach) {
 75       obj.forEach(it, ctx)
 76     }else {
 77       if($.isNumber(l)) {
 78         while(i < l) {
 79           if(it.call(ctx, obj[i], i, obj) === false) {
 80             return
 81           }
 82           i += 1
 83         }
 84       }else {
 85         for(key in obj) {
 86           if($.hasOwn(obj, key) && it.call(ctx, obj[key], key, obj) === false) {
 87             return
 88           }
 89         }
 90       }
 91     }
 92   }, startsWithHttp:function(orig, newUrl) {
 93     return!$.isString(orig) ? orig : orig.substring(0, 4) === "http" ? orig : newUrl
 94   }, map:function(obj, it, ctx) {
 95     var results = [], nativ = aproto.map;
 96     if($.isNil(obj)) {
 97       return results
 98     }
 99     if(nativ && obj.map === nativ) {
100       return obj.map(it, ctx)
101     }
102     ctx = ctx || obj;
103     $.each(obj, function(value, i, list) {
104       results.push(it.call(ctx, value, i, list))
105     });
106     return results
107   }, values:function(obj) {
108     return $.map(obj, $.identity)
109   }, slice:function(array, begin, end) {
110     return aproto.slice.call(array, $.isUndefined(begin) ? 0 : begin, $.isUndefined(end) ? array.length : end)
111   }, toArray:function(iterable) {
112     if(!iterable) {
113       return[]
114     }
115     if(iterable.toArray) {
116       return iterable.toArray
117     }
118     if($.isArray(iterable)) {
119       return iterable
120     }
121     if($.isArguments(iterable)) {
122       return $.slice(iterable)
123     }
124     return $.values(iterable)
125   }, size:function(obj) {
126     return $.toArray(obj).length
127   }, indexOf:function(array, item) {
128     var nativ = aproto.indexOf, i, l;
129     if(!array) {
130       return-1
131     }
132     if(nativ && array.indexOf === nativ) {
133       return array.indexOf(item)
134     }
135     for(i = 0, l = array.length;i < l;i += 1) {
136       if(array[i] === item) {
137         return i
138       }
139     }
140     return-1
141   }, isEmpty:function(obj) {
142     if(obj === null) {
143       return true
144     }
145     if($.isArray(obj) || $.isString(obj)) {
146       return obj.length === 0
147     }
148     for(var key in obj) {
149       if($.hasOwn(obj, key)) {
150         return false
151       }
152     }
153     return true
154   }, remove:function(array, item) {
155     var i = $.indexOf(array, item);
156     if(i >= 0) {
157       array.splice(i, 1)
158     }
159   }, param:function(a, encode) {
160     var s = [];
161     encode = encode || false;
162     function add(key, value) {
163       if($.isNil(value)) {
164         return
165       }
166       value = $.isFunction(value) ? value() : value;
167       if($.isArray(value)) {
168         $.each(value, function(v, n) {
169           add(key, v)
170         })
171       }else {
172         if(encode) {
173           s[s.length] = encodeURIComponent(key) + "\x3d" + encodeURIComponent(value)
174         }else {
175           s[s.length] = key + "\x3d" + value
176         }
177       }
178     }
179     if($.isArray(a)) {
180       $.each(a, function(v, n) {
181         add(n, v)
182       })
183     }else {
184       for(var p in a) {
185         if($.hasOwn(a, p)) {
186           add(p, a[p])
187         }
188       }
189     }
190     return s.join("\x26").replace(/%20/g, "+")
191   }, objectify:function(q) {
192     var arr, obj = {}, i, p, n, v, e;
193     if($.isNil(q)) {
194       return obj
195     }
196     if(q.substring(0, 1) == "?") {
197       q = q.substring(1)
198     }
199     arr = q.split("\x26");
200     for(i = 0;i < arr.length;i += 1) {
201       p = arr[i].split("\x3d");
202       n = p[0];
203       v = p[1];
204       e = obj[n];
205       if(!$.isNil(e)) {
206         if($.isArray(e)) {
207           e[e.length] = v
208         }else {
209           obj[n] = [];
210           obj[n][0] = e;
211           obj[n][1] = v
212         }
213       }else {
214         obj[n] = v
215       }
216     }
217     return obj
218   }, stripUrl:function(url) {
219     return $.isNil(url) ? null : url.replace(/([^:]+:\/\/[^\/\?#]+).*/, "$1")
220   }, query:function(url, q) {
221     if($.isNil(q)) {
222       return url
223     }
224     url = url.replace(/#.*$/, "");
225     url += /^\#/.test(q) ? q : (/\?/.test(url) ? "\x26" : "?") + q;
226     return url
227   }, extend:function(dest) {
228     $.each($.slice(arguments, 1), function(mixin, i) {
229       $.each(mixin, function(value, key) {
230         dest[key] = value
231       })
232     });
233     return dest
234   }, endsWith:function(str, suffix) {
235     return str.indexOf(suffix, str.length - suffix.length) !== -1
236   }, capitalize:function(str) {
237     return str.charAt(0).toUpperCase() + str.slice(1)
238   }, uncapitalize:function(str) {
239     return str.charAt(0).toLowerCase() + str.slice(1)
240   }, decode:function(str) {
241     var output = [], chr1, chr2, chr3 = "", enc1, enc2, enc3, enc4 = "", i = 0;
242     str = str.replace(/[^A-Za-z0-9\+\/\=]/g, "");
243     do {
244       enc1 = keyStr.indexOf(str.charAt(i++));
245       enc2 = keyStr.indexOf(str.charAt(i++));
246       enc3 = keyStr.indexOf(str.charAt(i++));
247       enc4 = keyStr.indexOf(str.charAt(i++));
248       chr1 = enc1 << 2 | enc2 >> 4;
249       chr2 = (enc2 & 15) << 4 | enc3 >> 2;
250       chr3 = (enc3 & 3) << 6 | enc4;
251       output.push(String.fromCharCode(chr1));
252       if(enc3 !== 64) {
253         output.push(String.fromCharCode(chr2))
254       }
255       if(enc4 !== 64) {
256         output.push(String.fromCharCode(chr3))
257       }
258       chr1 = chr2 = chr3 = "";
259       enc1 = enc2 = enc3 = enc4 = ""
260     }while(i < str.length);
261     return output.join("")
262   }, validEventName:function(name, res) {
263     var ns, parts = name.split(/\./), regex = /^[$A-Z_][0-9A-Z_$]*$/i, reserved = {"sfdc":true, "canvas":true, "force":true, "salesforce":true, "chatter":true};
264     $.each($.isArray(res) ? res : [res], function(v) {
265       reserved[v] = false
266     });
267     if(parts.length > 2) {
268       return 1
269     }
270     if(parts.length === 2) {
271       ns = parts[0].toLowerCase();
272       if(reserved[ns]) {
273         return 2
274       }
275     }
276     if(!regex.test(parts[0]) || !regex.test(parts[1])) {
277       return 3
278     }
279     return 0
280   }, prototypeOf:function(obj) {
281     var nativ = Object.getPrototypeOf, proto = "__proto__";
282     if($.isFunction(nativ)) {
283       return nativ.call(Object, obj)
284     }else {
285       if(typeof{}[proto] === "object") {
286         return obj[proto]
287       }else {
288         return obj.constructor.prototype
289       }
290     }
291   }, module:function(ns, decl) {
292     var parts = ns.split("."), parent = global.Sfdc.canvas, i, length;
293     if(parts[1] === "canvas") {
294       parts = parts.slice(2)
295     }
296     length = parts.length;
297     for(i = 0;i < length;i += 1) {
298       if($.isUndefined(parent[parts[i]])) {
299         parent[parts[i]] = {}
300       }
301       parent = parent[parts[i]]
302     }
303     if($.isFunction(decl)) {
304       decl = decl()
305     }
306     return $.extend(parent, decl)
307   }, document:function() {
308     return doc
309   }, byId:function(id) {
310     return doc.getElementById(id)
311   }, byClass:function(clazz) {
312     return doc.getElementsByClassName(clazz)
313   }, attr:function(el, name) {
314     var a = el.attributes, i;
315     for(i = 0;i < a.length;i += 1) {
316       if(name === a[i].name) {
317         return a[i].value
318       }
319     }
320   }, onReady:function(cb) {
321     if($.isFunction(cb)) {
322       readyHandlers.push(cb)
323     }
324   }, console:function() {
325     var enabled = false;
326     if(window && !window.console) {
327       window.console = {}
328     }
329     if(window && !window.console.log) {
330       window.console.log = function() {
331       }
332     }
333     if(window && !window.console.error) {
334       window.console.error = function() {
335       }
336     }
337     function isSessionStorage() {
338       try {
339         return"sessionStorage" in window && window.sessionStorage !== null
340       }catch(e) {
341         return false
342       }
343     }
344     function log() {
345     }
346     function error() {
347     }
348     function activate() {
349       if(Function.prototype.bind) {
350         log = Function.prototype.bind.call(console.log, console);
351         error = Function.prototype.bind.call(console.error, console)
352       }else {
353         log = function() {
354           Function.prototype.apply.call(console.log, console, arguments)
355         };
356         error = function() {
357           Function.prototype.apply.call(console.error, console, arguments)
358         }
359       }
360     }
361     function deactivate() {
362       log = function() {
363       };
364       error = function() {
365       }
366     }
367     function enable() {
368       enabled = true;
369       if(isSessionStorage()) {
370         sessionStorage.setItem("canvas_console", "true")
371       }
372       activate()
373     }
374     function disable() {
375       enabled = false;
376       if(isSessionStorage()) {
377         sessionStorage.setItem("canvas_console", "false")
378       }
379       deactivate()
380     }
381     enabled = isSessionStorage() && sessionStorage.getItem("canvas_console") === "true";
382     if(enabled) {
383       activate()
384     }else {
385       deactivate()
386     }
387     return{enable:enable, disable:disable, log:log, error:error}
388   }()}, readyHandlers = [], canvas = function(cb) {
389     if($.isFunction(cb)) {
390       readyHandlers.push(cb)
391     }
392   };
393   (function() {
394     var called = false, isFrame, fn;
395     function ready() {
396       if(called) {
397         return
398       }
399       called = true;
400       ready = $.nop;
401       $.each(readyHandlers, $.invoker);
402       readyHandlers = []
403     }
404     function tryScroll() {
405       if(called) {
406         return
407       }
408       try {
409         document.documentElement.doScroll("left");
410         ready()
411       }catch(e) {
412         setTimeout(tryScroll, 30)
413       }
414     }
415     if(document.addEventListener) {
416       document.addEventListener("DOMContentLoaded", ready, false)
417     }else {
418       if(document.attachEvent) {
419         try {
420           isFrame = self !== top
421         }catch(e) {
422         }
423         if(document.documentElement.doScroll && !isFrame) {
424           tryScroll()
425         }
426         document.attachEvent("onreadystatechange", function() {
427           if(document.readyState === "complete") {
428             ready()
429           }
430         })
431       }
432     }
433     if(window.addEventListener) {
434       window.addEventListener("load", ready, false)
435     }else {
436       if(window.attachEvent) {
437         window.attachEvent("onload", ready)
438       }else {
439         fn = window.onload;
440         window.onload = function() {
441           if(fn) {
442             fn()
443           }
444           ready()
445         }
446       }
447     }
448   })();
449   $.each($, function(fn, name) {
450     canvas[name] = fn
451   });
452   $.each(extmodules, function(fn, name) {
453     canvas[name] = fn
454   });
455   (function() {
456     var method;
457     var noop = function() {
458     };
459     var methods = ["assert", "clear", "count", "debug", "dir", "dirxml", "error", "exception", "group", "groupCollapsed", "groupEnd", "info", "log", "markTimeline", "profile", "profileEnd", "table", "time", "timeEnd", "timeStamp", "trace", "warn"];
460     var length = methods.length;
461     var console = typeof window !== "undefined" && window.console ? window.console : {};
462     while(length--) {
463       method = methods[length];
464       if(!console[method]) {
465         console[method] = noop
466       }
467     }
468   })();
469   if(!global.Sfdc) {
470     global.Sfdc = {}
471   }
472   global.Sfdc.canvas = canvas
473 })(this);
474 (function($$) {
475   var module = function() {
476     function isSecure() {
477       return window.location.protocol === "https:"
478     }
479     function set(name, value, days) {
480       var expires = "", date;
481       if(days) {
482         date = new Date;
483         date.setTime(date.getTime() + days * 24 * 60 * 60 * 1E3);
484         expires = "; expires\x3d" + date.toGMTString()
485       }else {
486         expires = ""
487       }
488       document.cookie = name + "\x3d" + value + expires + "; path\x3d/" + (isSecure() === true ? "; secure" : "")
489     }
490     function get(name) {
491       var nameEQ, ca, c, i;
492       if($$.isUndefined(name)) {
493         return document.cookie.split(";")
494       }
495       nameEQ = name + "\x3d";
496       ca = document.cookie.split(";");
497       for(i = 0;i < ca.length;i += 1) {
498         c = ca[i];
499         while(c.charAt(0) === " ") {
500           c = c.substring(1, c.length)
501         }
502         if(c.indexOf(nameEQ) === 0) {
503           return c.substring(nameEQ.length, c.length)
504         }
505       }
506       return null
507     }
508     function remove(name) {
509       set(name, "", -1)
510     }
511     return{set:set, get:get, remove:remove}
512   }();
513   $$.module("Sfdc.canvas.cookies", module)
514 })(Sfdc.canvas);
515 (function($$) {
516   var module = function() {
517     var accessToken, instUrl, instId, tOrigin, childWindow;
518     function init() {
519       accessToken = $$.cookies.get("access_token");
520       $$.cookies.remove("access_token")
521     }
522     function query(params) {
523       var r = [], n;
524       if(!$$.isUndefined(params)) {
525         for(n in params) {
526           if(params.hasOwnProperty(n)) {
527             r.push(n + "\x3d" + params[n])
528           }
529         }
530         return"?" + r.join("\x26")
531       }
532       return""
533     }
534     function refresh() {
535       $$.cookies.set("access_token", accessToken);
536       self.location.reload()
537     }
538     function login(ctx) {
539       var uri;
540       ctx = ctx || {};
541       uri = ctx.uri || "/rest/oauth2";
542       ctx.params = ctx.params || {state:""};
543       ctx.params.state = ctx.params.state || ctx.callback || window.location.pathname;
544       ctx.params.display = ctx.params.display || "popup";
545       ctx.params.redirect_uri = $$.startsWithHttp(ctx.params.redirect_uri, encodeURIComponent(window.location.protocol + "//" + window.location.hostname + ":" + window.location.port) + ctx.params.redirect_uri);
546       uri = uri + query(ctx.params);
547       childWindow = window.open(uri, "OAuth", "status\x3d0,toolbar\x3d0,menubar\x3d0,resizable\x3d0,scrollbars\x3d1,top\x3d50,left\x3d50,height\x3d500,width\x3d680")
548     }
549     function token(t) {
550       if(arguments.length === 0) {
551         if(!$$.isNil(accessToken)) {
552           return accessToken
553         }
554       }else {
555         accessToken = t
556       }
557       return accessToken
558     }
559     function instanceUrl(i) {
560       if(arguments.length === 0) {
561         if(!$$.isNil(instUrl)) {
562           return instUrl
563         }
564         instUrl = $$.cookies.get("instance_url")
565       }else {
566         if(i === null) {
567           $$.cookies.remove("instance_url");
568           instUrl = null
569         }else {
570           $$.cookies.set("instance_url", i);
571           instUrl = i
572         }
573       }
574       return instUrl
575     }
576     function parseHash(hash) {
577       var i, nv, nvp, n, v;
578       if(!$$.isNil(hash)) {
579         if(hash.indexOf("#") === 0) {
580           hash = hash.substr(1)
581         }
582         nvp = hash.split("\x26");
583         for(i = 0;i < nvp.length;i += 1) {
584           nv = nvp[i].split("\x3d");
585           n = nv[0];
586           v = decodeURIComponent(nv[1]);
587           if("access_token" === n) {
588             token(v)
589           }else {
590             if("instance_url" === n) {
591               instanceUrl(v)
592             }else {
593               if("target_origin" === n) {
594                 tOrigin = decodeURIComponent(v)
595               }else {
596                 if("instance_id" === n) {
597                   instId = v
598                 }
599               }
600             }
601           }
602         }
603       }
604     }
605     function checkChildWindowStatus() {
606       if(!childWindow || childWindow.closed) {
607         refresh()
608       }
609     }
610     function childWindowUnloadNotification(hash) {
611       parseHash(hash);
612       setTimeout(window.Sfdc.canvas.oauth.checkChildWindowStatus, 50)
613     }
614     function logout() {
615       token(null)
616     }
617     function loggedin() {
618       return!$$.isNil(token())
619     }
620     function loginUrl() {
621       var i, nvs, nv, q = self.location.search;
622       if(q) {
623         q = q.substring(1);
624         nvs = q.split("\x26");
625         for(i = 0;i < nvs.length;i += 1) {
626           nv = nvs[i].split("\x3d");
627           if("loginUrl" === nv[0]) {
628             return decodeURIComponent(nv[1]) + "/services/oauth2/authorize"
629           }
630         }
631       }
632       return"https://login.salesforce.com/services/oauth2/authorize"
633     }
634     function targetOrigin(to) {
635       if(!$$.isNil(to)) {
636         tOrigin = to;
637         return to
638       }
639       if(!$$.isNil(tOrigin)) {
640         return tOrigin
641       }
642       parseHash(document.location.hash);
643       return tOrigin
644     }
645     function instanceId(id) {
646       if(!$$.isNil(id)) {
647         instId = id;
648         return id
649       }
650       if(!$$.isNil(instId)) {
651         return instId
652       }
653       parseHash(document.location.hash);
654       return instId
655     }
656     function client() {
657       return{oauthToken:token(), instanceId:instanceId(), targetOrigin:targetOrigin()}
658     }
659     return{init:init, login:login, logout:logout, loggedin:loggedin, loginUrl:loginUrl, token:token, instance:instanceUrl, client:client, checkChildWindowStatus:checkChildWindowStatus, childWindowUnloadNotification:childWindowUnloadNotification}
660   }();
661   $$.module("Sfdc.canvas.oauth", module);
662   $$.oauth.init()
663 })(Sfdc.canvas);
664 (function($$, window) {
665   var module = function() {
666     var internalCallback;
667     function postMessage(message, target_url, target) {
668       var sfdcJson = Sfdc.JSON || JSON;
669       if($$.isNil(target_url)) {
670         throw"ERROR: target_url was not supplied on postMessage";
671       }
672       var otherWindow = $$.stripUrl(target_url);
673       target = target || parent;
674       if(window.postMessage) {
675         if($$.isObject(message)) {
676           message.targetModule = "Canvas"
677         }
678         message = sfdcJson.stringify(message);
679         $$.console.log("Sending Post Message ", message);
680         target.postMessage(message, otherWindow)
681       }
682     }
683     function receiveMessage(callback, source_origin) {
684       if(window.postMessage) {
685         if(callback) {
686           internalCallback = function(e) {
687             var data, r;
688             var sfdcJson = Sfdc.JSON || JSON;
689             $$.console.log("Post Message Got callback", e);
690             if(!$$.isNil(e)) {
691               if(typeof source_origin === "string" && e.origin !== source_origin) {
692                 $$.console.log("source origin's don't match", e.origin, source_origin);
693                 return false
694               }
695               if($$.isFunction(source_origin)) {
696                 r = source_origin(e.origin, e.data);
697                 if(r === false) {
698                   $$.console.log("source origin's function returning false", e.origin, e.data);
699                   return false
700                 }
701               }
702               if($$.appearsJson(e.data)) {
703                 try {
704                   data = sfdcJson.parse(e.data)
705                 }catch(ignore) {
706                 }
707                 if(!$$.isNil(data) && ($$.isNil(data.targetModule) || data.targetModule === "Canvas")) {
708                   $$.console.log("Invoking callback");
709                   callback(data, r)
710                 }
711               }
712             }
713           }
714         }
715         if(window.addEventListener) {
716           window.addEventListener("message", internalCallback, false)
717         }else {
718           window.attachEvent("onmessage", internalCallback)
719         }
720       }
721     }
722     function removeListener() {
723       if(window.postMessage) {
724         if(window.removeEventListener) {
725           window.removeEventListener("message", internalCallback, false)
726         }else {
727           window.detachEvent("onmessage", internalCallback)
728         }
729       }
730     }
731     return{post:postMessage, receive:receiveMessage, remove:removeListener}
732   }();
733   $$.module("Sfdc.canvas.xd", module)
734 })(Sfdc.canvas, this);
735 (function($$) {
736   var pversion, cversion = "31.0";
737   var module = function() {
738     var purl;
739     function getTargetOrigin(to) {
740       var h;
741       if(to === "*") {
742         return to
743       }
744       if(!$$.isNil(to)) {
745         h = $$.stripUrl(to);
746         purl = $$.startsWithHttp(h, purl);
747         if(purl) {
748           return purl
749         }
750       }
751       h = $$.document().location.hash;
752       if(h) {
753         h = decodeURIComponent(h.replace(/^#/, ""));
754         purl = $$.startsWithHttp(h, purl)
755       }
756       return purl
757     }
758     function xdCallback(data) {
759       if(data) {
760         if(submodules[data.type]) {
761           submodules[data.type].callback(data)
762         }
763       }
764     }
765     var submodules = function() {
766       var cbs = [], seq = 0, autog = true;
767       function postit(clientscb, message) {
768         var wrapped, to, c;
769         seq = seq > 100 ? 0 : seq + 1;
770         cbs[seq] = clientscb;
771         wrapped = {seq:seq, src:"client", clientVersion:cversion, parentVersion:pversion, body:message};
772         c = message && message.config && message.config.client;
773         to = getTargetOrigin($$.isNil(c) ? null : c.targetOrigin);
774         if($$.isNil(to)) {
775           throw"ERROR: targetOrigin was not supplied and was not found on the hash tag, this can result from a redirect or link to another page.";
776         }
777         $$.console.log("posting message ", {message:wrapped, to:to});
778         $$.xd.post(wrapped, to, parent)
779       }
780       function validateClient(client, cb) {
781         var msg;
782         client = client || $$.oauth && $$.oauth.client();
783         if($$.isNil(client) || $$.isNil(client.oauthToken)) {
784           msg = {status:401, statusText:"Unauthorized", parentVersion:pversion, payload:"client or client.oauthToken not supplied"}
785         }
786         if($$.isNil(client.instanceId) || $$.isNil(client.targetOrigin)) {
787           msg = {status:400, statusText:"Bad Request", parentVersion:pversion, payload:"client.instanceId or client.targetOrigin not supplied"}
788         }
789         if(!$$.isNil(msg)) {
790           if($$.isFunction(cb)) {
791             cb(msg);
792             return false
793           }else {
794             throw msg;
795           }
796         }
797         return true
798       }
799       var event = function() {
800         var subscriptions = {}, STR_EVT = "sfdc.streamingapi";
801         function validName(name, res) {
802           var msg, r = $$.validEventName(name, res);
803           if(r !== 0) {
804             msg = {1:"Event names can only contain one namespace", 2:"Namespace has already been reserved", 3:"Event name contains invalid characters"};
805             throw msg[r];
806           }
807         }
808         function findSubscription(event) {
809           var s, name = event.name;
810           if(name === STR_EVT) {
811             if(!$$.isNil(subscriptions[name])) {
812               s = subscriptions[name][event.params.topic]
813             }
814           }else {
815             s = subscriptions[name]
816           }
817           if(!$$.isNil(s) && ($$.isFunction(s.onData) || $$.isFunction(s.onComplete))) {
818             return s
819           }
820           return null
821         }
822         return{callback:function(data) {
823           var event = data.payload, subscription = findSubscription(event), func;
824           if(!$$.isNil(subscription)) {
825             if(event.method === "onData") {
826               func = subscription.onData
827             }else {
828               if(event.method === "onComplete") {
829                 func = subscription.onComplete
830               }
831             }
832             if(!$$.isNil(func) && $$.isFunction(func)) {
833               func(event.payload)
834             }
835           }
836         }, subscribe:function(client, s) {
837           var subs = {};
838           if($$.isNil(s) || !validateClient(client)) {
839             throw"precondition fail";
840           }
841           $$.each($$.isArray(s) ? s : [s], function(v) {
842             if(!$$.isNil(v.name)) {
843               validName(v.name, ["canvas", "sfdc"]);
844               if(v.name === STR_EVT) {
845                 if(!$$.isNil(v.params) && !$$.isNil(v.params.topic)) {
846                   if($$.isNil(subscriptions[v.name])) {
847                     subscriptions[v.name] = {}
848                   }
849                   subscriptions[v.name][v.params.topic] = v
850                 }else {
851                   throw"[" + STR_EVT + "] topic is missing";
852                 }
853               }else {
854                 subscriptions[v.name] = v
855               }
856               subs[v.name] = {params:v.params}
857             }else {
858               throw"subscription does not have a 'name'";
859             }
860           });
861           if(!client.isVF) {
862             postit(null, {type:"subscribe", config:{client:client}, subscriptions:subs})
863           }
864         }, unsubscribe:function(client, s) {
865           var subs = {};
866           if($$.isNil(s) || !validateClient(client)) {
867             throw"PRECONDITION FAIL: need fo supply client and event name";
868           }
869           if($$.isString(s)) {
870             subs[s] = {};
871             delete subscriptions[s]
872           }else {
873             $$.each($$.isArray(s) ? s : [s], function(v) {
874               var name = v.name ? v.name : v;
875               validName(name, ["canvas", "sfdc"]);
876               subs[name] = {params:v.params};
877               if(name === STR_EVT) {
878                 if(!$$.isNil(subscriptions[name])) {
879                   if(!$$.isNil(subscriptions[name][v.params.topic])) {
880                     delete subscriptions[name][v.params.topic]
881                   }
882                   if($$.size(subscriptions[name]) <= 0) {
883                     delete subscriptions[name]
884                   }
885                 }
886               }else {
887                 delete subscriptions[name]
888               }
889             })
890           }
891           if(!client.isVF) {
892             postit(null, {type:"unsubscribe", config:{client:client}, subscriptions:subs})
893           }
894         }, publish:function(client, e) {
895           if(!$$.isNil(e) && !$$.isNil(e.name)) {
896             validName(e.name);
897             if(validateClient(client)) {
898               postit(null, {type:"publish", config:{client:client}, event:e})
899             }
900           }
901         }}
902       }();
903       var callback = function() {
904         return{callback:function(data) {
905           if(data.status === 401 && $$.isArray(data.payload) && data.payload[0].errorCode && data.payload[0].errorCode === "INVALID_SESSION_ID") {
906             if($$.oauth) {
907               $$.oauth.logout()
908             }
909           }
910           if($$.isFunction(cbs[data.seq])) {
911             if(!$$.isFunction(cbs[data.seq])) {
912               alert("not function")
913             }
914             cbs[data.seq](data)
915           }else {
916           }
917         }}
918       }();
919       var services = function() {
920         var sr;
921         return{ajax:function(url, settings) {
922           var ccb, config, defaults;
923           if(!url) {
924             throw"PRECONDITION ERROR: url required with AJAX call";
925           }
926           if(!settings || !$$.isFunction(settings.success)) {
927             throw"PRECONDITION ERROR: function: 'settings.success' missing.";
928           }
929           if(!validateClient(settings.client, settings.success)) {
930             return
931           }
932           ccb = settings.success;
933           defaults = {method:"GET", async:true, contentType:"application/json", headers:{"Authorization":"OAuth " + settings.client.oauthToken, "Accept":"application/json"}, data:null};
934           config = $$.extend(defaults, settings || {});
935           config.success = undefined;
936           config.failure = undefined;
937           if(config.client.targetOrigin === "*") {
938             config.client.targetOrigin = null
939           }else {
940             purl = $$.startsWithHttp(config.targetOrigin, purl)
941           }
942           postit(ccb, {type:"ajax", url:url, config:config})
943         }, ctx:function(clientscb, client) {
944           if(validateClient(client, clientscb)) {
945             postit(clientscb, {type:"ctx", accessToken:client.oauthToken, config:{client:client}})
946           }
947         }, token:function(t) {
948           return $$.oauth && $$.oauth.token(t)
949         }, version:function() {
950           return{clientVersion:cversion, parentVersion:pversion}
951         }, signedrequest:function(s) {
952           if(arguments.length > 0) {
953             sr = s
954           }
955           return sr
956         }, refreshSignedRequest:function(clientscb) {
957           var id = window.name.substring("canvas-frame-".length), client = {oauthToken:"null", instanceId:id, targetOrigin:"*"};
958           postit(clientscb, {type:"refresh", accessToken:client.oauthToken, config:{client:client}})
959         }, repost:function(refresh) {
960           var id = window.name.substring("canvas-frame-".length), client = {oauthToken:"null", instanceId:id, targetOrigin:"*"}, r = refresh || false;
961           postit(null, {type:"repost", accessToken:client.oauthToken, config:{client:client}, refresh:r})
962         }}
963       }();
964       var frame = function() {
965         return{size:function() {
966           var docElement = $$.document().documentElement;
967           var contentHeight = docElement.scrollHeight, pageHeight = docElement.clientHeight, scrollTop = docElement && docElement.scrollTop || $$.document().body.scrollTop, contentWidth = docElement.scrollWidth, pageWidth = docElement.clientWidth, scrollLeft = docElement && docElement.scrollLeft || $$.document().body.scrollLeft;
968           return{heights:{contentHeight:contentHeight, pageHeight:pageHeight, scrollTop:scrollTop}, widths:{contentWidth:contentWidth, pageWidth:pageWidth, scrollLeft:scrollLeft}}
969         }, resize:function(client, size) {
970           var sh, ch, sw, cw, s = {height:"", width:""}, docElement = $$.document().documentElement;
971           if($$.isNil(size)) {
972             sh = docElement.scrollHeight;
973             ch = docElement.clientHeight;
974             if(ch !== sh) {
975               s.height = sh + "px"
976             }
977             sw = docElement.scrollWidth;
978             cw = docElement.clientWidth;
979             if(sw !== cw) {
980               s.width = sw + "px"
981             }
982           }else {
983             if(!$$.isNil(size.height)) {
984               s.height = size.height
985             }
986             if(!$$.isNil(size.width)) {
987               s.width = size.width
988             }
989           }
990           if(!$$.isNil(s.height) || !$$.isNil(s.width)) {
991             postit(null, {type:"resize", config:{client:client}, size:s})
992           }
993         }, autogrow:function(client, b, interval) {
994           var ival = $$.isNil(interval) ? 300 : interval;
995           autog = $$.isNil(b) ? true : b;
996           if(autog === false) {
997             return
998           }
999           setTimeout(function() {
1000             submodules.frame.resize(client);
1001             submodules.frame.autogrow(client, autog)
1002           }, ival)
1003         }}
1004       }();
1005       return{services:services, frame:frame, event:event, callback:callback}
1006     }();
1007     $$.xd.receive(xdCallback, getTargetOrigin);
1008     return{ctx:submodules.services.ctx, ajax:submodules.services.ajax, token:submodules.services.token, version:submodules.services.version, resize:submodules.frame.resize, size:submodules.frame.size, autogrow:submodules.frame.autogrow, subscribe:submodules.event.subscribe, unsubscribe:submodules.event.unsubscribe, publish:submodules.event.publish, signedrequest:submodules.services.signedrequest, refreshSignedRequest:submodules.services.refreshSignedRequest, repost:submodules.services.repost}
1009   }();
1010   $$.module("Sfdc.canvas.client", module)
1011 })(Sfdc.canvas);
1012