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