Merge branch '2015.11-develop' into 2016.11
[tine20] / tine20 / Tinebase / js / tineInit.js
1 /*
2  * Tine 2.0
3  * 
4  * @package     Tine
5  * @subpackage  Tinebase
6  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
7  * @author      Cornelius Weiss <c.weiss@metaways.de>
8  * @copyright   Copyright (c) 2007-2013 Metaways Infosystems GmbH (http://www.metaways.de)
9  *
10  * TODO         allow to add user defined part to Tine.title
11  */
12
13 /*global Ext, Tine, google, OpenLayers, Locale, */
14
15 /** ------------------------- Ext.ux Initialisation ------------------------ **/
16
17 Ext.ux.Printer.BaseRenderer.prototype.stylesheetPath = 'Tinebase/js/ux/Printer/print.css';
18
19
20 /** ------------------------ Tine 2.0 Initialisation ----------------------- **/
21
22 /**
23  * @class Tine
24  * @singleton
25  */
26 Ext.namespace('Tine', 'Tine.Tinebase', 'Tine.Calendar');
27
28 /**
29  * version of Tine 2.0 javascript client version, gets set a build / release time <br>
30  * <b>Supported Properties:</b>
31  * <table>
32  *   <tr><td><b>buildType</b></td><td> type of build</td></tr>
33  *   <tr><td><b>buildDate</b></td><td> date of build</td></tr>
34  *   <tr><td><b>buildRevision</b></td><td> revision of build</td></tr>
35  *   <tr><td><b>codeName</b></td><td> codename of release</td></tr>
36  *   <tr><td><b>packageString</b></td><td> packageString of release</td></tr>
37  *   <tr><td><b>releaseTime</b></td><td> releaseTime of release</td></tr>
38  * </table>
39  * @type {Object}
40  */
41 Tine.clientVersion = {};
42 Tine.clientVersion.buildType        = 'none';
43 Tine.clientVersion.buildDate        = 'none';
44 Tine.clientVersion.buildRevision    = 'none';
45 Tine.clientVersion.codeName         = 'none';
46 Tine.clientVersion.packageString    = 'none';
47 Tine.clientVersion.releaseTime      = 'none';
48
49 /**
50  * title of app (gets set at build time)
51  * 
52  * @type String
53  */
54 Tine.logo = 'images/tine_logo.png';
55 Tine.favicon;
56 Tine.title = 'Tine 2.0';
57 Tine.weburl = 'http://www.tine20.com/1/welcome-community/';
58 Tine.helpUrl = 'https://wiki.tine20.org/Main_Page';
59 Tine.bugreportUrl = 'https://api.tine20.net/bugreport.php';
60
61 /**
62  * quiet logging in release mode
63  */
64 Ext.LOGLEVEL = Tine.clientVersion.buildType === 'RELEASE' ? 0 : 7;
65 Tine.log = Ext.ux.log;
66
67 Ext.namespace('Tine.Tinebase');
68
69 /**
70  * @class Tine.Tinebase.tineInit
71  * @namespace Tine.Tinebase
72  * @sigleton
73  * static tine init functions
74  */
75 Tine.Tinebase.tineInit = {
76     /**
77      * @cfg {String} getAllRegistryDataMethod
78      */
79     getAllRegistryDataMethod: 'Tinebase.getAllRegistryData',
80
81     /**
82      * @cfg {Boolean} stateful
83      */
84     stateful: true,
85
86     /**
87      * @cfg {String} jsonKeyCookieId
88      */
89     jsonKeyCookieId: 'TINE20JSONKEY',
90
91     /**
92      * @cfg {String} requestUrl
93      */
94     requestUrl: 'index.php',
95     
96     /**
97      * prefix for localStorage keys
98      * @type String
99      */
100     lsPrefix: Tine.Tinebase.common.getUrl('path') + 'Tine',
101     
102     onPreferenceChangeRegistered: false,
103     
104     initWindow: function () {
105         Ext.getBody().on('keydown', function (e) {
106             if (e.ctrlKey && e.getKey() === e.A && ! (e.getTarget('form') || e.getTarget('input') || e.getTarget('textarea'))) {
107                 // disable the native 'select all'
108                 e.preventDefault();
109             } else if (e.getKey() === e.BACKSPACE && ! (e.getTarget('form') || e.getTarget('input') || e.getTarget('textarea'))) {
110                 // disable the native 'history back'
111                 e.preventDefault();
112             } else if (!window.isMainWindow && e.ctrlKey && e.getKey() === e.T) {
113                 // disable the native 'new tab' if in popup window
114                 e.preventDefault();
115             } else if (window.isMainWindow && e.ctrlKey && e.getKey() === e.L) {
116                 // reload on ctrl-l
117                 Tine.Tinebase.common.reload({
118                     clearCache: true
119                 });
120             }
121         });
122         
123         // disable generic drops
124         Ext.getBody().on('dragover', function (e) {
125             e.stopPropagation();
126             e.preventDefault();
127             e.browserEvent.dataTransfer.dropEffect = 'none';
128         }, this);
129     },
130
131     checkWebpack: function() {
132         if (! window.postal) {
133             var wikiurl = 'https://wiki.tine20.org/Developers/Getting_Started/Working_with_GIT#Install_webpack';
134             Ext.Msg.alert('Webpack-dev-server missing?',
135                 'You need to install and run webpack-dev-server! <a target="_blank" href="' + wikiurl + '">Installation instructions in the Wiki</a>.', function() {
136                 Tine.Tinebase.common.reload();
137             });
138         }
139     },
140
141     initPostal: function () {
142         if (! window.postal) return;
143
144         var config = postal.fedx.transports.xwindow.configure();
145         postal.fedx.transports.xwindow.configure( {
146             localStoragePrefix: Tine.Tinebase.tineInit.lsPrefix + '.' + config.localStoragePrefix
147         } );
148         postal.instanceId('xwindow-' + _.random(0,1000));
149         postal.configuration.promise.createDeferred = function() {
150             return Promise.defer();
151         };
152         postal.configuration.promise.getPromise = function(dfd) {
153             return dfd.promise;
154         };
155         postal.fedx.addFilter( [
156             { channel: 'thirdparty', topic: '#', direction: 'both' },
157             //{ channel: 'postal.request-response', topic: '#', direction: 'both' }
158         ] );
159         postal.fedx.signalReady();
160
161         postal.addWireTap( function( d, e ) {
162             Tine.log.debug( "ID: " + postal.instanceId() + " " + JSON.stringify( e, null, 4 ) );
163         } );
164     },
165     
166     initDebugConsole: function () {
167         var map = new Ext.KeyMap(Ext.getDoc(), [{
168             key: [122], // F11
169             ctrl: true,
170             fn: Tine.Tinebase.common.showDebugConsole
171         }]);
172     },
173
174     /**
175      * Each window has exactly one viewport containing a card layout in its lifetime
176      * The default card is a splash screen.
177      * 
178      * defautl wait panel (picture only no string!)
179      */
180     initBootSplash: function () {
181         
182         this.splash = {
183             xtype: 'container',
184             id: 'tine-viewport-waitcycle',
185             border: false,
186             layout: 'fit',
187             width: 16,
188             height: 16,
189             // the content elements come from the initial html so they are displayed fastly
190             contentEl: Ext.select('div[class^=tine-viewport-]')
191         };
192         
193         Tine.Tinebase.viewport = new Ext.Viewport({
194             layout: 'fit',
195             border: false,
196             items: {
197                 xtype: 'container',
198                 id: 'tine-viewport-maincardpanel',
199                 ref: 'tineViewportMaincardpanel',
200                 isWindowMainCardPanel: true,
201                 layout: 'card',
202                 border: false,
203                 activeItem: 0,
204                 items: this.splash
205             }
206         });
207     },
208
209     initLoginPanel: function() {
210         if (window.isMainWindow && ! Tine.loginPanel) {
211             var mainCardPanel = Tine.Tinebase.viewport.tineViewportMaincardpanel;
212             Tine.loginPanel = new Tine.Tinebase.LoginPanel({
213                 defaultUsername: Tine.Tinebase.registry.get('defaultUsername'),
214                 defaultPassword: Tine.Tinebase.registry.get('defaultPassword')
215             });
216             mainCardPanel.add(Tine.loginPanel);
217         }
218         
219         // event firing is unpredictable in IE9/10/11, you'll never know when it comes ...
220         if (! Ext.isNewIE) {
221             Tine.Tinebase.registry.on('replace', function(key, oldValue, newValue) {
222                 if (oldValue && !newValue) {
223                     Tine.log.info('tineInit::initLoginPanel - handle logout in other window');
224                     if (window.isMainWindow) {
225                         Tine.Tinebase.common.reload();
226                     } else {
227                         Ext.ux.PopupWindow.close(window);
228                     }
229                 }
230             }, this, 'currentAccount');
231         }
232     },
233
234     showLoginBox: function(cb, scope) {
235         var mainCardPanel = Tine.Tinebase.viewport.tineViewportMaincardpanel,
236             activeItem = mainCardPanel.layout.activeItem;
237
238         mainCardPanel.layout.setActiveItem(Tine.loginPanel.id);
239         Tine.loginPanel.doLayout();
240         Tine.loginPanel.onLogin = function(response) {
241             mainCardPanel.layout.setActiveItem(activeItem);
242             cb.call(scope||window, response);
243         };
244
245 //        //listen for other windows login?
246 //        Tine.Tinebase.registry.on('replace', function() {
247 //            mainCardPanel.layout.setActiveItem(activeItem);
248 //        }, this, 'currentAccount');
249
250     },
251
252     renderWindow: function () {
253         Tine.log.info('renderWindow::start');
254         
255         var mainCardPanel = Tine.Tinebase.viewport.tineViewportMaincardpanel;
256
257         // check if user is already logged in
258         if (! Tine.Tinebase.registry.get('currentAccount')) {
259             Tine.Tinebase.tineInit.showLoginBox(function(response){
260                 Tine.log.info('tineInit::renderWindow -fetch users registry');
261                 Tine.Tinebase.tineInit.initRegistry(true, function() {
262                     Tine.log.info('tineInit::renderWindow - registry fetched, render main window');
263                     Ext.MessageBox.hide();
264                     Tine.Tinebase.tineInit.initWindowMgr();
265                     Tine.Tinebase.tineInit.renderWindow();
266                 });
267             });
268             
269             return;
270         }
271
272         // experimental deep link
273         if (window.location.hash) {
274             var hash = window.location.hash.replace(/^#+/, ''),
275                 config;
276
277             if (hash.match(/\//)) {
278                 var args = hash.split('/'),
279                     app = Tine.Tinebase.appMgr.get(args.shift()),
280                     method = args.shift();
281
282                 config = app.dispatchRoute(method, args);
283
284             } else {
285                 //http://tine.example.com/#{"name":"TimesheetEditWindow_0","contentPanelConstructor":"Tine.Timetracker.TimesheetEditDialog","recordId":0}
286                 config = Ext.decode(hash);
287             }
288
289             if (window.history && window.history.replaceState) {
290                 window.history.replaceState({}, document.title, Tine.Tinebase.common.getUrl());
291             }
292
293             // what about plugins?
294             Ext.applyIf(config, {
295                 name: window.name,
296                 popup: window
297             });
298
299             window.name = config.name;
300
301             // disable mainWindows per hash for the moment. MainWindow concept needs to be rethought
302             // in the context of window manager rewrite
303             window.isMainWindow = false;
304
305             Ext.ux.PopupWindowMgr.register(new Ext.ux.PopupWindow(config));
306         }
307
308         /**
309          * register MainWindow
310          */
311         else if (window.isMainWindow) {
312             Ext.ux.PopupWindowMgr.register({
313                 name: window.name,
314                 popup: window,
315                 contentPanelConstructor: 'Tine.Tinebase.MainScreenPanel'
316             });
317         }
318
319
320         Tine.log.info('renderWindow::before get window');
321         
322         // fetch window config from WindowMgr
323         var c = Ext.ux.PopupWindowMgr.get(window) || {};
324         
325         // set window title
326         window.document.title = Ext.util.Format.stripTags(c.title ? c.title : window.document.title);
327         
328         Tine.log.info('renderWindow::getCenterPanel');
329         
330         // finally render the window contents in a new card
331         var card = Tine.WindowFactory.getCenterPanel(c);
332         mainCardPanel.add(card);
333         mainCardPanel.layout.setActiveItem(card.id);
334         card.doLayout();
335         
336         window.initializationComplete = true;
337     },
338
339     initAjax: function () {
340         Ext.Ajax.url = Tine.Tinebase.tineInit.requestUrl;
341         Ext.Ajax.method = 'POST';
342         
343         Ext.Ajax.defaultHeaders = {
344             'X-Tine20-Request-Type' : 'JSON'
345         };
346         
347         Ext.Ajax.transactions = {};
348
349         Tine.Tinebase.tineInit.jsonKeyCookieProvider = new Ext.ux.util.Cookie();
350
351         /**
352          * inspect all requests done via the ajax singleton
353          * 
354          * - send custom headers
355          * - send json key 
356          * - implicitly transform non jsonrpc requests
357          * 
358          * NOTE: implicitly transformed reqeusts get their callback fn's proxied 
359          *       through generic response inspectors as defined below
360          */
361         Ext.Ajax.on('beforerequest', function (connection, options) {
362
363             var jsonKey = Tine.Tinebase.registry && Tine.Tinebase.registry.get ? Tine.Tinebase.registry.get('jsonKey') : '';
364             if (Tine.Tinebase.tineInit.jsonKeyCookieProvider.get(this.jsonKeyCookieId)) {
365                 var cookieJsonKey = Tine.Tinebase.tineInit.jsonKeyCookieProvider.get(this.jsonKeyCookieId);
366                 Tine.Tinebase.tineInit.jsonKeyCookieProvider.clear(this.jsonKeyCookieId);
367                 // NOTE cookie reset is not always working in IE, so we need to check jsonKey again
368                 if (cookieJsonKey && cookieJsonKey != "null") {
369                     jsonKey = cookieJsonKey;
370                     Tine.Tinebase.registry.set('jsonKey', jsonKey);
371                 }
372             }
373
374             options.headers = options.headers || {};
375             options.headers['X-Tine20-JsonKey'] = jsonKey;
376             options.headers['X-Tine20-TransactionId'] = Tine.Tinebase.data.Record.generateUID();
377             
378             options.url = Ext.urlAppend((options.url ? options.url : Tine.Tinebase.tineInit.requestUrl),  'transactionid=' + options.headers['X-Tine20-TransactionId']);
379             
380             // convert non Ext.Direct request to jsonrpc
381             // - convert params
382             // - convert error handling
383             if (options.params && !options.isUpload) {
384                 var params = {};
385                 
386                 var def = Tine.Tinebase.registry.get('serviceMap') ? Tine.Tinebase.registry.get('serviceMap').services[options.params.method] : false;
387                 if (def) {
388                     // sort parms according to def
389                     for (var i = 0, p; i < def.parameters.length; i += 1) {
390                         p = def.parameters[i].name;
391                         params[p] = options.params[p];
392                     }
393                 } else {
394                     for (var param in options.params) {
395                         if (options.params.hasOwnProperty(param) && param !== 'method') {
396                             params[param] = options.params[param];
397                         }
398                     }
399                 }
400                 
401                 options.jsonData = Ext.encode({
402                     jsonrpc: '2.0',
403                     method: options.params.method,
404                     params: params,
405                     id: ++Ext.Direct.TID
406                 });
407                 
408                 options.cbs = {};
409                 options.cbs.success  = options.success  || null;
410                 options.cbs.failure  = options.failure  || null;
411                 options.cbs.callback = options.callback || null;
412                 
413                 options.isImplicitJsonRpc = true;
414                 delete options.params;
415                 delete options.success;
416                 delete options.failure;
417                 delete options.callback;
418             }
419             
420             Ext.Ajax.transactions[options.headers['X-Tine20-TransactionId']] = {
421                 date: new Date(),
422                 json: options.jsonData
423             };
424         });
425
426
427         
428         /**
429          * inspect completed responses => staus code == 200
430          * 
431          * - detect resoponse errors (e.g. html from xdebug) and convert to exceptional states
432          * - implicitly transform requests from JSONRPC
433          * 
434          *  NOTE: All programatically catchable exceptions lead to successfull requests
435          *        with the jsonprc protocol. For implicitly converted jsonprc requests we 
436          *        transform error states here and route them to the error methods defined 
437          *        in the request options
438          *        
439          *  NOTE: Illegal json data responses are mapped to error code 530
440          *        Empty resonses (Ext.Decode can't deal with them) are maped to 540
441          *        Memory exhausted to 550
442          */
443         Ext.Ajax.on('requestcomplete', function (connection, response, options) {
444             delete Ext.Ajax.transactions[options.headers['X-Tine20-TransactionId']];
445             
446             // detect resoponse errors (e.g. html from xdebug) and convert into error response
447             if (! options.isUpload && ! response.responseText.match(/^([{\[])|(<\?xml)+/)) {
448                 var exception = {
449                     code: response.responseText !== "" ? 530 : 540,
450                     message: response.responseText !== "" ? 'illegal json data in response' : 'empty response',
451                     traceHTML: response.responseText,
452                     request: options.jsonData,
453                     response: response.responseText
454                 };
455                 
456                 // Fatal error: Allowed memory size of n bytes exhausted (tried to allocate m bytes) 
457                 if (response.responseText.match(/^Fatal error: Allowed memory size of /m)) {
458                     Ext.apply(exception, {
459                         code: 550,
460                         message: response.responseText
461                     });
462                 }
463                 
464                 // encapsulate as jsonrpc response
465                 var requestOptions = Ext.decode(options.jsonData);
466                 response.responseText = Ext.encode({
467                     jsonrpc: requestOptions.jsonrpc,
468                     id: requestOptions.id,
469                     error: {
470                         code: -32000,
471                         message: exception.message,
472                         data: exception
473                     }
474                 });
475             }
476             
477             // strip jsonrpc fragments for non Ext.Direct requests
478             if (options.isImplicitJsonRpc) {
479                 var jsonrpc = Ext.decode(response.responseText);
480                 if (jsonrpc.result) {
481                     response.responseText = Ext.encode(jsonrpc.result);
482                     
483                     if (options.cbs.success) {
484                         options.cbs.success.call(options.scope, response, options);
485                     }
486                     if (options.cbs.callback) {
487                         options.cbs.callback.call(options.scope, options, true, response);
488                     }
489                 } else {
490                     
491                     response.responseText = Ext.encode(jsonrpc.error);
492                     
493                     if (options.cbs.failure) {
494                         options.cbs.failure.call(options.scope, response, options);
495                     } else if (options.cbs.callback) {
496                         options.cbs.callback.call(options.scope, options, false, response);
497                     } else {
498                         var responseData = Ext.decode(response.responseText);
499                             
500                         exception = responseData.data ? responseData.data : responseData;
501                         exception.request = options.jsonData;
502                         exception.response = response.responseText;
503                         
504                         Tine.Tinebase.ExceptionHandler.handleRequestException(exception);
505                     }
506                 }
507             }
508         });
509         
510         /**
511          * inspect request exceptions
512          *  - convert to jsonrpc compatiple exceptional states
513          *  - call generic exception handler if no handler is defined in request options
514          *  
515          * NOTE: Request exceptions are exceptional state from web-server:
516          *       -> status codes != 200 : This kind of exceptions are not part of the jsonrpc protocol
517          *       -> timeouts: status code 520
518          */
519         Ext.Ajax.on('requestexception', function (connection, response, options) {
520             delete Ext.Ajax.transactions[options.headers['X-Tine20-TransactionId']];
521             // map connection errors to errorcode 510 and timeouts to 520
522             var errorCode = response.status > 0 ? response.status :
523                             (response.status === 0 ? 510 : 520);
524                             
525             // convert into error response
526             if (! options.isUpload) {
527                 var exception = {
528                     code: errorCode,
529                     message: 'request exception: ' + response.statusText,
530                     traceHTML: response.responseText,
531                     request: options.jsonData,
532                     requestHeaders: options.headers,
533                     openTransactions: Ext.Ajax.transactions,
534                     response: response.responseText
535                 };
536                 
537                 // encapsulate as jsonrpc response
538                 var requestOptions = Ext.decode(options.jsonData);
539                 response.responseText = Ext.encode({
540                     jsonrpc: requestOptions.jsonrpc,
541                     id: requestOptions.id,
542                     error: {
543                         code: -32000,
544                         message: exception.message,
545                         data: exception
546                     }
547                 });
548             }
549             
550             // NOTE: Tine.data.RecordProxy is implicitRPC atm.
551             if (options.isImplicitJsonRpc) {
552                 var jsonrpc = Ext.decode(response.responseText);
553                 
554                 response.responseText = Ext.encode(jsonrpc.error);
555                     
556                 if (options.cbs.failure) {
557                     options.cbs.failure.call(options.scope, response, options);
558                 } else if (options.cbs.callback) {
559                     options.cbs.callback.call(options.scope, options, false, response);
560                 } else {
561                     var responseData = Ext.decode(response.responseText);
562                     
563                     exception = responseData.data ? responseData.data : responseData;
564                     
565                     Tine.Tinebase.ExceptionHandler.handleRequestException(exception);
566                 }
567                 
568             } else if (! options.failure && ! options.callback) {
569                 Tine.Tinebase.ExceptionHandler.handleRequestException(exception);
570             }
571         });
572     },
573
574     /**
575      * init registry
576      *
577      * @param {Boolean} forceReload
578      * @param {Function} cb
579      * @param {Object} scope
580      */
581     initRegistry: function (forceReload, cb, scope) {
582         Tine.Tinebase.registry = store.namespace(Tine.Tinebase.tineInit.lsPrefix + '.' + 'Tinebase.registry');
583
584         var version = Tine.Tinebase.registry.get('version'),
585             userApplications = Tine.Tinebase.registry.get('userApplications') || [];
586
587         var reloadNeeded =
588                !version
589             || !userApplications
590             || userApplications.length < 2;
591
592         if (forceReload || reloadNeeded) {
593             Tine.Tinebase.tineInit.clearRegistry();
594
595             Ext.Ajax.request({
596                 timeout: 120000, // 2 minutes
597                 params: {
598                     method: Tine.Tinebase.tineInit.getAllRegistryDataMethod
599                 },
600                 failure: function () {
601                     // if registry could not be loaded, this is mostly due to missconfiguaration
602                     // don't send error reports for that!
603                     Tine.Tinebase.ExceptionHandler.handleRequestException({
604                         code: 503
605                     });
606                 },
607                 success: function (response, request) {
608                     var registryData = Ext.util.JSON.decode(response.responseText);
609                     for (var app in registryData) {
610                         if (registryData.hasOwnProperty(app)) {
611                             var appData = registryData[app];
612                             Ext.ns('Tine.' + app);
613                             Tine[app].registry = store.namespace(Tine.Tinebase.tineInit.lsPrefix + '.' + app + '.registry');
614
615                             for (var key in appData) {
616                                 if (appData.hasOwnProperty(key)) {
617                                     if (key === 'preferences') {
618                                         Tine[app].preferences = store.namespace(Tine.Tinebase.tineInit.lsPrefix + '.' + app + '.preferences');
619                                         for (var pref in appData[key]) {
620                                             if (appData[key].hasOwnProperty(pref)) {
621                                                 Tine[app].preferences.set(pref, appData[key][pref]);
622                                             }
623                                         }
624
625                                     } else {
626                                         Tine[app].registry.set(key, appData[key]);
627                                     }
628                                 }
629                             }
630                         }
631                     }
632
633                     Tine.Tinebase.tineInit.onRegistryLoad();
634
635                     cb.call(scope);
636                 }
637             });
638         } else {
639             for (var app,i=0;i<userApplications.length;i++) {
640                 app = userApplications[i].name;
641                 Ext.ns('Tine.' + app);
642                 Tine[app].registry = store.namespace(Tine.Tinebase.tineInit.lsPrefix + '.' + app + '.registry');
643                 Tine[app].preferences = store.namespace(Tine.Tinebase.tineInit.lsPrefix + '.' + app + '.preferences');
644             }
645
646             Tine.Tinebase.tineInit.onRegistryLoad();
647             cb.call(scope);
648         }
649
650
651     },
652
653     /**
654      * apply registry data
655      */
656     onRegistryLoad: function() {
657         if (! Tine.Tinebase.tineInit.onPreferenceChangeRegistered 
658             && Tine.Tinebase.registry.get('preferences')
659             && Tine.Tinebase.registry.get('currentAccount')
660             && ! Ext.isNewIE
661         ) {
662             Tine.log.info('tineInit::onRegistryLoad - register onPreferenceChange handler');
663             Tine.Tinebase.preferences.on('replace', Tine.Tinebase.tineInit.onPreferenceChange);
664             Tine.Tinebase.tineInit.onPreferenceChangeRegistered = true;
665         }
666
667         Tine.helpUrl = Tine.Tinebase.registry.get('helpUrl') || Tine.helpUrl;
668         //Do we have a custom weburl for branding?
669         Tine.weburl = Tine.Tinebase.registry.get('brandingWeburl') ? Tine.Tinebase.registry.get('brandingWeburl') : Tine.weburl;
670         //DO we have a custom title for branding?
671         Tine.title = Tine.Tinebase.registry.get('brandingTitle') ? Tine.Tinebase.registry.get('brandingTitle') : Tine.title;
672         Tine.logo = Tine.Tinebase.registry.get('brandingLogo') ? Tine.Tinebase.registry.get('brandingLogo') : Tine.logo;
673         Tine.favicon = Tine.Tinebase.registry.get('brandingFavicon') ? Tine.Tinebase.registry.get('brandingFavicon') : Tine.favicon;
674         
675         Ext.override(Ext.ux.file.Upload, {
676             maxFileUploadSize: Tine.Tinebase.registry.get('maxFileUploadSize'),
677             maxPostSize: Tine.Tinebase.registry.get('maxPostSize')
678         });
679
680         Tine.Tinebase.tineInit.initExtDirect();
681
682         Tine.Tinebase.tineInit.initState();
683
684         if (Tine.Tinebase.registry.get('currentAccount')) {
685             Tine.Tinebase.tineInit.initAppMgr();
686         }
687
688         Tine.Tinebase.tineInit.initUploadMgr();
689
690         Tine.Tinebase.tineInit.initLoginPanel();
691     },
692
693     /**
694      * remove all registry data
695      */
696     clearRegistry: function() {
697         Tine.log.info('tineInit::clearRegistry');
698         if (Ext.isFunction(store.namespace)) {
699             store.namespace(Tine.Tinebase.tineInit.lsPrefix).clearAll();
700         }
701     },
702
703     /**
704      * executed when a value in Tinebase registry/preferences changed
705      *
706      * @param {string} key
707      * @param {value} oldValue
708      * @param {value} newValue
709      */
710     onPreferenceChange: function (key, oldValue, newValue) {
711         if (Tine.Tinebase.tineInit.isReloading) {
712             return;
713         }
714         
715         switch (key) {
716             case 'windowtype':
717             case 'confirmLogout':
718             case 'timezone':
719             case 'locale':
720                 Tine.log.info('tineInit::onPreferenceChange - reload mainscreen');
721                 Tine.Tinebase.common.reload({
722                     clearCache: key == 'locale'
723                 });
724
725                 break;
726         }
727     },
728     
729     /**
730      * initialise window and windowMgr (only popup atm.)
731      */
732     initWindowMgr: function () {
733         /**
734          * initialise window types
735          */
736         var windowType = 'Browser';
737         Ext.ux.PopupWindow.prototype.url = 'index.php';
738
739         if (Tine.Tinebase.registry && Tine.Tinebase.registry.get('preferences')) {
740             // update window factory window type (required after login)
741             windowType = Tine.Tinebase.registry.get('preferences').get('windowtype');
742             if (! windowType) {
743                 windowType = 'Browser';
744             }
745         }
746
747         Tine.WindowFactory = new Ext.ux.WindowFactory({
748             windowType: windowType
749         });
750
751         // init ApplicationStarter on Ext window once
752         if (windowType == 'Ext') {
753             Tine.Tinebase.ApplicationStarter.init();
754         }
755     },
756     /**
757      * initialise state provider
758      */
759     initState: function () {
760         if (Tine.Tinebase.tineInit.stateful === true) {
761             if (window.isMainWindow || Ext.isIE) {
762                 // NOTE: IE is as always pain in the ass! cross window issues prohibit serialisation of state objects
763                 Ext.state.Manager.setProvider(new Tine.Tinebase.StateProvider());
764             } else {
765                 var mainWindow = Ext.ux.PopupWindowMgr.getMainWindow();
766                 Ext.state.Manager = mainWindow.Ext.state.Manager;
767             }
768         }
769     },
770     
771     /**
772      * add provider to Ext.Direct based on Tine servicemap
773      */
774     initExtDirect: function () {
775         var sam = Tine.Tinebase.registry.get('serviceMap');
776         
777         Ext.Direct.addProvider(Ext.apply(sam, {
778             'type'     : 'jsonrpcprovider',
779             'namespace': 'Tine',
780             'url'      : sam.target
781         }));
782     },
783     
784     /**
785      * init external libraries
786      */
787     initLibs: function () {
788         if (OpenLayers) {
789             // fix OpenLayers script location to find images/themes/...
790             OpenLayers._getScriptLocation = function () {
791                 return 'library/OpenLayers/';
792             };
793         }
794     },
795     
796     /**
797      * initialise application manager
798      */
799     initAppMgr: function () {
800         if (! Ext.isIE9 && ! Ext.isIE && ! window.isMainWindow) {
801             // return app from main window for non-IE browsers
802             Tine.Tinebase.appMgr = Ext.ux.PopupWindowMgr.getMainWindow().Tine.Tinebase.appMgr;
803         } else {
804             Tine.Tinebase.appMgr = new Tine.Tinebase.AppManager();
805         }
806     },
807     
808     /**
809      * initialise upload manager
810      */
811     initUploadMgr: function () {
812         Tine.Tinebase.uploadManager = new Ext.ux.file.UploadManager();
813     },
814     
815     /**
816      * config locales
817      */
818     initLocale: function () {
819         //Locale.setlocale(Locale.LC_ALL, '');
820         window.i18n = new Locale.Gettext();
821         window.i18n.textdomain('Tinebase');
822
823         window._ = function (msgid) {
824             Tine.log.warn('_() is deprecated, please use i18n._ instead' + new Error().stack);
825             return window.i18n.dgettext('Tinebase', msgid);
826         };
827
828         Tine.Tinebase.prototypeTranslation();
829     }
830 };
831
832 Ext.onReady(function () {
833     Tine.Tinebase.tineInit.initWindow();
834     Tine.Tinebase.tineInit.checkWebpack();
835     Tine.Tinebase.tineInit.initPostal();
836     Tine.Tinebase.tineInit.initDebugConsole();
837     Tine.Tinebase.tineInit.initBootSplash();
838     Tine.Tinebase.tineInit.initLocale();
839     Tine.Tinebase.tineInit.initAjax();
840     Tine.Tinebase.tineInit.initLibs();
841
842     Tine.Tinebase.tineInit.initRegistry(false, function() {
843         Tine.Tinebase.tineInit.initWindowMgr();
844         Tine.Tinebase.tineInit.renderWindow();
845     });
846 });