diff --git a/addons/web_editor/static/src/js/editor/image_processing.js b/addons/web_editor/static/src/js/editor/image_processing.js
index 1308c23b0e0..ee52f6ad31f 100644
--- a/addons/web_editor/static/src/js/editor/image_processing.js
+++ b/addons/web_editor/static/src/js/editor/image_processing.js
@@ -233,6 +233,8 @@ export async function applyModifications(img, dataOptions = {}) {
// Crop
const container = document.createElement('div');
const original = await loadImage(originalSrc);
+ // loadImage may have ended up loading a different src (see: LOAD_IMAGE_404)
+ originalSrc = original.getAttribute('src');
container.appendChild(original);
await activateCropper(original, 0, data);
let croppedImg = $(original).cropper('getCroppedCanvas', {width, height});
@@ -358,6 +360,7 @@ export function loadImage(src, img = new Image()) {
img.src = source;
};
// The server will return a placeholder image with the following src.
+ // grep: LOAD_IMAGE_404
const placeholderHref = "/web/image/__odoo__unknown__src__/";
return new Promise((resolve, reject) => {
@@ -419,6 +422,8 @@ async function _updateImageData(src, key = 'objectURL') {
}
/**
* Returns the size of a cached image.
+ * Warning: this supposes that the image is already in the cache, i.e. that
+ * _updateImageData was called before.
*
* @param {String} src used as a key on the image cache map.
* @returns {Number} size of the image in bytes.
diff --git a/addons/website/static/tests/tours/drop_404_ir_attachment_url.js b/addons/website/static/tests/tours/drop_404_ir_attachment_url.js
new file mode 100644
index 00000000000..3906ac20d7c
--- /dev/null
+++ b/addons/website/static/tests/tours/drop_404_ir_attachment_url.js
@@ -0,0 +1,44 @@
+/** @odoo-module **/
+
+import wTourUtils from '@website/js/tours/tour_utils';
+
+wTourUtils.registerWebsitePreviewTour('drop_404_ir_attachment_url', {
+ test: true,
+ url: '/',
+ edition: true,
+}, () => [
+ wTourUtils.dragNDrop({
+ id: 's_404_snippet',
+ name: '404 Snippet',
+ }),
+ {
+ content: 'Click on the snippet image',
+ trigger: 'iframe .s_404_snippet img',
+ }, {
+ content: 'Once the image UI appears, check the image has no size (404)',
+ trigger: 'iframe .s_404_snippet img',
+ extra_trigger: '.snippet-option-ReplaceMedia',
+ run: function () {
+ const imgEl = this.$anchor[0];
+ if (!imgEl.complete
+ || imgEl.naturalWidth !== 0
+ || imgEl.naturalHeight !== 0) {
+ console.error('This is supposed to be a 404 image');
+ }
+ },
+ },
+ wTourUtils.changeOption('ImageTools', 'we-select[data-name="shape_img_opt"] we-toggler'),
+ wTourUtils.changeOption('ImageTools', 'we-button[data-set-img-shape]'),
+ {
+ content: 'Once the shape is applied, check the image has now a size (placeholder image)',
+ trigger: 'iframe .s_404_snippet img[src^="data:"]',
+ run: function () {
+ const imgEl = this.$anchor[0];
+ if (!imgEl.complete
+ || imgEl.naturalWidth === 0
+ || imgEl.naturalHeight === 0) {
+ console.error('Even though the original image was a 404, the option should have been applied on the placeholder image');
+ }
+ },
+ },
+]);
diff --git a/addons/website/tests/test_ui.py b/addons/website/tests/test_ui.py
index 92ef59e4edf..fd967304945 100644
--- a/addons/website/tests/test_ui.py
+++ b/addons/website/tests/test_ui.py
@@ -515,3 +515,40 @@ class TestUi(odoo.tests.HttpCase):
'path': 'website/static/tests/tour_utils/widget_lifecycle_patch_wysiwyg.js',
})
self.start_tour(self.env['website'].get_client_action_url('/'), 'widget_lifecycle', login='admin')
+
+ def test_drop_404_ir_attachment_url(self):
+ website_snippets = self.env.ref('website.snippets')
+ self.env['ir.ui.view'].create([{
+ 'name': '404 Snippet',
+ 'type': 'qweb',
+ 'key': 'website.s_404_snippet',
+ 'arch': """
+
+
+

+
+
+ """,
+ }, {
+ 'type': 'qweb',
+ 'inherit_id': website_snippets.id,
+ 'arch': """
+
+
+
+ """,
+ }])
+ attachment = self.env['ir.attachment'].create({
+ 'name': '404_ir_attachment',
+ 'type': 'url',
+ 'url': '/web/static/__some__typo__.png',
+ 'mimetype': 'image/png',
+ })
+ self.env['ir.model.data'].create({
+ 'name': '404_ir_attachment',
+ 'module': 'website',
+ 'model': 'ir.attachment',
+ 'res_id': attachment.id,
+ })
+ self.start_tour(self.env['website'].get_client_action_url('/'), 'drop_404_ir_attachment_url', login='admin')