Commit 76360727 authored by Cédric Le Ninivin's avatar Cédric Le Ninivin

RenderJS: prepares communication with parent gadget only if communication channel is ready

It removes communication timeout with parent iFrame and solve the issue of timeout in case of a high load due to heavy JS processing
/reviewed-on !2
parent 0ab5cb9e
...@@ -1020,7 +1020,11 @@ ...@@ -1020,7 +1020,11 @@
notifyDeclareMethod, notifyDeclareMethod,
gadget_ready = false, gadget_ready = false,
iframe_top_gadget, iframe_top_gadget,
last_acquisition_gadget; last_acquisition_gadget,
declare_method_list_waiting = [],
gadget_failed = false,
gadget_error,
connection_ready = false;
// Create the gadget class for the current url // Create the gadget class for the current url
if (gadget_model_dict.hasOwnProperty(url)) { if (gadget_model_dict.hasOwnProperty(url)) {
...@@ -1079,28 +1083,45 @@ ...@@ -1079,28 +1083,45 @@
setAqParent(root_gadget, last_acquisition_gadget); setAqParent(root_gadget, last_acquisition_gadget);
} else { } else {
// Create the communication channel
embedded_channel = Channel.build({
window: window.parent,
origin: "*",
scope: "renderJS"
});
// Create the root gadget instance and put it in the loading stack // Create the root gadget instance and put it in the loading stack
tmp_constructor = RenderJSEmbeddedGadget; tmp_constructor = RenderJSEmbeddedGadget;
tmp_constructor.__ready_list = RenderJSGadget.__ready_list.slice(); tmp_constructor.__ready_list = RenderJSGadget.__ready_list.slice();
tmp_constructor.__service_list = RenderJSGadget.__service_list.slice(); tmp_constructor.__service_list = RenderJSGadget.__service_list.slice();
tmp_constructor.prototype.__path = url; tmp_constructor.prototype.__path = url;
root_gadget = new RenderJSEmbeddedGadget(); root_gadget = new RenderJSEmbeddedGadget();
setAqParent(root_gadget, last_acquisition_gadget);
// Create the communication channel
// Notify parent about gadget instanciation embedded_channel = Channel.build({
notifyReady = function () { window: window.parent,
if ((declare_method_count === 0) && (gadget_ready === true)) { origin: "*",
embedded_channel.notify({method: "ready"}); scope: "renderJS",
} onReady: function () {
var k;
iframe_top_gadget = false;
//Default: Define __aq_parent to inform parent window
root_gadget.__aq_parent =
tmp_constructor.prototype.__aq_parent = function (method_name,
argument_list, time_out) {
return new RSVP.Promise(function (resolve, reject) {
embedded_channel.call({
method: "acquire",
params: [
method_name,
argument_list
],
success: function (s) {
resolve(s);
},
error: function (e) {
reject(e);
},
timeout: time_out
});
});
}; };
// Inform parent gadget about declareMethod calls here. // Channel is ready, so now declare Function
notifyDeclareMethod = function (name) { notifyDeclareMethod = function (name) {
declare_method_count += 1; declare_method_count += 1;
embedded_channel.call({ embedded_channel.call({
...@@ -1115,6 +1136,56 @@ ...@@ -1115,6 +1136,56 @@
} }
}); });
}; };
for (k = 0; k < declare_method_list_waiting.length; k += 1) {
notifyDeclareMethod(declare_method_list_waiting[k]);
}
declare_method_list_waiting = [];
// If Gadget Failed Notify Parent
if (gadget_failed) {
embedded_channel.notify({
method: "failed",
params: gadget_error
});
return;
}
// Get Top URL
return tmp_constructor.prototype.__aq_parent('getTopURL', [])
.then(function (topURL) {
var base = document.createElement('base');
base.href = topURL;
base.target = "_top";
document.head.appendChild(base);
connection_ready = true;
notifyReady();
//the channel is ok
//so bind calls to renderJS method on the instance
embedded_channel.bind("methodCall", function (trans, v) {
root_gadget[v[0]].apply(root_gadget, v[1])
.then(function (g) {
trans.complete(g);
}).fail(function (e) {
trans.error(e.toString());
});
trans.delayReturn(true);
});
})
.fail(function (error) {
throw error;
});
}
});
// Notify parent about gadget instanciation
notifyReady = function () {
if ((declare_method_count === 0) && (gadget_ready === true)) {
embedded_channel.notify({method: "ready"});
}
};
// Inform parent gadget about declareMethod calls here.
notifyDeclareMethod = function (name) {
declare_method_list_waiting.push(name);
};
notifyDeclareMethod("getInterfaceList"); notifyDeclareMethod("getInterfaceList");
notifyDeclareMethod("getRequiredCSSList"); notifyDeclareMethod("getRequiredCSSList");
...@@ -1139,26 +1210,7 @@ ...@@ -1139,26 +1210,7 @@
tmp_constructor.allowPublicAcquisition = tmp_constructor.allowPublicAcquisition =
RenderJSGadget.allowPublicAcquisition; RenderJSGadget.allowPublicAcquisition;
//Default: Define __aq_parent to inform parent window iframe_top_gadget = true;
tmp_constructor.prototype.__aq_parent = function (method_name,
argument_list, time_out) {
return new RSVP.Promise(function (resolve, reject) {
embedded_channel.call({
method: "acquire",
params: [
method_name,
argument_list
],
success: function (s) {
resolve(s);
},
error: function (e) {
reject(e);
},
timeout: time_out
});
});
};
} }
tmp_constructor.prototype.__acquired_method_dict = {}; tmp_constructor.prototype.__acquired_method_dict = {};
...@@ -1283,45 +1335,6 @@ ...@@ -1283,45 +1335,6 @@
return root_gadget; return root_gadget;
} }
if (window.top !== window.self) {
//checking channel should be done before sub gadget's declaration
//__ready_list:
//0: clearGadgetInternalParameters
//1: loadSubGadgetDOMDeclaration
//.....
tmp_constructor.__ready_list.splice(1, 0, function () {
return root_gadget.__aq_parent('getTopURL', [], 100)
.then(function (topURL) {
var base = document.createElement('base');
base.href = topURL;
base.target = "_top";
document.head.appendChild(base);
//the channel is ok
//so bind calls to renderJS method on the instance
embedded_channel.bind("methodCall", function (trans, v) {
root_gadget[v[0]].apply(root_gadget, v[1])
.then(function (g) {
trans.complete(g);
}).fail(function (e) {
trans.error(e.toString());
});
trans.delayReturn(true);
});
})
.fail(function (error) {
if (error === "timeout_error") {
//the channel fail
//we consider current gadget is parent gadget
//redifine last acquisition gadget
iframe_top_gadget = true;
setAqParent(root_gadget, last_acquisition_gadget);
} else {
throw error;
}
});
});
}
tmp_constructor.ready(function (g) { tmp_constructor.ready(function (g) {
return startService(g); return startService(g);
}); });
...@@ -1346,11 +1359,15 @@ ...@@ -1346,11 +1359,15 @@
loading_gadget_promise loading_gadget_promise
.then(function () { .then(function () {
gadget_ready = true; gadget_ready = true;
if (connection_ready) {
notifyReady(); notifyReady();
}
}) })
.fail(function (e) { .fail(function (e) {
//top gadget in iframe //top gadget in iframe
if (iframe_top_gadget) { if (iframe_top_gadget) {
gadget_failed = true;
gadget_error = e.toString();
letsCrash(e); letsCrash(e);
} else { } else {
embedded_channel.notify({method: "failed", params: e.toString()}); embedded_channel.notify({method: "failed", params: e.toString()});
......
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Embedded page for renderJS test</title>
<meta name="viewport" content="width=device-width, height=device-height"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script src="../node_modules/rsvp/dist/rsvp-2.0.4.js" type="text/javascript"></script>
<script src="../dist/renderjs-latest.js" type="text/javascript"></script>
<script src="./embedded_heavy.js" type="text/javascript"></script>
</head>
<body>
</body>
</html>
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment