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 28 (function ($$, window) { 29 30 "use strict"; 31 32 var module = (function() { 33 34 var internalCallback; 35 36 /** 37 * @description Pass a message to the target url 38 * @param {String} message The message to send 39 * @param {String} target_url Specifies what the origin of the target must be for the event to be dispatched. 40 * @param {String} [target] The window that is the message's target. Defaults to the parent of the current window. 41 */ 42 function postMessage(message, target_url, target) { 43 var sfdcJson = Sfdc.JSON || JSON; 44 45 // If target url was not supplied (client may have lost it), we could default to '*', 46 // However there are security implications here as other canvas apps could receive this 47 // canvas apps oauth token. 48 if ($$.isNil(target_url)) { 49 throw "ERROR: target_url was not supplied on postMessage"; 50 } 51 var otherWindow = $$.stripUrl(target_url); 52 53 target = target || parent; // default to parent 54 if (window.postMessage) { 55 // the browser supports window.postMessage, so call it with a targetOrigin 56 // set appropriately, based on the target_url parameter. 57 58 // Add the targetModule as Canvas so we are the only ones interested in these events 59 if ($$.isObject(message)) {message.targetModule = "Canvas";} 60 message = sfdcJson.stringify(message); 61 $$.console.log("Sending Post Message ", message); 62 target.postMessage(message, otherWindow); 63 } 64 } 65 66 /** 67 * @name Sfdc.canvas.xd#receive 68 * @description Runs the callback function when the message event is received. 69 * @param {Function} callback Function to run when the message event is received 70 if the event origin is acceptable. 71 * @param {String} source_origin The origin of the desired events 72 */ 73 function receiveMessage(callback, source_origin) { 74 75 // browser supports window.postMessage (if not not supported for pilot - removed per securities request) 76 if (window.postMessage) { 77 // bind the callback to the actual event associated with window.postMessage 78 if (callback) { 79 internalCallback = function(e) { 80 81 var data, r; 82 var sfdcJson = Sfdc.JSON || JSON; 83 84 $$.console.log("Post Message Got callback", e); 85 86 if (!$$.isNil(e)) { 87 if (typeof source_origin === 'string' && e.origin !== source_origin) { 88 $$.console.log("source origin's don't match", e.origin, source_origin); 89 return false; 90 } 91 if ($$.isFunction(source_origin)) { 92 r = source_origin(e.origin, e.data); 93 if (r === false) { 94 $$.console.log("source origin's function returning false", e.origin, e.data); 95 return false; 96 } 97 } 98 if ($$.appearsJson(e.data)) { 99 try { 100 data = sfdcJson.parse(e.data); 101 } catch (ignore) { 102 // Ignore parsing errors of any non json objects sent from other frames 103 } 104 // If we could parse the data and there is a targetModule make sure it is for us 105 if (!$$.isNil(data) && ($$.isNil(data.targetModule) || data.targetModule === "Canvas")) { 106 $$.console.log("Invoking callback"); 107 callback(data, r); 108 } 109 } 110 } 111 }; 112 } 113 if (window.addEventListener) { 114 window.addEventListener('message', internalCallback, false); 115 } else { 116 window.attachEvent('onmessage', internalCallback); 117 } 118 } 119 } 120 121 /** 122 * @description Removes the message event listener 123 * @public 124 */ 125 function removeListener() { 126 127 // browser supports window.postMessage 128 if (window.postMessage) { 129 if (window.removeEventListener) { 130 window.removeEventListener('message', internalCallback, false); 131 } else { 132 window.detachEvent('onmessage', internalCallback); 133 } 134 } 135 } 136 137 return { 138 post : postMessage, 139 receive : receiveMessage, 140 remove : removeListener 141 }; 142 }()); 143 144 $$.module('Sfdc.canvas.xd', module); 145 146 }(Sfdc.canvas, this));