From 8a888bca8ac172d1c39ba53e6da97012a1588429 Mon Sep 17 00:00:00 2001 From: Samuel Degueldre Date: Thu, 10 Jun 2021 05:52:34 +0000 Subject: [PATCH] [REF] web: move crash manager to frontend only Previously, we removed the crash manager and moved its responsibilities to the error service. Because the crash manager was used in both the frontend and backend, and because the infrastructure code required to use the error service in the frontend hasn't been written yet, the crash manager has been moved to the frontend assets where it is still needed in the interim. Most of the logic of the crash manager has been moved to public_crash_manager (as it is now the only crash manager and it doesn't make sense to keep the inheritance hierarchy). References to the crash manager in the backend were adapted where needed or removed where they were no longer useful. closes odoo-dev/odoo#943 Related: odoo-dev/enterprise#174 Signed-off-by: Aaron Bohy (aab) --- addons/point_of_sale/__manifest__.py | 1 - .../static/tests/unit/helpers/test_main.js | 23 - addons/web/__manifest__.py | 3 - .../static/src/core/network/rpc_service.js | 2 +- .../public_crash_manager.js | 398 +++++++++++++++++ .../public_crash_manager.xml} | 0 .../crash_manager_warning_dialog.js | 30 ++ addons/web/static/src/legacy/js/core/misc.js | 4 - .../src/legacy/js/fields/basic_fields.js | 1 - .../legacy/js/public/public_crash_manager.js | 31 -- .../src/legacy/js/services/crash_manager.js | 421 ------------------ addons/web/static/src/legacy/legacy_setup.js | 4 +- addons/web/static/src/legacy/utils.js | 24 +- addons/web/static/src/legacy/xml/dialog.xml | 3 + addons/web/static/tests/helpers/legacy.js | 2 - .../static/tests/legacy/helpers/test_utils.js | 1 - 16 files changed, 458 insertions(+), 490 deletions(-) delete mode 100644 addons/point_of_sale/static/tests/unit/helpers/test_main.js create mode 100644 addons/web/static/src/legacy/frontend/public_crash_manager/public_crash_manager.js rename addons/web/static/src/legacy/{xml/crash_manager.xml => frontend/public_crash_manager/public_crash_manager.xml} (100%) create mode 100644 addons/web/static/src/legacy/js/_deprecated/crash_manager_warning_dialog.js delete mode 100644 addons/web/static/src/legacy/js/public/public_crash_manager.js delete mode 100644 addons/web/static/src/legacy/js/services/crash_manager.js diff --git a/addons/point_of_sale/__manifest__.py b/addons/point_of_sale/__manifest__.py index 7e7c9a77086..7bf4d9127bd 100644 --- a/addons/point_of_sale/__manifest__.py +++ b/addons/point_of_sale/__manifest__.py @@ -194,7 +194,6 @@ 'point_of_sale.qunit_suite_tests': [ 'web/static/tests/legacy/component_extension_tests.js', 'point_of_sale/static/tests/unit/**/*', - ('remove', 'point_of_sale/static/tests/unit/helpers/test_main.js') ], 'point_of_sale.assets_backend_prod_only': [ 'point_of_sale/static/src/js/chrome_adapter.js', diff --git a/addons/point_of_sale/static/tests/unit/helpers/test_main.js b/addons/point_of_sale/static/tests/unit/helpers/test_main.js deleted file mode 100644 index f42e01cbd6e..00000000000 --- a/addons/point_of_sale/static/tests/unit/helpers/test_main.js +++ /dev/null @@ -1,23 +0,0 @@ -odoo.define('web.web_client', function (require) { - // this module is required by the test - const { bus } = require('web.core'); - const WebClient = require('web.AbstractWebClient'); - - // listen to unhandled rejected promises, and when the rejection is not due - // to a crash, prevent the browser from displaying an 'unhandledrejection' - // error in the console, which would make tests crash on each Promise.reject() - // something similar is done by the CrashManagerService, but by default, it - // isn't deployed in tests - bus.on('crash_manager_unhandledrejection', this, function (ev) { - if (!ev.reason || !(ev.reason instanceof Error)) { - ev.stopPropagation(); - ev.stopImmediatePropagation(); - ev.preventDefault(); - } - }); - - owl.config.mode = "dev"; - - const webClient = new WebClient(); - return webClient; -}); diff --git a/addons/web/__manifest__.py b/addons/web/__manifest__.py index e596e50b492..62305f57316 100644 --- a/addons/web/__manifest__.py +++ b/addons/web/__manifest__.py @@ -204,7 +204,6 @@ This module provides the core of the Odoo Web Client. 'web/static/src/legacy/js/services/session.js', 'web/static/src/legacy/js/public/public_env.js', - 'web/static/src/legacy/js/public/public_crash_manager.js', 'web/static/src/legacy/js/public/public_root.js', 'web/static/src/legacy/js/public/public_root_instance.js', 'web/static/src/legacy/js/public/public_widget.js', @@ -396,7 +395,6 @@ This module provides the core of the Odoo Web Client. 'web/static/src/legacy/js/services/config.js', 'web/static/src/legacy/js/services/core.js', 'web/static/src/legacy/js/services/local_storage_service.js', - 'web/static/src/legacy/js/services/crash_manager.js', 'web/static/src/legacy/js/core/error_utils.js', 'web/static/src/legacy/js/services/session_storage_service.js', 'web/static/src/legacy/js/common_env.js', @@ -408,7 +406,6 @@ This module provides the core of the Odoo Web Client. # Used during the transition of the web architecture 'web.frontend_legacy': [ - # Old rainbow man kept for website compatibility 'web/static/src/legacy/frontend/**/*', ], diff --git a/addons/web/static/src/core/network/rpc_service.js b/addons/web/static/src/core/network/rpc_service.js index 0bf6056a51c..e2261754650 100644 --- a/addons/web/static/src/core/network/rpc_service.js +++ b/addons/web/static/src/core/network/rpc_service.js @@ -25,7 +25,7 @@ export class ConnectionAbortedError extends Error {} // ----------------------------------------------------------------------------- // Main RPC method // ----------------------------------------------------------------------------- -function makeErrorFromResponse(reponse) { +export function makeErrorFromResponse(reponse) { // Odoo returns error like this, in a error field instead of properly // using http error codes... const { code, data: errorData, message, type: subType } = reponse; diff --git a/addons/web/static/src/legacy/frontend/public_crash_manager/public_crash_manager.js b/addons/web/static/src/legacy/frontend/public_crash_manager/public_crash_manager.js new file mode 100644 index 00000000000..a9942498278 --- /dev/null +++ b/addons/web/static/src/legacy/frontend/public_crash_manager/public_crash_manager.js @@ -0,0 +1,398 @@ +odoo.define('web.CrashManager', function (require) { + "use strict"; + + const AbstractService = require('web.AbstractService'); + var ajax = require('web.ajax'); + var core = require('web.core'); + var Dialog = require('web.Dialog'); + var Widget = require('web.Widget'); + var config = require('web.config'); + var { formatTraceback, annotateTraceback } = require("@web/legacy/js/core/error_utils"); + + var _t = core._t; + var _lt = core._lt; + + // Register this eventlistener before qunit does. + // Some errors needs to be negated by the crash_manager. + window.addEventListener('unhandledrejection', ev => + core.bus.trigger('crash_manager_unhandledrejection', ev) + ); + + let active = true; + + /** + * An extension of Dialog Widget to render the warnings and errors on the website. + * Extend it with your template of choice like ErrorDialog/WarningDialog + */ + var CrashManagerDialog = Dialog.extend({ + xmlDependencies: (Dialog.prototype.xmlDependencies || []).concat( + ['/web/static/src/legacy/frontend/public_crash_manager/public_crash_manager.xml'] + ), + + /** + * @param {Object} error + * @param {string} error.message the message in Warning/Error Dialog + * @param {string} error.traceback the traceback in ErrorDialog + * + * @constructor + */ + init: function (parent, options, error) { + this._super.apply(this, [parent, options]); + this.error = error; + this.message = error.message; + this.traceback = error.traceback; + core.bus.off('close_dialogs', this); + }, + + willStart: async function () { + await this._super() + const jsError = this.error.data && this.error.data.jsError; + if (jsError) { + if (config.isDebug('assets')) { + this.traceback = await annotateTraceback(jsError); + } else { + this.traceback = formatTraceback(jsError); + } + } + }, + + start: async function () { + await this._super(); + const message = this.message; + const traceback = this.traceback; + + if (!traceback) { + return; + } + this.$(".o_error_detail").on("shown.bs.collapse", function (e) { + e.target.scrollTop = e.target.scrollHeight; + }); + + const $clipboardBtn = this.$(".o_clipboard_button"); + $clipboardBtn.tooltip({title: _t("Copied !"), trigger: "manual", placement: "left"}); + this.clipboard = new window.ClipboardJS($clipboardBtn[0], { + text: function () { + return (_t("Error") + ":\n" + message + "\n\n" + traceback).trim(); + }, + // Container added because of Bootstrap modal that give the focus to another element. + // We need to give to correct focus to ClipboardJS (see in ClipboardJS doc) + // https://github.com/zenorocha/clipboard.js/issues/155 + container: this.el, + }); + this.clipboard.on("success", function (e) { + _.defer(function () { + $clipboardBtn.tooltip("show"); + _.delay(function () { + $clipboardBtn.tooltip("hide"); + }, 800); + }); + }); + }, + destroy() { + if (this.clipboard) { + this.$(".o_clipboard_button").tooltip('dispose'); + this.clipboard.destroy(); + } + this._super(); + } + }); + + var ErrorDialog = CrashManagerDialog.extend({ + template: 'CrashManager.error', + }); + + var WarningDialog = CrashManagerDialog.extend({ + template: 'CrashManager.warning', + + /** + * Sets size to medium by default. + * + * @override + */ + init: function (parent, options, error) { + this._super(parent, _.extend({ + size: 'medium', + }, options), error); + }, + + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + /** + * Focuses the ok button. + * + * @override + */ + open: function () { + this._super({shouldFocusButtons: true}); + }, + }); + + var CrashManager = AbstractService.extend({ + init: function () { + var self = this; + active = true; + this.isConnected = true; + this.odooExceptionTitleMap = { + 'odoo.addons.base.models.ir_mail_server.MailDeliveryException': _lt("MailDeliveryException"), + 'odoo.exceptions.AccessDenied': _lt("Access Denied"), + 'odoo.exceptions.AccessError': _lt("Access Error"), + 'odoo.exceptions.MissingError': _lt("Missing Record"), + 'odoo.exceptions.UserError': _lt("User Error"), + 'odoo.exceptions.ValidationError': _lt("Validation Error"), + 'odoo.exceptions.Warning': _lt("Warning"), + }; + + this._super.apply(this, arguments); + + // crash manager integration + core.bus.on('rpc_error', this, this.rpc_error); + window.onerror = function (message, file, line, col, error) { + // Scripts injected in DOM (eg: google API's js files) won't return a clean error on window.onerror. + // The browser will just give you a 'Script error.' as message and nothing else for security issue. + // To enable onerror to work properly with CORS file, you should: + // 1. add crossorigin="anonymous" to your