diff --git a/addons/web/common/http.py b/addons/web/common/http.py index 620e3a548dc..4bdd87a6764 100644 --- a/addons/web/common/http.py +++ b/addons/web/common/http.py @@ -6,12 +6,12 @@ import ast import contextlib import functools import logging -import urllib import os import pprint import sys import threading import traceback +import urllib import uuid import xmlrpclib @@ -137,20 +137,19 @@ class JsonRequest(WebRequest): :returns: an utf8 encoded JSON-RPC2 or JSONP reply """ - method = self.httprequest.method args = self.httprequest.args jsonp = args.get('jsonp', False) requestf = None request = None - if jsonp and method == 'POST': + if jsonp and self.httprequest.method == 'POST': # jsonp 2 steps step1 POST: save call self.init(args) req.session.jsonp_requests[args.get('id')] = self.httprequest.form['r'] headers=[('Content-Type', 'text/plain; charset=utf-8')] r = werkzeug.wrappers.Response(request_id, headers=headers) return r - elif args['jsonp'] and args.get('id'): + elif jsonp and args.get('id'): # jsonp 2 steps step2 GET: run and return result self.init(args) request = self.session.jsonp_requests.pop(args.get(id), "") @@ -195,6 +194,8 @@ class JsonRequest(WebRequest): } } except Exception: + logging.getLogger(__name__ + '.JSONRequest.dispatch').exception\ + ("An error occured while handling a json request") error = { 'code': 300, 'message': "OpenERP WebClient Error", @@ -205,9 +206,9 @@ class JsonRequest(WebRequest): } if error: response["error"] = error - _logger.error("[%s] <--\n%s", rid, pprint.pformat(response)) - elif _logger.isEnabledFor(logging.DEBUG): - _logger.debug("[%s] <--\n%s", rid, pprint.pformat(response)) + + if _logger.isEnabledFor(logging.DEBUG): + _logger.debug("<--\n%s", pprint.pformat(response)) if jsonp: mime = 'application/javascript' diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index e745020c594..9c6edcf378a 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -10,6 +10,7 @@ import os import re import simplejson import time +import urllib2 import xmlrpclib import zlib from xml.etree import ElementTree @@ -245,7 +246,7 @@ class WebClient(openerpweb.Controller): class Proxy(openerpweb.Controller): _cp_path = '/web/proxy' - @jsonrequest + @openerpweb.jsonrequest def load(self, req, path): #req.config.socket_port #if not re.match('^/[^/]+/static/.*', path): @@ -254,7 +255,7 @@ class Proxy(openerpweb.Controller): env = req.httprequest.environ port = env['SERVER_PORT'] - o = urllib.urlopen('http://127.0.0.1:%s%s' % (port, path)) + o = urllib2.urlopen('http://127.0.0.1:%s%s' % (port, path)) return o.read() class Database(openerpweb.Controller): diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js index 70beb7ecc34..cbf475af44e 100644 --- a/addons/web/static/src/js/chrome.js +++ b/addons/web/static/src/js/chrome.js @@ -1004,20 +1004,12 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie this.header.on_logout.add(this.login.on_logout); this.header.on_action.add(this.on_menu_action); - this.session.on_session_invalid.add(this.login.do_ask_login); - this.session.on_session_valid.add_last(this.header.do_update); - this.session.on_session_invalid.add_last(this.header.do_update); - this.session.on_session_valid.add_last(this.on_logged); - this.session.on_session_invalid.add_last(this.on_logged_out); - - this._current_state = null; - }, start: function() { this._super.apply(this, arguments); var self = this; - openerp.connection.bind("",function() { + this.session.bind().then(function() { var params = {}; if (jQuery.param != undefined && jQuery.deparam(jQuery.param.querystring()).kitten != undefined) { this.$element.addClass("kitten-mode-activated"); @@ -1026,17 +1018,25 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie }); } self.$element.html(QWeb.render("Interface", params)); - openerp.connection.session_restore(); - self.menu = new openerp.web.Menu(self, "oe_menu", "oe_secondary_menu"); self.menu.on_action.add(self.on_menu_action); - self.notification.prependTo(self.$element); self.loading.appendTo($('#oe_loading')); self.header.appendTo($("#oe_header")); self.login.appendTo($('#oe_login')); self.menu.start(); + self.login.on_login_invalid(); + }); + this.session.ready.then(function() { + self.login.on_login_valid(); + self.header.do_update(); + self.menu.do_reload(); + if(self.action_manager) + self.action_manager.stop(); + self.action_manager = new openerp.web.ActionManager(this); + self.action_manager.appendTo($("#oe_app")); + self.bind_hashchange(); }); }, do_reload: function() { @@ -1050,24 +1050,8 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie var n = this.notification; n.warn.apply(n, arguments); }, - on_logged: function() { - this.menu.do_reload(); - if(this.action_manager) - this.action_manager.stop(); - this.action_manager = new openerp.web.ActionManager(this); - this.action_manager.appendTo($("#oe_app")); - - if (openerp._modules_loaded) { // TODO: find better option than this - this.bind_hashchange(); - } else { - this.session.on_modules_loaded.add({ // XXX what about a $.Deferred ? - callback: $.proxy(this, 'bind_hashchange'), - unique: true, - position: 'last' - }) - } - }, - on_logged_out: function() { + on_loggued_out: function() { + this.header.do_update(); $(window).unbind('hashchange', this.on_hashchange); this.do_push_state({}); if(this.action_manager) diff --git a/addons/web/static/src/js/core.js b/addons/web/static/src/js/core.js index 55bce373330..f28d0adfc03 100644 --- a/addons/web/static/src/js/core.js +++ b/addons/web/static/src/js/core.js @@ -352,11 +352,11 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. */ init: function() { this._super(); - // TODO: session should have an optional name indicating that they'll - // be saved to (and revived from) cookies + // TODO: session store in cookie should be optional this.name = openerp._session_id; }, bind: function(host, protocol) { + var self = this; this.host = (host == undefined) ? location.host : host; this.protocol = (protocol == undefined) ? location.protocol : protocol; this.prefix = this.protocol + '//' + this.host; @@ -368,13 +368,13 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. this.username = false; this.user_context= {}; this.db = false; - this.module_loading = $.Deferred(); this.module_list = []; this.module_loaded = {"web": true}; this.context = {}; this.shortcuts = []; this.active_id = null; - this.do_load_qweb(['/web/webclient/qweb'], continuation); + this.ready = $.Deferred(); + return this.session_restore(); }, /** * Executes an RPC call, registering the provided callbacks. @@ -522,74 +522,52 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. }, on_rpc_error: function(error) { }, + /** + * Init a session, reloads from cookie, if it exists + */ + session_restore: function () { + var self = this; + // TODO: session store in cookie should be optional + this.session_id = this.get_cookie('session_id'); + return this.rpc("/web/session/get_session_info", {}).pipe(function(result) { + // If immediately follows a login (triggered by trying to restore + // an invalid session or no session at all), refresh session data + // (should not change, but just in case...) + _.extend(self, { + db: result.db, + username: result.login, + uid: result.uid, + user_context: result.context + }); + var deferred = self.do_load_qweb(['/web/webclient/qweb']); + if(self.uid) { + return deferred.then(self.load_modules()); + } + return deferred; + }); + }, /** * The session is validated either by login or by restoration of a previous session */ - on_session_valid: function(continuation) { - this.load_modules().then(function() { continuation() } ); - }, - on_session_invalid: function(continuation) { - }, - session_is_valid: function() { - return this.uid; - }, - session_authenticate: function(db, login, password, success_callback) { + session_authenticate: function(db, login, password) { var self = this; var base_location = document.location.protocol + '//' + document.location.host; var params = { db: db, login: login, password: password, base_location: base_location }; - return this.rpc("/web/session/authenticate", params, function(result) { + return this.rpc("/web/session/authenticate", params).pipe(function(result) { _.extend(self, { session_id: result.session_id, - uid: result.uid, - user_context: result.context, db: result.db, - username: result.login + username: result.login, + uid: result.uid, + user_context: result.context }); - self.session_save(); - self.on_session_valid(success_callback); - return true; + // TODO: session store in cookie should be optional + self.set_cookie('session_id', this.session_id); + return self.load_modules(); }); }, - /** - * Reloads uid and session_id from local storage, if they exist - */ - session_restore: function (continuation) { - var self = this; - this.session_id = this.get_cookie('session_id'); - return this.rpc("/web/session/get_session_info", {}).then(function(result) { - // If immediately follows a login (triggered by trying to restore - // an invalid session or no session at all), refresh session data - // (should not change, but just in case...) but should not call - // on_session_valid again as it triggers reloading the menu - var already_logged = self.uid; - _.extend(self, { - uid: result.uid, - user_context: result.context, - db: result.db, - username: result.login - }); - if (!already_logged) { - if (self.uid) { - self.on_session_valid(continuation); - } else { - self.on_session_invalid(continuation); - } - } - }, function() { - self.on_session_invalid(continuation); - }); - }, - /** - * Saves the session id and uid locally - */ - session_save: function () { - this.set_cookie('session_id', this.session_id); - }, - logout: function() { + session_logout: function() { this.set_cookie('session_id', ''); - this.reload_client(); - }, - reload_client: function() { window.location.reload(); }, /** @@ -640,19 +618,21 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. self.module_list = result; var lang = self.user_context.lang; var params = { mods: ["web"].concat(result), lang: lang}; - self.rpc('/web/webclient/translations',params).then(function(transs) { + self.rpc('/web/webclient/translations',params).pipe(function(transs) { openerp.web._t.database.set_bundle(transs); var modules = self.module_list.join(','); var file_list = ["/web/static/lib/datejs/globalization/" + self.user_context.lang.replace("_", "-") + ".js" ]; return $.when( - self.rpc('/web/webclient/qweblist', {mods: modules}, self.do_load_qweb), self.rpc('/web/webclient/csslist', {mods: modules}, self.do_load_css), - self.rpc('/web/webclient/jslist', {mods: modules}, function(files) { + self.rpc('/web/webclient/qweblist', {mods: modules}).pipe(self.do_load_qweb), + self.rpc('/web/webclient/jslist', {mods: modules}).pipe(function(files) { self.do_load_js(file_list.concat(files)); }) - ); + ).then(function() { + self.ready.resolve(); + }); }); }); }, @@ -660,7 +640,7 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. var self = this; _.each(files, function (file) { $('head').append($('', { - 'href': self.get_absolute_url(file), + 'href': self.get_url(file), 'rel': 'stylesheet', 'type': 'text/css' })); @@ -668,32 +648,39 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. }, do_load_js: function(files) { var self = this; + var d = $.Deferred(); if(files.length != 0) { var file = files.shift(); var tag = document.createElement('script'); tag.type = 'text/javascript'; - tag.src = self.get_absolute_url(file); + tag.src = self.get_url(file); tag.onload = tag.onreadystatechange = function() { if ( (tag.readyState && tag.readyState != "loaded" && tag.readyState != "complete") || tag.onload_done ) return; tag.onload_done = true; - self.do_load_js(files, callback); + self.do_load_js(files).then(function () { + d.resolve(); + }); }; var head = document.head || document.getElementsByTagName('head')[0]; head.appendChild(tag); } else { self.on_modules_loaded(); + d.resolve(); } + return d; }, do_load_qweb: function(files) { var self = this; if (files.length != 0) { var file = files.shift(); - self.rpc('/web/proxy/load', {path: file}, function(xml) { + return self.rpc('/web/proxy/load', {path: file}).pipe(function(xml) { openerp.web.qweb.add_template(_.str.trim(xml)); - self.do_load_qweb(files, callback); + return self.do_load_qweb(files); }); - } + } else { + return $.when(); + } }, on_modules_loaded: function() { for(var j=0; j