diff --git a/addons/.bzrignore b/addons/.bzrignore
deleted file mode 100644
index 8c34871011766994d9efa304fb1e95991198d608..0000000000000000000000000000000000000000
--- a/addons/.bzrignore
+++ /dev/null
@@ -1,2 +0,0 @@
-.*
-**/node_modules
diff --git a/addons/sale/sale.py b/addons/sale/sale.py
index 45c32a33b22384af596855a83d939ad5dacaad80..397bc0deccc15a4f27d0b7e0ddf9d6d1cdc2726a 100644
--- a/addons/sale/sale.py
+++ b/addons/sale/sale.py
@@ -128,13 +128,12 @@ class sale_order(osv.osv):
         sale_clause = ''
         no_invoiced = False
         for arg in args:
-            if arg[1] == '=':
-                if arg[2]:
-                    clause += 'AND inv.state = \'paid\''
-                else:
-                    clause += 'AND inv.state != \'cancel\' AND sale.state != \'cancel\'  AND inv.state <> \'paid\'  AND rel.order_id = sale.id '
-                    sale_clause = ',  sale_order AS sale '
-                    no_invoiced = True
+            if (arg[1] == '=' and arg[2]) or (arg[1] == '!=' and not arg[2]):
+                clause += 'AND inv.state = \'paid\''
+            else:
+                clause += 'AND inv.state != \'cancel\' AND sale.state != \'cancel\'  AND inv.state <> \'paid\'  AND rel.order_id = sale.id '
+                sale_clause = ',  sale_order AS sale '
+                no_invoiced = True
 
         cursor.execute('SELECT rel.order_id ' \
                 'FROM sale_order_invoice_rel AS rel, account_invoice AS inv '+ sale_clause + \
diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css
index b4c0d3050bf68b50907c1491003cee4e9eee04c6..6a82696ac4b1d53a46e71ca4604faa8e66303344 100644
--- a/addons/web/static/src/css/base.css
+++ b/addons/web/static/src/css/base.css
@@ -2624,11 +2624,11 @@
 .openerp .oe_list_editable .oe_list_content td.oe_list_field_cell {
   padding: 4px 6px 3px;
 }
-.openerp .oe_list.oe_list_editable.oe_editing .oe_edition .oe_list_field_cell:not(.oe_readonly) {
+.openerp .oe_list.oe_list_editable.oe_editing .oe_edition .oe_list_field_cell {
   color: transparent;
   text-shadow: none;
 }
-.openerp .oe_list.oe_list_editable.oe_editing .oe_edition .oe_list_field_cell:not(.oe_readonly) * {
+.openerp .oe_list.oe_list_editable.oe_editing .oe_edition .oe_list_field_cell * {
   visibility: hidden;
 }
 .openerp .oe_list.oe_list_editable.oe_editing .oe_m2o_drop_down_button {
@@ -2644,6 +2644,13 @@
   min-width: 0;
   max-width: none;
 }
+.openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_list_field_handle {
+  color: transparent;
+}
+.openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_readonly {
+  padding: 4px 6px 3px;
+  text-align: left;
+}
 .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field input, .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field textarea {
   height: 27px;
   -moz-border-radius: 0;
@@ -2655,9 +2662,14 @@
 .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field input, .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field textarea, .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field select {
   min-width: 0;
 }
-.openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_form_field_float input, .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_form_view_integer input {
+.openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_form_field_float.oe_readonly, .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_form_view_integer.oe_readonly {
+  padding: 6px 0px 0px;
   text-align: right;
+  max-width: 100px;
+}
+.openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_form_field_float input, .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_form_view_integer input {
   width: 100% !important;
+  text-align: right;
 }
 .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_form_field_datetime input.oe_datepicker_master, .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_form_field_date input.oe_datepicker_master {
   width: 100% !important;
diff --git a/addons/web/static/src/css/base.sass b/addons/web/static/src/css/base.sass
index 136cdbdef24bfbeed2427738715fed0c8aa76a7e..69d338b637d23544ba4e69b8d9e69ed23df00bf1 100644
--- a/addons/web/static/src/css/base.sass
+++ b/addons/web/static/src/css/base.sass
@@ -2117,7 +2117,7 @@ $sheet-padding: 16px
     .oe_list_editable .oe_list_content td.oe_list_field_cell
         padding: 4px 6px 3px
     .oe_list.oe_list_editable.oe_editing
-        .oe_edition .oe_list_field_cell:not(.oe_readonly)
+        .oe_edition .oe_list_field_cell
             *
                 visibility: hidden
             color: transparent
@@ -2129,6 +2129,11 @@ $sheet-padding: 16px
         .oe_input_icon
             margin-top: 5px
         .oe_form_field
+            &.oe_list_field_handle
+                color: transparent
+            &.oe_readonly
+                padding: 4px 6px 3px
+                text-align: left
             min-width: 0
             max-width: none
             input, textarea
@@ -2139,9 +2144,13 @@ $sheet-padding: 16px
             input, textarea, select
                 min-width: 0
             &.oe_form_field_float,&.oe_form_view_integer
-                input
+                &.oe_readonly
+                    padding: 6px 0px 0px
                     text-align: right
+                    max-width: 100px
+                input
                     width: 100% !important
+                    text-align: right
             &.oe_form_field_datetime,&.oe_form_field_date
                 input.oe_datepicker_master
                     width: 100% !important
diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js
index c816d186fde91bdab5e27c450a49e317a4b9bc1b..1c75f341436773003f02f58edab46e9d2a2e482b 100644
--- a/addons/web/static/src/js/view_form.js
+++ b/addons/web/static/src/js/view_form.js
@@ -2810,7 +2810,9 @@ instance.web.form.FieldDatetime = instance.web.form.AbstractField.extend(instanc
     },
     set_dimensions: function (height, width) {
         this._super(height, width);
-        this.datewidget.$input.css('height', height);
+        if (!this.get("effective_readonly")) {
+            this.datewidget.$input.css('height', height);
+        }
     }
 });
 
@@ -3510,6 +3512,7 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
         this.floating = false;
         this.current_display = null;
         this.is_started = false;
+        this.ignore_focusout = false;
     },
     reinit_value: function(val) {
         this.internal_set_value(val);
@@ -3641,6 +3644,7 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
         var ed_delay = 200;
         var ed_duration = 15000;
         var anyoneLoosesFocus = function (e) {
+            if (self.ignore_focusout) { return; }
             var used = false;
             if (self.floating) {
                 if (self.last_search.length > 0) {
@@ -3844,11 +3848,17 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
     _search_create_popup: function() {
         this.no_ed = true;
         this.ed_def.reject();
-        return instance.web.form.CompletionFieldMixin._search_create_popup.apply(this, arguments);
+        this.ignore_focusout = true;
+        this.reinit_value(false);
+        var res = instance.web.form.CompletionFieldMixin._search_create_popup.apply(this, arguments);
+        this.ignore_focusout = false;
+        this.no_ed = false;
+        return res;
     },
     set_dimensions: function (height, width) {
         this._super(height, width);
-        this.$input.css('height', height);
+        if (!this.get("effective_readonly") && this.$input)
+            this.$input.css('height', height);
     }
 });
 
diff --git a/addons/web/static/src/js/view_list_editable.js b/addons/web/static/src/js/view_list_editable.js
index ea2c28d9c3f924a5b8e5ac1ac4a9f727d5ff93aa..144de8eb21c914c2239309f593cdcdedc1f29443 100644
--- a/addons/web/static/src/js/view_list_editable.js
+++ b/addons/web/static/src/js/view_list_editable.js
@@ -285,9 +285,7 @@
             if (!this.editor.is_editing()) { return; }
             for(var i=0, len=this.fields_for_resize.length; i<len; ++i) {
                 var item = this.fields_for_resize[i];
-                if (!item.field.get('effective_invisible')) {
-                    this.resize_field(item.field, item.cell);
-                }
+                this.resize_field(item.field, item.cell);
             }
         },
         /**
@@ -306,6 +304,11 @@
                 at: 'left top',
                 of: $cell
             });
+            if (field.get('effective_readonly')) {
+                field.$el.addClass('oe_readonly');
+            }
+            if(field.widget == "handle")
+                field.$el.addClass('oe_list_field_handle');
         },
         /**
          * @return {jQuery.Deferred}
@@ -451,13 +454,7 @@
         setup_events: function () {
             var self = this;
             _.each(this.editor.form.fields, function(field, field_name) {
-                var set_invisible = function() {
-                    field.set({'force_invisible': field.get('effective_readonly')});
-                };
-                field.on("change:effective_readonly", self, set_invisible);
-                set_invisible();
-                field.on('change:effective_invisible', self, function () {
-                    if (field.get('effective_invisible')) { return; }
+                field.on("change:effective_readonly", self, function(){
                     var item = _(self.fields_for_resize).find(function (item) {
                         return item.field === field;
                     });
diff --git a/openerp/addons/base/ir/ir_http.py b/openerp/addons/base/ir/ir_http.py
index ac3091e33b954de26e23761c34d01831ce83ea3d..21c8b7ef94181f773b3666be4c6d817040ade131 100644
--- a/openerp/addons/base/ir/ir_http.py
+++ b/openerp/addons/base/ir/ir_http.py
@@ -76,17 +76,23 @@ class ir_http(osv.AbstractModel):
             request.uid = request.session.uid
 
     def _authenticate(self, auth_method='user'):
-        if request.session.uid:
-            try:
-                request.session.check_security()
-                # what if error in security.check()
-                #   -> res_users.check()
-                #   -> res_users.check_credentials()
-            except (openerp.exceptions.AccessDenied, openerp.http.SessionExpiredException):
-                # All other exceptions mean undetermined status (e.g. connection pool full),
-                # let them bubble up
-                request.session.logout()
-        getattr(self, "_auth_method_%s" % auth_method)()
+        try:
+            if request.session.uid:
+                try:
+                    request.session.check_security()
+                    # what if error in security.check()
+                    #   -> res_users.check()
+                    #   -> res_users.check_credentials()
+                except (openerp.exceptions.AccessDenied, openerp.http.SessionExpiredException):
+                    # All other exceptions mean undetermined status (e.g. connection pool full),
+                    # let them bubble up
+                    request.session.logout()
+            getattr(self, "_auth_method_%s" % auth_method)()
+        except (openerp.exceptions.AccessDenied, openerp.http.SessionExpiredException):
+            raise
+        except Exception:
+            _logger.exception("Exception during request Authentication.")
+            raise openerp.exceptions.AccessDenied()
         return auth_method
 
     def _handle_exception(self, exception):
diff --git a/openerp/addons/base/module/module.py b/openerp/addons/base/module/module.py
index eb154d4a05fb237fc2450ec3c614a33fa35d05e8..df673f95b32d8472b3a4e4d47c536a0470776e92 100644
--- a/openerp/addons/base/module/module.py
+++ b/openerp/addons/base/module/module.py
@@ -496,6 +496,7 @@ class module(osv.osv):
             'params': {'menu_id': menu_ids and menu_ids[0] or False}
         }
 
+    #TODO remove me in master, not called anymore
     def button_immediate_uninstall(self, cr, uid, ids, context=None):
         """
         Uninstall the selected module(s) immediately and fully,
diff --git a/openerp/addons/base/module/module_view.xml b/openerp/addons/base/module/module_view.xml
index 110b607fd4e73b1feb5a351b1e51143978bbfa79..9077a1f86db93c4fdf7fc9c929a7cc3ea49cfa22 100644
--- a/openerp/addons/base/module/module_view.xml
+++ b/openerp/addons/base/module/module_view.xml
@@ -82,8 +82,7 @@
                         <div>
                             <button name="button_immediate_install" states="uninstalled" string="Install" type="object" class="oe_highlight"/>
                             <button name="button_immediate_upgrade" states="installed" string="Upgrade" type="object" class="oe_highlight"/>
-                            <button name="button_immediate_uninstall" states="installed" string="Uninstall" type="object"
-                                confirm="Do you confirm the uninstallation of this module? This will permanently erase all data currently stored by the module!"/>
+                        <button name="button_uninstall" states="installed" string="Uninstall" type="object"/>
                             <button name="button_uninstall_cancel" states="to remove" string="Cancel Uninstall" type="object"/>
                             <button name="button_upgrade_cancel" states="to upgrade" string="Cancel Upgrade" type="object"/>
                             <button name="button_install_cancel" states="to install" string="Cancel Install" type="object"/>
diff --git a/openerp/addons/base/module/wizard/base_module_upgrade.py b/openerp/addons/base/module/wizard/base_module_upgrade.py
index c75058ab8350c13f462b105c8086f15ffcccab3c..365895be7acae460f043cab71a4a6d88cab899bf 100644
--- a/openerp/addons/base/module/wizard/base_module_upgrade.py
+++ b/openerp/addons/base/module/wizard/base_module_upgrade.py
@@ -68,6 +68,20 @@ class base_module_upgrade(osv.osv_memory):
         res = mod_obj.read(cr, uid, ids, ['name','state'], context)
         return {'module_info': '\n'.join(map(lambda x: x['name']+' : '+x['state'], res))}
 
+    def upgrade_module_cancel(self, cr, uid, ids, context=None):
+        mod_obj = self.pool.get('ir.module.module')
+        to_installed_ids = mod_obj.search(cr, uid, [
+            ('state', 'in', ['to upgrade', 'to remove'])])
+        if to_installed_ids:
+            mod_obj.write(cr, uid, to_installed_ids, {'state': 'installed'}, context=context)
+
+        to_uninstalled_ids = mod_obj.search(cr, uid, [
+            ('state', '=', 'to install')])
+        if to_uninstalled_ids:
+            mod_obj.write(cr, uid, to_uninstalled_ids, {'state': 'uninstalled'}, context=context)
+
+        return {'type': 'ir.actions.act_window_close'}
+
     def upgrade_module(self, cr, uid, ids, context=None):
         ir_module = self.pool.get('ir.module.module')
 
diff --git a/openerp/addons/base/module/wizard/base_module_upgrade_view.xml b/openerp/addons/base/module/wizard/base_module_upgrade_view.xml
index 1a1225befcb78ea5761487918ac6a751b5a9581e..10c023e51482e3713a321b6907761bfbb66c9921 100644
--- a/openerp/addons/base/module/wizard/base_module_upgrade_view.xml
+++ b/openerp/addons/base/module/wizard/base_module_upgrade_view.xml
@@ -7,14 +7,15 @@
             <field name="model">base.module.upgrade</field>
             <field name="arch" type="xml">
                 <form string="System Update" version="7.0">
-                    <div><label string="Your system will be updated."/></div>
-                    <div><label string="Note that this operation might take a few minutes."/></div>
-                    <separator string="Modules to Update"/>
+                    <p>This module will trigger the uninstallation of below modules.</p>
+                    <p><strong>This operation will permanently erase all data currently stored by the modules!</strong></p>
+                    <p>If you wish to cancel the process, press the cancel button below</p>
+                    <separator string="Impacted Modules"/>
                     <field name="module_info"/>
                     <footer>
                         <button name="upgrade_module" string="Update" type="object" class="oe_highlight"/>
                         or
-                        <button string="Cancel" class="oe_link" special="cancel"/>
+                        <button string="Cancel" class="oe_link" name="upgrade_module_cancel" type="object"/>
                     </footer>
                 </form>
             </field>
diff --git a/openerp/addons/base/res/res_config.py b/openerp/addons/base/res/res_config.py
index 5bbd377f29dc736d3e81584670df883ed4c79866..06453526ebcba285dd10af5aadc9994b7efc38c1 100644
--- a/openerp/addons/base/res/res_config.py
+++ b/openerp/addons/base/res/res_config.py
@@ -28,6 +28,7 @@ from openerp.osv import osv, fields
 from openerp.tools import ustr
 from openerp.tools.translate import _
 from openerp import exceptions
+from lxml import etree
 
 _logger = logging.getLogger(__name__)
 
@@ -434,6 +435,43 @@ class res_config_settings(osv.osv_memory, res_config_module_installation_mixin):
     def copy(self, cr, uid, id, values, context=None):
         raise osv.except_osv(_("Cannot duplicate configuration!"), "")
 
+    def fields_view_get(self, cr, user, view_id=None, view_type='form',
+                        context=None, toolbar=False, submenu=False):
+        ret_val = super(res_config_settings, self).fields_view_get(
+            cr, user, view_id=view_id, view_type=view_type, context=context,
+            toolbar=toolbar, submenu=submenu)
+
+        doc = etree.XML(ret_val['arch'])
+
+        for field in ret_val['fields']:
+            if not field.startswith("module_"):
+                continue
+            for node in doc.xpath("//field[@name='%s']" % field):
+                if 'on_change' not in node.attrib:
+                    node.set("on_change",
+                    "onchange_module(%s, '%s')" % (field, field))
+
+        ret_val['arch'] = etree.tostring(doc)
+        return ret_val
+
+    def onchange_module(self, cr, uid, ids, field_value, module_name, context={}):
+        module_pool = self.pool.get('ir.module.module')
+        module_ids = module_pool.search(
+            cr, uid, [('name', '=', module_name.replace("module_", '')),
+            ('state','in', ['to install', 'installed', 'to upgrade'])],
+            context=context)
+
+        if module_ids and not field_value:
+            dep_ids = module_pool.downstream_dependencies(cr, uid, module_ids, context=context)
+            dep_name = [x.shortdesc for x  in module_pool.browse(
+                cr, uid, dep_ids + module_ids, context=context)]
+            message = '\n'.join(dep_name)
+            return {'warning': {'title': _('Warning!'),
+                    'message':
+                    _('Disabling this option will also uninstall the following modules \n%s' % message)
+                   }}
+        return {}
+
     def _get_classified_fields(self, cr, uid, context=None):
         """ return a dictionary with the fields classified by category::
 
diff --git a/openerp/http.py b/openerp/http.py
index abee8ac2b3d70ab815d3ffbfa7dc32a02b0f5f98..ceddf234c1cba8fc3530bee4bc5796b7dee423ff 100644
--- a/openerp/http.py
+++ b/openerp/http.py
@@ -270,8 +270,6 @@ class WebRequest(object):
            to abitrary responses. Anything returned (except None) will
            be used as response.""" 
         self._failed = exception # prevent tx commit
-        if isinstance(exception, werkzeug.exceptions.HTTPException):
-            return exception
         raise
 
     def _call_function(self, *args, **kwargs):
@@ -538,6 +536,15 @@ class HttpRequest(WebRequest):
         params.pop('session_id', None)
         self.params = params
 
+    def _handle_exception(self, exception):
+        """Called within an except block to allow converting exceptions
+           to abitrary responses. Anything returned (except None) will
+           be used as response."""
+        try:
+            return super(HttpRequest, self)._handle_exception(exception)
+        except werkzeug.exceptions.HTTPException, e:
+            return e
+
     def dispatch(self):
         if request.httprequest.method == 'OPTIONS' and request.endpoint and request.endpoint.routing.get('cors'):
             headers = {
diff --git a/openerp/service/server.py b/openerp/service/server.py
index 72e130edf8b6a8e17985f49c88a86f6ecad285f2..c0dc15caab7af8004ca3888a425a6626ddbc9c40 100644
--- a/openerp/service/server.py
+++ b/openerp/service/server.py
@@ -46,8 +46,15 @@ SLEEP_INTERVAL = 60     # 1 min
 #----------------------------------------------------------
 # Werkzeug WSGI servers patched
 #----------------------------------------------------------
+class LoggingBaseWSGIServerMixIn(object):
+    def handle_error(self, request, client_address):
+        t, e, _ = sys.exc_info()
+        if t == socket.error and e.errno == errno.EPIPE:
+            # broken pipe, ignore error
+            return
+        _logger.exception('Exception happened during processing of request from %s', client_address)
 
-class BaseWSGIServerNoBind(werkzeug.serving.BaseWSGIServer):
+class BaseWSGIServerNoBind(LoggingBaseWSGIServerMixIn, werkzeug.serving.BaseWSGIServer):
     """ werkzeug Base WSGI Server patched to skip socket binding. PreforkServer
     use this class, sets the socket and calls the process_request() manually
     """
@@ -74,7 +81,7 @@ class RequestHandler(werkzeug.serving.WSGIRequestHandler):
 # should also work with systemd socket activation. This is currently untested
 # and not yet used.
 
-class ThreadedWSGIServerReloadable(werkzeug.serving.ThreadedWSGIServer):
+class ThreadedWSGIServerReloadable(LoggingBaseWSGIServerMixIn, werkzeug.serving.ThreadedWSGIServer):
     """ werkzeug Threaded WSGI Server patched to allow reusing a listen socket
     given by the environement, this is used by autoreload to keep the listen
     socket open when a reload happens.