Skip to content

Commit

Permalink
Merge pull request #16 from LivePersonInc/fix-iframe-reload
Browse files Browse the repository at this point in the history
Fix iframe reload
  • Loading branch information
miki2826 authored Jun 1, 2017
2 parents ea9ed63 + c00b729 commit 05631bf
Show file tree
Hide file tree
Showing 19 changed files with 277 additions and 73 deletions.
16 changes: 7 additions & 9 deletions build/aliases.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
module.exports = function (grunt, options) {

var tasks = ['node_version', 'jshint', 'env', 'instrument', 'connect', 'mocha', 'makeReport', 'concat', 'concat_in_order', 'uglify'];
var validate = ['node_version', 'jshint'];
var test = ['env', 'instrument', 'connect', 'mocha:test', 'makeReport'];
var unitTest = ['simplemocha:unittest'];
var pack = ['concat', 'concat_in_order', 'uglify'];
var tasks = [].concat(validate, unitTest, test, pack);
return {
'tasks': ['availabletasks'],
'default': tasks,
'test': [
'node_version',
'mochaTest',
'env',
'instrument',
'connect',
'mocha'
]
'test': test,
'unittest': unitTest
};
};
2 changes: 1 addition & 1 deletion build/mocha.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"threshold": 80,
"globalThreshold": 84,
"timeout": 60000,
"--web-security" : false,
"--web-security": false,
"urls": [
"http://localhost:8001/test/resources/events_test_base.html"
]
Expand Down
7 changes: 7 additions & 0 deletions build/simplemocha.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"unittest": {
"src": [
"./unittest/**/*_test.js"
]
}
}
13 changes: 7 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "chronosjs",
"description": "JS Channels Mechanism",
"version": "0.0.23",
"version": "0.1.0",
"author": {
"name": "LivePersonInc",
"email": "fe-infra-lp@liveperson.com"
Expand All @@ -21,25 +21,26 @@
"circuit-breakerjs": "~0.0.5"
},
"devDependencies": {
"body-parser": "^1.17.1",
"chai": "~3.5.0",
"body-parser": "~1.17.2",
"chai": "~4.0.1",
"grunt": "~1.0.1",
"grunt-available-tasks": "~0.6.3",
"grunt-concat-in-order": "~0.2.6",
"grunt-contrib-concat": "~1.0.1",
"grunt-contrib-connect": "~1.0.2",
"grunt-contrib-jshint": "~1.1.0",
"grunt-contrib-uglify": "^2.2.1",
"grunt-contrib-uglify": "^3.0.1",
"grunt-env": "~0.4.4",
"grunt-istanbul": "~0.7.2",
"grunt-mocha": "~1.0.4",
"grunt-node-version": "~1.0.2",
"grunt-replace": "~1.0.1",
"grunt-simple-mocha": "~0.4.1",
"load-grunt-config": "~0.19.2",
"mkdirp": "~0.5.1",
"mocha": "~3.2.0",
"mocha": "~3.4.2",
"requirejs": "~2.3.3",
"sinon": "~2.1.0",
"sinon": "~2.3.2",
"time-grunt": "~1.4.0"
},
"repository": {
Expand Down
35 changes: 21 additions & 14 deletions src/Channels.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,18 @@
}
}(typeof ChronosRoot === "undefined" ? this : ChronosRoot, function (root, exports, Events, Commands, ReqRes, hide) {
function Channels(options) {

options = options || {};

var externalAPIS = [];

var events = options.events || new Events(options.config && options.config.events);
var commands = options.commands || new Commands(options.config && options.config.commands);
var reqres = options.reqres || new ReqRes(options.config && options.config.reqres);


this.once = events.once;
this.hasFiredEvents = events.hasFired;
this.trigger = _wrapCalls({
func: events.trigger,
context: events,
triggerType: "trigger"
});
this.publish = this.trigger;
this.trigger = events.trigger;
this.publish = events.publish;
this.bind = events.bind;
this.register = events.register;
this.unbind = events.unbind;
Expand All @@ -60,9 +55,20 @@
this.request = reqres.request;
this.reply = reqres.reply;
this.stopReplying = reqres.stopReplying;

if (options.externalProxy === true) {
this.trigger = _wrapCalls({
func: events.trigger,
context: events,
triggerType: "trigger"
});
this.publish = _wrapCalls({
func: events.publish,
context: events,
triggerType: "trigger"
});
this.registerProxy = registerProxy;
}
}

/**
* Wraps API calls to trigger other registered functions
Expand All @@ -76,12 +82,13 @@

options.func.apply(options.context, Array.prototype.slice.call(arguments, 0));

for(var i = 0; i < externalAPIS.length; i++){
for (var i = 0; i < externalAPIS.length; i++) {
api = externalAPIS[i];
if(api[options.triggerType]){
try{
if (api[options.triggerType]) {
try {
api[options.triggerType].apply(api.context,Array.prototype.slice.call(arguments, 0));
}catch (exc){}
}
catch (exc) {}
}
}
};
Expand All @@ -92,7 +99,7 @@
* @param external
*/
function registerProxy(external){
if(typeof external === 'object' && external.trigger){
if (typeof external === 'object' && external.trigger) {
externalAPIS.push(external);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
/* istanbul ignore next */
if ("object" === typeof exports) {
// CommonJS
factory(root, exports, require("util/EventsUtil").EventsUtil, require("util/CommandsUtil").CommandsUtil);
factory(root, exports, require("./util/EventsUtil").EventsUtil, require("./util/CommandsUtil").CommandsUtil);
}
/* istanbul ignore next */
else {
Expand Down
2 changes: 1 addition & 1 deletion src/Events.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
/* istanbul ignore next */
if ("object" === typeof exports) {
// CommonJS
factory(root, exports, require("util/EventsUtil").EventsUtil);
factory(root, exports, require("./util/EventsUtil").EventsUtil);
}
/* istanbul ignore next */
else {
Expand Down
2 changes: 1 addition & 1 deletion src/Reqres.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
/* istanbul ignore next */
if ("object" === typeof exports) {
// CommonJS
factory(root, exports, require("util/EventsUtil").EventsUtil, require("util/CommandsUtil").CommandsUtil);
factory(root, exports, require("./util/EventsUtil").EventsUtil, require("./util/CommandsUtil").CommandsUtil);
}
/* istanbul ignore next */
else {
Expand Down
24 changes: 18 additions & 6 deletions src/courier/PostMessageChannel.js
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,8 @@
this.targetOrigin = options.targetOrigin;
this.maxConcurrency = PostMessageUtilities.parseNumber(options.maxConcurrency, DEFAULT_CONCURRENCY);
this.handshakeInterval = PostMessageUtilities.parseNumber(options.handshakeInterval, DEFAULT_HANDSHAKE_RETRY_INTERVAL);
this.handshakeAttempts = PostMessageUtilities.parseNumber(options.handshakeAttempts, DEFAULT_HANDSHAKE_RETRY_ATTEMPTS);
this.handshakeAttemptsOrig = PostMessageUtilities.parseNumber(options.handshakeAttempts, DEFAULT_HANDSHAKE_RETRY_ATTEMPTS);
this.handshakeAttempts = this.handshakeAttemptsOrig;
this.hostParam = options.hostParam;
this.channel = "undefined" !== typeof options.channel ? options.channel : _getChannelUrlIndicator();
this.useObjects = options.useObjects;
Expand Down Expand Up @@ -564,6 +565,10 @@
if (!this.disposed && !this.ready) {
this.ready = true;

// Handshake was successful, Channel is ready for messages
// Set the counter back to original value for dealing with iframe reloads
this.handshakeAttempts = this.handshakeAttemptsOrig;

// Process queued messages if any
if (this.messageQueue && this.messageQueue.length) {
PostMessageUtilities.delay(function() {
Expand Down Expand Up @@ -638,7 +643,9 @@
* @private
*/
function _createIFrame(options, container) {
var frame = document.createElement("IFRAME");
var name = PostMessageUtilities.createUniqueSequence(IFRAME_PREFIX + PostMessageUtilities.SEQUENCE_FORMAT);
var delay = options.delayLoad;
var defaultAttributes = {
"id": name,
"name" :name,
Expand All @@ -647,23 +654,22 @@
"title": "", // Adding an empty title for accessibility
"role": "presentation", // Adding a presentation role http://yahoodevelopers.tumblr.com/post/59489724815/easy-fixes-to-common-accessibility-problems
"allowTransparency":"true"
},
defaultStyle = {
};
var defaultStyle = {
width :"0px",
height : "0px",
position :"absolute",
top : "-1000px",
left : "-1000px"
};
var frame = document.createElement("IFRAME");
var delay = options.delayLoad;

options.attributes = options.attributes || defaultAttributes;
for(var key in options.attributes){
for (var key in options.attributes){
if (options.attributes.hasOwnProperty(key)) {
frame.setAttribute(key, options.attributes[key]);
}
}

options.style = options.style || defaultStyle;
if (options.style) {
for (var attr in options.style) {
Expand Down Expand Up @@ -696,6 +702,12 @@
var load = function() {
this.loading = false;

if (this.handshakeAttempts === this.handshakeAttemptsOrig) {
// Probably a first try for handshake or a reload of the iframe,
// Either way, we'll need to perform handshake, so ready flag should be set to false (if not already)
this.ready = false;
}

_handshake.call(this, this.handshakeInterval);
}.bind(this);

Expand Down
14 changes: 7 additions & 7 deletions src/courier/PostMessageCourier.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
* 2) IE9-, FF & Opera Mini does not support MessageChannel and therefore we fallback to using basic postMessage.
* This makes the communication opened to any handler registered for messages on the same origin.
* 3) All passDataByRef flags (in LPEventChannel) are obviously ignored
* 4) In case the browser does not support passing object using postMessage (IE8+, Opera Mini), and no special serialize/deserialize methods are supplied to LPPostMessageCourier,
* 4) In case the browser does not support passing object using postMessage (IE8+, Opera Mini), and no special serialize/deserialize methods are supplied to PostMessageCourier,
* All data is serialized using JSON.stringify/JSON.parse which means that Object data is limited to JSON which supports types like:
* strings, numbers, null, arrays, and objects (and does not allow circular references).
* Trying to serialize other types, will result in conversion to null (like Infinity or NaN) or to a string (Dates)
* that must be manually deserialized on the other side
* 5) When Iframe is managed outside of LPPostMessageCourier (passed by reference to the constructor),
* a targetOrigin option is expected to be passed to the constructor, and a query parameter with the name "lphost" is expected on the iframe url (unless the LPPostMessageCourier
* 5) When Iframe is managed outside of PostMessageCourier (passed by reference to the constructor),
* a targetOrigin option is expected to be passed to the constructor, and a query parameter with the name "lpHost" is expected on the iframe url (unless the PostMessageCourier
* at the iframe side, had also been initialized with a valid targetOrigin option)
*/
// TODO: Add Support for target management when there is a problem that requires re-initialization of the target
Expand Down Expand Up @@ -198,10 +198,10 @@
* @param eventChannel
* @private
*/
function _registerProxy(eventChannel){
if(eventChannel && eventChannel.registerProxy){
function _registerProxy(eventChannel) {
if (eventChannel && "function" === typeof eventChannel.registerProxy) {
eventChannel.registerProxy({
trigger: function(){
trigger: function () {
_postMessage.call(this, Array.prototype.slice.apply(arguments), ACTION_TYPE.TRIGGER);
},
context: this
Expand Down Expand Up @@ -550,7 +550,7 @@

/**
* Method for checking two way communication for action
* @param {LPPostMessageCourier.ACTION_TYPE} action - the action type name
* @param {PostMessageCourier.ACTION_TYPE} action - the action type name
* @returns {Boolean} flag to indicate whether the action is two way (had return call)
* @private
*/
Expand Down
48 changes: 34 additions & 14 deletions src/courier/PostMessageUtilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
}
}, "*");
}
catch(ex) {
catch (ex) {
// Browsers which has postMessage Objects support sends messages using
// the structured clone algorithm - https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
// In which Error and Function objects cannot be duplicated by the structured clone algorithm; attempting to do so will throw a DATA_CLONE_ERR exception.
Expand Down Expand Up @@ -145,16 +145,38 @@
return domain;
}

/**
* Method to resolve the needed origin parameters from url
* @param {String} [hostParam] - string to represent the name of the host parameter in querystring
* @param {String} [url] - string to represent the url to resolve parameters from
* @returns {String} the parameter from the url
*/
function resolveParameters(hostParam, url) {
var param;
var value = getURLParameter("lpHost", url);

if (!value) {
param = getURLParameter("hostParam", url) || hostParam;

if (param) {
value = getURLParameter(param, url);
}
}

return value;
}

/**
* Method to resolve the needed origin
* @param {Object} [target] - the target to resolve the host for
* @param {Boolean} [top] - boolean indication for using helper of the top window if needed
* @param {String} [hostParam] - string to represent the name of the host parameter in querystring
* @returns {String} the origin for the target
*/
function resolveOrigin(target, top) {
function resolveOrigin(target, top, hostParam) {
var origin;
var url;
var param;
var ref;

try {
url = target && target.contentWindow && "undefined" !== typeof Window && !(target instanceof Window) && target.getAttribute && target.getAttribute("src");
Expand All @@ -163,23 +185,20 @@

try {
if (!url) {
url = getURLParameter("lpHost");

if (!url) {
param = getURLParameter("hostParam");

if (param) {
url = getURLParameter(param);
}
}
url = resolveParameters(hostParam);
}

if (!url) {
url = document.referrer;
ref = true;
}

if (url) {
url = decodeURIComponent(url);

if (ref) {
url = resolveParameters(hostParam, url);
}
}

origin = getHost(url, target, top);
Expand All @@ -194,10 +213,11 @@
/**
* Method to retrieve a url parameter from querystring by name
* @param {String} name - the name of the parameter
* @param {String} [url] - optional url to parse
* @returns {String} the url parameter value
*/
function getURLParameter(name) {
return decodeURIComponent((new RegExp("[?|&]" + name + "=" + "([^&;]+?)(&|#|;|$)").exec(document.location.search) || [void 0, ""])[1].replace(/\+/g, "%20")) || null;
function getURLParameter(name, url) {
return decodeURIComponent((new RegExp("[?|&]" + name + "=" + "([^&;]+?)(&|#|;|$)").exec(url || document.location.search) || [void 0, ""])[1].replace(/\+/g, "%20")) || null;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/util/CommandsUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
/* istanbul ignore next */
if ("object" === typeof exports) {
// CommonJS
factory(root, exports, require("util/EventsUtil").EventsUtil);
factory(root, exports, require("./EventsUtil").EventsUtil);
}
/* istanbul ignore next */
else {
Expand Down
Loading

0 comments on commit 05631bf

Please sign in to comment.