htmlfile transport type added
[brisk.git] / web / xynt-streaming.js
1 // old targetpage == page and moved into start method
2
3 //
4 // CLASS transport_htmlfile
5 //
6 function transport_htmlfile(doc, page)
7 {
8     this.doc = doc;
9     this.transfdoc = new ActiveXObject("htmlfile");
10     this.transfdoc.open();
11     /*this.transfdoc.write("<html><head><script>");
12     this.transfdoc.write("document.domain=\""+(doc.domain)+"\";");
13     this.transfdoc.write("</"+"script></"+"head>"); */
14     this.transfdoc.write("<html><body><iframe id='iframe'></iframe></body></html>");
15     this.transfdoc.close();
16
17     this.ifra = this.transfdoc.getElementById("iframe");
18     this.ifra.contentWindow.location.href = page;
19 }
20
21 transport_htmlfile.prototype = {
22     doc: null,
23     ifra: null,
24     tradoc: null,
25
26     destroy: function () { /* public */
27         if (this.ifra != null) {
28         //     this.doc.body.removeChild(this.ifra);
29         //     delete this.ifra;
30              this.ifra = null;
31         }
32
33         if (this.transfdoc) {
34             delete this.transfdoc;
35             this.transfdoc = null;
36         }
37     },
38
39     xstr_is_init: function () { /* public */
40         return (typeof(this.ifra.contentWindow.xynt_streaming) != 'undefined');
41     },
42
43     /* only after a successfull is_initialized call */
44     xstr_is_ready: function () { /* public */
45         return (this.ifra.contentWindow.xynt_streaming == "ready");
46     },
47
48     /* only after a successfull is_ready call to be sure the accessibility of the var */
49     xstr_set: function (xynt_streaming) { /* public */
50         this.ifra.contentWindow.xynt_streaming = xynt_streaming;
51     },
52
53     ctx_new_is_set: function () { /* public */
54         return (typeof(this.ifra.contentWindow.ctx_new) != 'undefined');
55     },
56
57     ctx_new_curlen_get: function () { /* public */
58         return (this.ifra.contentWindow.ctx_new.length);
59     },
60
61     ctx_new_getchar: function(idx) { /* public */
62     },
63
64     ctx_old_len_is_set: function () { /* public */
65         return (typeof(this.ifra.contentWindow.ctx_old_len) != 'undefined');
66     },
67
68     ctx_old_len_get: function () { /* public */
69         return (this.ifra.contentWindow.ctx_old_len);
70     },
71
72     ctx_old_len_set: function (len) { /* public */
73         this.ifra.contentWindow.ctx_old_len = len;
74     },
75
76     ctx_old_len_add: function (len) { /* public */
77         this.ifra.contentWindow.ctx_old_len += len;
78     },
79
80     new_part: function () { /* public */
81         return (this.ifra.contentWindow.ctx_new.substr(this.ifra.contentWindow.ctx_old_len));
82     },
83
84     scrcls_set: function (step) { /* public */
85         this.ifra.contentWindow.script_clean = step;
86     }
87 }
88
89
90
91 //
92 // CLASS transport_iframe
93 //
94 function transport_iframe(doc, page)
95 {
96     this.doc = doc;
97     this.ifra = doc.createElement("iframe");
98     this.ifra.style.visibility = "hidden";
99     doc.body.appendChild(this.ifra);
100     this.ifra.contentWindow.location.href = page;
101 }
102
103 transport_iframe.prototype = {
104     doc: null,
105     ifra: null,
106
107     destroy: function () { /* public */
108         if (this.ifra != null) {
109             this.doc.body.removeChild(this.ifra);
110             delete this.ifra;
111             this.ifra = null;
112         }
113     },
114
115     xstr_is_init: function () { /* public */
116         return (typeof(this.ifra.contentWindow.xynt_streaming) != 'undefined');
117     },
118
119     /* only after a successfull is_initialized call */
120     xstr_is_ready: function () { /* public */
121         return (this.ifra.contentWindow.xynt_streaming == "ready");
122     },
123
124     /* only after a successfull is_ready call to be sure the accessibility of the var */
125     xstr_set: function (xynt_streaming) { /* public */
126         this.ifra.contentWindow.xynt_streaming = xynt_streaming;
127     },
128
129     ctx_new_is_set: function () { /* public */
130         return (typeof(this.ifra.contentWindow.ctx_new) != 'undefined');
131     },
132
133     ctx_new_curlen_get: function () { /* public */
134         return (this.ifra.contentWindow.ctx_new.length);
135     },
136
137     ctx_new_getchar: function(idx) { /* public */
138     },
139
140     ctx_old_len_is_set: function () { /* public */
141         return (typeof(this.ifra.contentWindow.ctx_old_len) != 'undefined');
142     },
143
144     ctx_old_len_get: function () { /* public */
145         return (this.ifra.contentWindow.ctx_old_len);
146     },
147
148     ctx_old_len_set: function (len) { /* public */
149         this.ifra.contentWindow.ctx_old_len = len;
150     },
151
152     ctx_old_len_add: function (len) { /* public */
153         this.ifra.contentWindow.ctx_old_len += len;
154     },
155
156     new_part: function () { /* public */
157         return (this.ifra.contentWindow.ctx_new.substr(this.ifra.contentWindow.ctx_old_len));
158     },
159
160     scrcls_set: function (step) { /* public */
161         this.ifra.contentWindow.script_clean = step;
162     }
163 }
164
165 function xynt_streaming(win, transp_type, console, gst, from, cookiename, sess, sandbox, page, cmdproc)
166 {
167     this.win = win;
168     this.transp_type = transp_type;
169     this.console = console;
170     this.gst = gst;
171     this.from = from;
172     this.cookiename = cookiename;
173     this.sess = sess;
174     this.sandbox = sandbox;
175     this.page = page;
176     this.cmdproc = cmdproc;
177     // this.cmdproc = function(com){/* console.log("COM: "+com); */ eval(com);}
178
179     this.doc = win.document;
180     this.keepalive_old = -1;
181     this.keepalive_new = -1;
182 }
183
184 xynt_streaming.prototype = {
185     win:               null,
186     transp_type:       null,
187     transp:            null,
188     console:           null,
189     gst:               null,
190     from:              null,
191     cookiename:        null,
192     sess:              null,
193     sandbox:           null,
194     page:              null,
195     cmdproc:           null,
196
197     doc:               null,
198     cookiepath: "/brisk/",
199     watchdog_hdl:      null,
200     hbit:              null,
201     keepalive_old:    -1,
202     keepalive_new:    -1,
203     keepalives_equal:  0,
204     /* NOTE: right watch_timeout value to 100, for devel reasons use 1000 or more */
205     // FIXME watchdog_timeout:  200,
206     /* restart after  3 * 40 * 100 millisec if server ping is missing => 12secs */
207     keepalives_eq_max: 3,
208     watchdog_checktm:  40,
209     watchdog_timeout:  100,
210     watchdog_ct:       0,
211     watchable:         false,
212     restart_n:         0,
213     comm_match:        /_*@BEGIN@(.*?)@END@/g, 
214     comm_clean:        /_*@BEGIN@(.*?)@END@/,
215     stream:            "",
216     the_end:           false,
217
218     start: function() { /* public */
219         if (this.the_end) 
220             return;
221
222         createCookie(this.cookiename, sess, 24*365, this.cookiepath);
223         // alert("start");
224         this.log("xynt_streaming:start restart: "+this.restart_n);
225         this.keepalives_equal = 0;
226
227         // page arrangement
228         this.page = url_complete(this.win.location.href, this.page);
229         // stat, subst, this.gst.st
230
231         this.page = url_append_args(this.page, "sess", this.sess, "stat", stat, "subst", subst, "step", this.gst.st, "from", this.from);
232         this.log(this.page);
233
234         // transport instantiation
235         if (this.transp_type == "iframe") {
236             this.transp = new transport_iframe(this.doc, this.page);
237         }
238         else if (this.transp_type == "htmlfile") {
239             this.transp = new transport_htmlfile(this.doc, this.page);
240         }
241         else
242             return;
243
244         // watchdog setting
245         this.watchdog_ct  = 0;
246         if (!this.the_end) {
247             this.watchdog_hdl = setTimeout(function(obj) { obj.log("tout1"); obj.watchdog(); }, this.watchdog_timeout, this);
248         }
249     },
250
251     stop: function() {
252         this.the_end = true;
253         this.abort();
254     },
255
256     hbit_set: function (hbit) {
257         this.hbit = hbit;
258     },
259
260     watchdog: function () {
261         // alert("watchdog");
262         var i, again;
263         var comm_newpart, comm_len, comm_arr;
264         var ctx_new_len;
265
266         if (this.sandbox != null) {
267             // from old: var zug = "POLL sess = "+sess+" stat = "+stat+" subst = "+subst+" step = "+this.gst.st+" step_loc = "+this.gst.st_loc+" step_loc_new = "+this.gst.st_loc_new+" STOP: "+this.stopped;
268             var zug = "WATCHDOG  sess = ["+this.sess+"]  step = "+this.gst.st+" step_loc = "+this.gst.st_loc+" step_loc_new = "+this.gst.st_loc_new;          
269             if (zug != this.sandbox.innerHTML)
270                 this.sandbox.innerHTML = zug;
271         }
272
273         // WATCHDOGING THE CONNECTION
274         this.log("hs::watchdog: start, cur equal times: "+this.keepalives_equal);
275         if (!this.watchable) {
276             do {
277                 try{
278                     // if (typeof(this.ifra.contentWindow.xynt_streaming) == 'undefined')
279                     if (!this.transp.xstr_is_init()) {
280                         this.log("hs::watchdog: xstr_is_init = false");
281                         break;
282                     }
283                 }
284                 catch(b) {
285                     this.log("hs::watchdog: exception");
286                     break;
287                 }
288
289                 /*
290                   on IE7 the the window frame scope is cleaned after the href is set, so we wait 
291                   for a well know variable value before assign this object value to it (OO is a passion)
292                 */
293                 // if (this.ifra.contentWindow.xynt_streaming == "ready") {
294                 if (this.transp.xstr_is_ready()) {
295                     // this.ifra.contentWindow.xynt_streaming = this;
296                     this.transp.xstr_set(this);
297                     this.watchable = true;
298                     this.watchdog_ct = 0;
299                     this.log("hs::watchdog: watchable = yes");
300                 }
301             } while (false);
302         }
303         if ( (this.watchdog_ct % this.watchdog_checktm) == 0) {
304             this.log("hs::watchdog: this.keepalive_old: "+this.keepalive_old+" this.keepalive_new: "+this.keepalive_new);
305             if (this.keepalive_old == this.keepalive_new) {
306                 this.keepalives_equal++;
307             }
308             else {
309                 this.keepalive_old = this.keepalive_new;
310                 this.keepalives_equal = 0;
311             }
312             
313             if (this.keepalives_equal > this.keepalives_eq_max) {
314                 this.log("hs::watchdog: MAX ACHIEVED "+this.keepalives_equal);
315                 this.reload();
316                 // alert("watchdog return reload");
317                 return;
318             }
319         }
320
321         // PICK COMMANDS FROM STREAM
322         do {
323             // alert("do--while begin ["+again+"]");
324             // CHECK: maybe again here isn't needed 
325             again = 0;
326             try {
327                 /* if (typeof(this.ifra.contentWindow.ctx_new)     == 'undefined' ||
328                    typeof(this.ifra.contentWindow.ctx_old_len) == 'undefined') */
329                 if (!this.transp.ctx_new_is_set() || !this.transp.ctx_old_len_is_set())
330                     break;
331             }
332             catch(b) {
333                 break;
334             }
335             
336             // ctx_new_len = this.ifra.contentWindow.ctx_new.length;
337             ctx_new_len = this.transp.ctx_new_curlen_get();
338             // if (ctx_new_len <= this.ifra.contentWindow.ctx_old_len) {
339             if (ctx_new_len <= this.transp.ctx_old_len_get()) {
340                 break;
341             }
342             this.log("new: "+ ctx_new_len + "  old: "+this.transp.ctx_old_len_get());
343             this.keepalive_new++;
344             // alert("pre-loop 1");
345             for (i = this.transp.ctx_old_len_get() ; i < ctx_new_len ; i++) {
346                 // if (this.ifra.contentWindow.ctx_new.charAt(i) != '_') {
347                 if (this.transp.ctx_new_getchar(i) != '_') {
348                     // this.log("ctx_new.char(i) != '_' ["+this.ifra.contentWindow.ctx_new.charAt(i)+"]");
349                     break;
350                 }
351                 // else {
352                 //     this.log("ctx_new.charAt(i) == '_'");
353                 // }
354             }
355             // this.ifra.contentWindow.ctx_old_len = i;
356             this.transp.ctx_old_len_set(i);
357             if (i == ctx_new_len) {
358                 this.log("old_len == i");
359                 break;
360             }
361             else {
362                 this.log("old_len != i: "+i);
363             }
364             // alert("do--while middle ["+this.ifra.contentWindow.ctx_old_len+"]");
365
366             comm_newpart = this.transp.new_part();
367             this.log("COM_NEWPART: ["+comm_newpart+"]");
368             comm_len = 0;
369             comm_arr = comm_newpart.match(this.comm_match);
370
371             // alert("do--while middle2 ["+again+"]");
372             if (comm_arr) {
373                 var comm_arr_len = comm_arr.length;
374                 for (i = 0 ; i < comm_arr_len ; i++) {
375                     var temp = comm_arr[i].replace(this.comm_clean,"$1").split("|");
376                     this.gst.comms = this.gst.comms.concat(temp);
377                     comm_len += comm_arr[i].length;
378                 }
379                 again = 1;
380             }
381             // this.ifra.contentWindow.ctx_old_len += comm_len;
382             this.transp.ctx_old_len_add(comm_len);
383             // this.ifra.contentWindow.script_clean = this.gst.st;
384             this.transp.scrcls_set(this.gst.st);
385             // alert("do--while end ["+again+"]");
386         } while (again);
387
388         // alert("post while");
389         // EXECUTION OF STREAM COMMANDS
390         do {
391             again = 0;
392             //MOP ?? xhrrestart = 0;
393             if (this.gst.st_loc < this.gst.st_loc_new) {
394                 // there is some slow actions running
395                 break;
396             }
397             else if (this.gst.comms.length > 0) {
398                 var singlecomm;
399                 
400                 singlecomm = this.gst.comms.shift();
401                 // alert("EXE"+gugu);
402                 // $("xhrdeltalog").innerHTML = "EVALL: "+singlecomm.replace("<", "&lt;", "g"); +"<br>";
403                 //xx this.hbit("+");
404
405                 // alert("SINGLE: ["+singlecomm+"]");
406                 this.cmdproc(singlecomm);
407                 again = 1;
408             }
409         } while (again);
410         this.watchdog_ct++;
411         if (!this.the_end) {
412             this.watchdog_hdl = setTimeout(function(obj) { /* obj.log("tout2"); */ obj.watchdog(); }, this.watchdog_timeout, this);
413         }
414         // alert("watchdog return normal");
415
416         return;
417     },
418
419     //
420     // moved to xynt-streaming-ifra as push()
421     //
422     // keepalive: function (s) {
423     //     this.log("hs::keepalive");
424     //     if (s != null) {
425     //         this.log(s);
426     //         this.ifra.contentWindow.ctx_new += "@BEGIN@"+s+"@END@";
427     //     }
428     //     else {
429     //         this.ifra.contentWindow.ctx_new += "_";
430     //     }
431     //     // this.keepalive_new++;
432     // },
433
434     abort: function () { /* public */
435         // this.log("PATH: "+this.ifra.contentWindow.location.protocol + "://" + this.ifra.contentWindow.location.host + "/" + this.ifra.contentWindow.location.pathname);
436
437         this.gst.abort();
438         if (this.watchdog_hdl != null) {
439             clearTimeout(this.watchdog_hdl);
440             this.watchdog_hdl = null;
441         }
442
443         this.restart_n++;
444         this.log("hs::reload");
445         this.watchable = false;
446         if (this.transp != null) {
447             this.transp.destroy();
448             delete this.transp;
449             this.transp = null;
450         }
451     },
452
453     reload: function () {
454         this.abort();
455         this.start(null);
456     },
457
458     log: function (s) {
459         if (this.console != null) {
460             return (this.console.log(s));
461         }
462     }
463 }