]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/xul/staff_client/chrome/content/util/network.js
xul_param and modal xulG conversion
[Evergreen.git] / Open-ILS / xul / staff_client / chrome / content / util / network.js
1 dump('entering util/network.js\n');
2
3 if (typeof util == 'undefined') util = {};
4 util.network = function () {
5
6         JSAN.use('util.error'); this.error = new util.error();
7         JSAN.use('util.sound'); this.sound = new util.sound();
8
9         return this;
10 };
11
12 util.network.prototype = {
13
14         'link_id' : 0,
15
16         'NETWORK_FAILURE' : null,
17
18         'simple_request' : function(method_id,params,f,override_params) {
19                 if (typeof api[method_id] == 'undefined') throw( 'Method not found for ' + method_id );
20                 var secure = true; if (typeof api[method_id].secure != 'undefined') secure = api[method_id].secure;
21                 return this.request(api[method_id].app,api[method_id].method,params,f,override_params,{ 'secure' : secure, 'method_id' : method_id });
22         },
23
24         'cached_request' : function(method_id,params,f,override_params) {
25                 if (typeof api[method_id] == 'undefined') throw( 'Method not found for ' + method_id );
26                 var secure = true; if (typeof api[method_id].secure != 'undefined') secure = api[method_id].secure;
27                 return this.request(api[method_id].app,api[method_id].method,params,f,override_params,{ 'secure' : secure, 'want_cached' : true, 'method_id' : method_id });
28         },
29
30         'get_result' : function (req) {
31                 var obj = this;
32                 var result;
33                 try {
34                         result = req.getResultObject(); 
35                 } catch(E) {
36                         try {
37                                 if (instanceOf(E, NetworkFailure)) {
38                                         obj.NETWORK_FAILURE = E;
39                                 } else {
40                                         try { obj.NETWORK_FAILURE = js2JSON(E); } catch(F) { dump(F + '\n'); obj.NETWORK_FAILURE = E; };
41                                 }
42                         } catch(I) { 
43                                 obj.NETWORK_FAILURE = 'Unknown status';
44                         }
45                         result = null;
46                 }
47                 return result;
48         },
49
50         'is_cacheable' : function(method_id) {
51                 return (api[method_id].cacheable);
52         },
53
54         'request' : function (app,name,params,f,override_params,_params) {
55
56                 var obj = this;
57
58                 try { 
59
60                 if (_params && _params.want_cached) if ( this.is_cacheable(_params.method_id) ) {
61                         JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
62                         var key = (app + '+' + name + '+' + js2JSON(params)).replace(/\./g,'_');
63                         var x = data.cached_request[key];
64                         if (x) {
65                                 obj.error.sdump('D_CACHE','Cached request found for key = \n' + key + '\n' + js2JSON(x) + '\n');                
66                                 switch(x.status) {
67                                         case 'pending' :
68                                                 if ( Number(new Date()) - Number(x.status_time) > 60000 ) break; // if pending request is taking too long
69                                                 if (f) { // Setup a self-destroying observer on the pending request to handle this request
70                                                         obj.error.sdump('D_CACHE','Cached request pending, adding watch to handle current asynchronous request. key = \n' + key + '\n');
71                                                         var id = data.observers.add('cached_request.'+key+'.status',function(p,o,n) {
72                                                                         obj.error.sdump('D_OBSERVERS','Entering watch function for key = \n' + key + '\np = ' + p + '\no = ' + js2JSON(o) + '\nn = ' + js2JSON(n) + '\nx = ' + js2JSON(x) + '\n');
73                                                                         if (n == 'complete') {
74                                                                                 obj.error.sdump('D_CACHE','Cached request completed for key = \n' + key + '\nNow calling a previous async request watching this one.\n');
75                                                                                 f( { 'getResultObject' : function() { return JSON2js( js2JSON( x.request ) ); } } );
76                                                                                 setTimeout( function() { try { data.observers.remove(id); } catch(E) { alert(E); } }, 0 );
77                                                                         }
78                                                                         return n;
79                                                                 }
80                                                         );
81                                                         return null;
82                                                 } else {
83                                                         obj.error.sdump('D_CACHE','Pending request and synchronous request collision with key = \n' + key + '\nFalling through...\n');
84                                                 }
85                                         break;
86                                         case 'complete' :
87                                                 if ( Number( new Date() ) < x.expire_time ) {
88                                                         if (f) {
89                                                                 obj.error.sdump('D_CACHE','Cached request found completed, handling asynchronous request now. key = \n' + key + '\n');
90                                                                 f( { 'getResultObject' : function() { return JSON2js( js2JSON( x.request ) ); } } );
91                                                                 return null;
92                                                         } else {
93                                                                 obj.error.sdump('D_CACHE','Cached request found completed, key = \n' + key + '\nreturning value =\n' + x.request + '\n');
94                                                                 return JSON2js( js2JSON( x.request ) ); // FIXME -- cloning the object is a workaround, otherwise instanceOf somehow silently fails
95                                                         }
96                                                 } else {
97                                                         obj.error.sdump('D_CACHE','Cached request found completed, however, it has expired. key = \n' + key + '\nFalling through...\n');
98                                                 }
99                                         break;
100                                 }
101                         } else {
102                                 obj.error.sdump('D_CACHE','Cached request not found for key = \n' + key + '\n');                
103                         }
104                 }
105
106                 var request =  this._request(app,name,params,f,override_params,_params);
107                 if (request) {
108                         return this.get_result(request);
109                 } else {
110                         return null;
111                 }
112
113                 } catch(E) {
114                         alert(E); 
115                 }
116         },
117
118         '_request' : function (app,name,params,f,override_params,_params) {
119                 var obj = this;
120                 try {
121                         var sparams = js2JSON(params);
122                         obj.error.sdump('D_SES','request '+app+' '+name+' '+obj.error.pretty_print(sparams.slice(1,sparams.length-1))+
123                                 '\noverride_params = ' + override_params + '\n_params = ' + _params +
124                                 '\nResult #' + (++obj.link_id) + ( f ? ' asynced' : ' synced' ) );
125
126                         var key; var x; var data;
127                         if (_params && obj.is_cacheable(_params.method_id)) {
128                                 JSAN.use('OpenILS.data'); data = new OpenILS.data(); data.init({'via':'stash'});
129                                 key = (app + '+' + name + '+' + js2JSON(params)).replace(/\./g,'_');
130                                 data.cached_request[key] = { 'test' : 'test', 'status' : 'pending', 'status_time' : Number(new Date()) }; 
131                                 data.stash('cached_request');
132                                 x = data.cached_request[key];
133                                 obj.error.sdump('D_CACHE','Current request is cacheable, setting pending status for key = \n' + key + '\nUpdating cache with ' + js2JSON(x) + '\n');
134                         }
135
136                         var request = new RemoteRequest( app, name );
137                         if (_params && _params.secure) {
138                                 request.setSecure(true);
139                         } else {
140                                 request.setSecure(false);
141                         }
142                         for(var index in params) {
143                                 request.addParam(params[index]);
144                         }
145         
146                         if (f)  {
147                                 request.setCompleteCallback(
148                                         function(req) {
149                                                 try {
150                                                         var json_string = js2JSON(obj.get_result(req));
151                                                         obj.error.sdump('D_SES_RESULT','asynced result #' 
152                                                                 + obj.link_id + '\n\n' 
153                                                                 + (json_string.length > 80 ? obj.error.pretty_print(json_string) : json_string) 
154                                                                 + '\n\nOriginal Request:\n\n' 
155                                                                 + 'request '+app+' '+name+' '+ sparams.slice(1,sparams.length-1));
156                                                         req = obj.rerequest_on_session_timeout(app,name,params,req,override_params,_params);
157                                                         req = obj.rerequest_on_perm_failure(app,name,params,req,override_params,_params);
158                                                         if (override_params) {
159                                                                 req = obj.rerequest_on_override(app,name,params,req,override_params,_params);
160                                                         }
161                                                         req = obj.check_for_offline(app,name,params,req,override_params,_params);
162                                                         if (_params && obj.is_cacheable(_params.method_id)) {
163                                                                 x.request = obj.get_result(req);
164                                                                 x.status = 'complete'; x.status_time = Number(new Date()); x.expire_time = Number(x.status_time) + api[_params.method_id].ttl;
165                                                                 data.stash('cached_request');
166                                                                 obj.error.sdump('D_CACHE','Previously pending cached request is now complete for key = \n' + key + '\nUpdating cache with ' + js2JSON(x) + '\n');
167                                                         }
168                                                         f(req);
169                                                         obj.NETWORK_FAILURE = null;
170                                                 } catch(E) {
171                                                         try {
172                                                                 E.ilsevent = -2;
173                                                                 E.textcode = 'Server/Method Error';
174                                                         } catch(F) {}
175                                                         f( { 'getResultObject' : function() { return E; } } );
176                                                 }
177                                         }
178                                 );
179                                 try {
180                                         request.send(false);
181                                 } catch(E) {
182                                         throw(E);
183                                 }
184                                 return null;
185                         } else {
186                                 try {
187                                         request.send(true);
188                                 } catch(E) {
189                                         throw(E);
190                                 }
191                                 var result = obj.get_result(request);
192                                 var json_string = js2JSON(result);
193                                 this.error.sdump('D_SES_RESULT','synced result #' 
194                                         + obj.link_id + '\n\n' + ( json_string.length > 80 ? obj.error.pretty_print(json_string) : json_string ) 
195                                         + '\n\nOriginal Request:\n\n' 
196                                         + 'request '+app+' '+name+' '+ sparams.slice(1,sparams.length-1));
197                                 request = obj.rerequest_on_session_timeout(app,name,params,request,override_params,_params);
198                                 request = obj.rerequest_on_perm_failure(app,name,params,request,override_params,_params);
199                                 if (override_params) {
200                                         request = obj.rerequest_on_override(app,name,params,request,override_params,_params);
201                                 }
202                                 request = obj.check_for_offline(app,name,params,request,override_params,_params);
203                                 obj.NETWORK_FAILURE = null;
204                                 if (_params && obj.is_cacheable(_params.method_id)) {
205                                         x.request = result;
206                                         x.status = 'complete'; x.status_time = Number(new Date()); x.expire_time = Number(x.status_time) + api[_params.method_id].ttl;
207                                         data.stash('cached_request');
208                                         obj.error.sdump('D_CACHE','Previously pending cached request is now complete for key = \n' + key + '\nUpdating cache with ' + js2JSON(x) + '\n');
209                                 }
210                                 return request;
211                         }
212
213                 } catch(E) {
214                         alert(E);
215                         if (instanceOf(E,perm_ex)) {
216                                 alert('in util.network, _request : permission exception: ' + js2JSON(E));
217                         }
218                         throw(E);
219                 }
220         },
221
222         'check_for_offline' : function (app,name,params,req,override_params,_params) {
223                 var obj = this;
224                 var result = obj.get_result(req);
225                 if (result != null) return req;
226
227                 JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
228                 var proceed = true;
229
230                 while(proceed) {
231
232                         proceed = false;
233
234                         var r;
235
236                         if (data.proceed_offline) {
237
238                                 r = 1;
239
240                         } else {
241
242                                 var network_failure_string;
243                                 var network_failure_status_string;
244                                 var msg;
245
246                                 try { network_failure_string = String( obj.NETWORK_FAILURE ); } catch(E) { network_failure_string = E; }
247                                 try { network_failure_status_string = typeof obj.NETWORK_FAILURE == 'object' && typeof obj.NETWORK_FAILURE != 'null' && typeof obj.NETWORK_FAILURE.status == 'function' ? obj.NETWORK_FAILURE.status() : ''; } catch(E) { network_failure_status_string = ''; obj.error.sdump('D_ERROR', 'setting network_failure_status_string: ' + E); }
248                                 
249                                 try { msg = 'Network/server failure.  Please check your Internet connection to ' + data.server_unadorned + ' and choose Retry Network.  If you need to enter Offline Mode, choose Ignore Errors in this and subsequent dialogs.  If you believe this error is due to a bug in Evergreen and not network problems, please contact your helpdesk or friendly Evergreen admins, and give them this information:\nmethod=' + name + '\nparams=' + js2JSON(params) + '\nTHROWN:\n' + network_failure_string + '\nSTATUS:\n' + network_failure_status_string; } catch(E) { msg = E; }
250
251                                 try { obj.error.sdump('D_SES_ERROR',msg); } catch(E) { alert(E); }
252
253                                 r = obj.error.yns_alert(msg,'Network Failure','Retry Network','Ignore Errors',null,'Check here to confirm this message');
254                                 if (r == 1) {
255                                         data.proceed_offline = true; data.stash('proceed_offline');
256                                         dump('Remembering proceed_offline for 200000 ms.\n');
257                                         setTimeout(
258                                                 function() {
259                                                         data.proceed_offline = false; data.stash('proceed_offline');
260                                                         dump('Setting proceed_offline back to false.\n');
261                                                 }, 200000
262                                         );
263                                 }
264                         }
265
266                         dump( r == 0 ? 'Retry Network\n' : 'Ignore Errors\n' );
267
268                         switch(r) {
269                                 case 0: 
270                                         req = obj._request(app,name,params,null,override_params,_params);
271                                         if (obj.get_result(req)) proceed = true; /* daily WTF, why am I even doing this? :) */
272                                         return req;
273                                 break;
274                                 case 1: 
275                                         return { 'getResultObject' : function() { return { 'ilsevent' : -1, 'textcode' : 'Network/Server Problem' }; } };
276                                 break;
277                         }
278                 }
279         },
280
281         'reset_titlebars' : function(data) {
282                 var obj = this;
283                 data.stash_retrieve();
284                 try {
285                         JSAN.use('util.window'); var win =  new util.window();
286                         var windowManager = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService();
287                         var windowManagerInterface = windowManager.QueryInterface(Components.interfaces.nsIWindowMediator);
288                         var enumerator = windowManagerInterface.getEnumerator(null);
289
290                         var w; // set title on all appshell windows
291                         while ( w = enumerator.getNext() ) {
292                                 if (w.document.title.match(/^\d/)) {
293                                         w.document.title = 
294                                                 win.appshell_name_increment() 
295                                                 + ': ' + data.list.au[0].usrname() 
296                                                 + '@' + data.ws_name;
297                                                 + '.' + data.server_unadorned 
298                                 }
299                         }
300                 } catch(E) {
301                         obj.error.standard_unexpected_error_alert('Error setting window titles to match new login',E);
302                 }
303         },
304
305         'get_new_session' : function(name,xulG,text) {
306                 var obj = this;
307                 try {
308
309                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
310                 var url = urls.XUL_AUTH_SIMPLE;
311                 if (typeof xulG != 'undefined' && typeof xulG.url_prefix == 'function') url = xulG.url_prefix( url );
312                 JSAN.use('util.window'); var win = new util.window();
313                 var my_xulG = win.open(
314                         url,
315                         //+ '?login_type=staff'
316                         //+ '&desc_brief=' + window.escape( text ? 'Session Expired' : 'Operator Change' )
317                         //+ '&desc_full=' + window.escape( text ? 'Please enter the credentials for a new login session.' : 'Please enter the credentials for the new login session.  Note that the previous session is still active.'),
318                         //'simple_auth' + (new Date()).toString(),
319                         'Authorize',
320                         'chrome,resizable,modal,width=700,height=500',
321                         {
322                                 'login_type' : 'staff',
323                                 'desc_brief' : text ? 'Session Expired' : 'Operator Change',
324                                 'desc_full' : text ? 'Please enter the credentials for a new login session.' : 'Please enter the credentials for the new login session.  Note that the previous session is still active.',
325                                 //'simple_auth' : (new Date()).toString(),
326                         }
327                 );
328                 JSAN.use('OpenILS.data');
329                 var data = new OpenILS.data(); data.init({'via':'stash'});
330                 if (typeof my_xulG.temporary_session != 'undefined' && my_xulG.temporary_session != '') {
331                         data.session.key = my_xulG.temporary_session.key; 
332                         data.session.authtime = my_xulG.temporary_session.authtime; 
333                         data.stash('session');
334                         if (! data.list.au ) data.list.au = [];
335                         data.list.au[0] = JSON2js( my_xulG.temporary_session.usr );
336                         data.stash('list');
337                         obj.reset_titlebars(data);
338                         return true;
339                 } else { alert('here2'); }
340                 return false;
341
342                 } catch(E) {
343                         obj.error.standard_unexpected_error_alert('util.network.get_new_session',E);
344                 }
345         },
346
347         'rerequest_on_session_timeout' : function(app,name,params,req,override_params,_params) {
348                 try {
349                         var obj = this;
350                         var robj = obj.get_result(req);
351                         if (robj != null && robj.ilsevent && robj.ilsevent == 1001) {
352
353                                 if (obj.get_new_session(name,undefined,true)) {
354                                         JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
355                                         params[0] = data.session.key;
356                                         req = obj._request(app,name,params,null,override_params,_params);
357                                 }
358                         }
359                 } catch(E) {
360                         this.error.standard_unexpected_error_alert('rerequest_on_session_timeout',E);
361                 }
362                 return req;
363         },
364         
365         'rerequest_on_perm_failure' : function(app,name,params,req,override_params,_params) {
366                 try {
367                         var obj = this;
368                         var robj = obj.get_result(req);
369                         if (robj != null && robj.ilsevent && robj.ilsevent == 5000) {
370                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
371                                 if (location.href.match(/^chrome/)) {
372                                         //alert('Permission denied.');
373                                 } else {
374                                         JSAN.use('util.window'); var win = new util.window();
375                                         var my_xulG = win.open(
376                                                 urls.XUL_AUTH_SIMPLE,
377                                                 //+ '?login_type=temp'
378                                                 //+ '&desc_brief=' + window.escape('Permission Denied: ' + robj.ilsperm)
379                                                 //+ '&desc_full=' + window.escape('Another staff member with the above permission may authorize this specific action.  Please notify your library administrator if you need this permission.  If you feel you have received this exception in error, inform your friendly Evergreen developers of the above permission and this debug information: ' + name),
380                                                 //'simple_auth' + (new Date()).toString(),
381                                                 'Authorize',
382                                                 'chrome,resizable,modal,width=700,height=500',
383                                                 {
384                                                         'login_type' : 'temp',
385                                                         'desc_brief' : 'Permission Denied: ' + robj.ilsperm,
386                                                         'desc_full' : 'Another staff member with the above permission may authorize this specific action.  Please notify your library administrator if you need this permission.  If you feel you have received this exception in error, please inform your friendly Evergreen developers or helpdesk staff of the above permission and this debug information: ' + name,
387                                                         //'simple_auth' : (new Date()).toString(),
388                                                 }
389                                         );
390                                         JSAN.use('OpenILS.data');
391                                         //var data = new OpenILS.data(); data.init({'via':'stash'});
392                                         if (typeof my_xulG.temporary_session != 'undefined' && my_xulG.temporary_session != '') {
393                                                 params[0] = my_xulG.temporary_session.key;
394                                                 req = obj._request(app,name,params,null,override_params,_params);
395                                         }
396                                 }
397                         }
398                 } catch(E) {
399                         this.error.sdump('D_ERROR',E);
400                 }
401                 return req;
402         },
403
404         'rerequest_on_override' : function (app,name,params,req,override_params,_params) {
405                 var obj = this;
406                 try {
407                         if (!override_params.text) override_params.text = {};
408                         function override(r) {
409                                 try {
410                                         netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
411                                         obj.sound.bad();
412                                         var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">' + 
413                                                 '<groupbox><caption label="Exceptions"/>' + 
414                                                 '<grid><columns><column/><column/></columns><rows>';
415                                         for (var i = 0; i < r.length; i++) {
416                                                 var t1 = String(r[i].ilsevent).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
417                                                 var t2 = String(r[i].textcode).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
418                                                 var t3 = String((override_params.text[r[i].ilsevent] ? override_params.text[r[i].ilsevent](r[i]) : '')).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
419                                                 var t4 = String(r[i].desc).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
420                                                 xml += '<row>' + 
421                                                         '<description style="color: red" tooltiptext="' + t1 + '">' + t2 + '</description>' + 
422                                                         '<description>' + t3 + '</description>' + 
423                                                         '</row><row>' + '<description>' + t4 + '</description>' + '</row>';
424                                         }
425                                         xml += '</rows></grid></groupbox><groupbox><caption label="Override"/><hbox>' + 
426                                                 '<description>Force this action?</description>' + 
427                                                 '<button accesskey="N" label="No" name="fancy_cancel"/>' + 
428                                                 '<button id="override" accesskey="Y" label="Yes" name="fancy_submit" value="override"/></hbox></groupbox></vbox>';
429                                         //JSAN.use('OpenILS.data');
430                                         //var data = new OpenILS.data(); data.init({'via':'stash'});
431                                         //data.temp_override_xml = xml; data.stash('temp_override_xml');
432                                         JSAN.use('util.window'); var win = new util.window();
433                                         var fancy_prompt_data = win.open(
434                                                 urls.XUL_FANCY_PROMPT,
435                                                 //+ '?xml_in_stash=temp_override_xml'
436                                                 //+ '&title=' + window.escape(override_params.title),
437                                                 'fancy_prompt', 'chrome,resizable,modal,width=700,height=500',
438                                                 { 'xml' : xml, 'title' : override_params.title }
439                                         );
440                                         if (fancy_prompt_data.fancy_status == 'complete') {
441                                                 req = obj._request(app,name + '.override',params);
442                                         }
443                                         return req;
444                                 } catch(E) {
445                                         alert('in util.network, rerequest_on_override, override:' + E);
446                                 }
447                         }
448
449                         var result = obj.get_result(req);
450                         if (!result) return req;
451
452                         if ( (typeof result.ilsevent != 'undefined') && (override_params.overridable_events.indexOf(result.ilsevent) != -1) ) {
453                                 req = override([result]);
454                         } else {
455                                 var found_good = false; var found_bad = false;
456                                 for (var i = 0; i < result.length; i++) {
457                                         if ( (result[i].ilsevent != 'undefined') && (override_params.overridable_events.indexOf(result[i].ilsevent) != -1) ) {
458                                                 found_good = true;
459                                         } else {
460                                                 found_bad = true;
461                                         }
462                                 }
463                                 if (found_good && (!found_bad)) req = override(result);
464                         }
465
466                         return req;
467                 } catch(E) {
468                         throw(E);
469                 }
470         },
471
472
473 }
474
475 /*
476 function sample_callback(request) {
477         var result = request.getResultObject();
478 }
479 */
480
481 dump('exiting util/network.js\n');