Add warning at submission for listed MV3 uploads (#19893)
* Add warning at submission for listed MV3 uploads
This commit is contained in:
Родитель
d04c031646
Коммит
94a1caf110
|
@ -2,11 +2,14 @@ import waffle
|
|||
|
||||
from django.utils.translation import gettext
|
||||
|
||||
from olympia import amo
|
||||
from olympia.amo.urlresolvers import linkify_and_clean
|
||||
from olympia.versions.models import DeniedInstallOrigin
|
||||
|
||||
|
||||
def insert_validation_message(
|
||||
results,
|
||||
*,
|
||||
type_='error',
|
||||
message='',
|
||||
msg_id='',
|
||||
|
@ -26,6 +29,11 @@ def insert_validation_message(
|
|||
'message': message,
|
||||
'description': description,
|
||||
'compatibility_type': compatibility_type,
|
||||
# Indicate that it's an extra message not coming from the linter:
|
||||
# our JavaScript has some logic to display a checklist if there are
|
||||
# linter warnings, so we want these custom messages we're inserting
|
||||
# to be excluded from that.
|
||||
'extra': True,
|
||||
},
|
||||
)
|
||||
# Need to increment 'errors' or 'warnings' count, so add an extra 's' after
|
||||
|
@ -69,7 +77,7 @@ def annotate_search_plugin_restriction(results, file_path, channel):
|
|||
)
|
||||
|
||||
|
||||
def annotate_validation_results(results, parsed_data):
|
||||
def annotate_validation_results(*, results, parsed_data, channel):
|
||||
"""Annotate validation results with potential add-on restrictions like
|
||||
denied origins."""
|
||||
if waffle.switch_is_active('record-install-origins'):
|
||||
|
@ -84,4 +92,57 @@ def annotate_validation_results(results, parsed_data):
|
|||
origin=origin
|
||||
),
|
||||
)
|
||||
add_manifest_version_messages(results=results, channel=channel)
|
||||
return results
|
||||
|
||||
|
||||
def add_manifest_version_messages(*, results, channel):
|
||||
mv = results.get('metadata', {}).get('manifestVersion')
|
||||
if mv != 3:
|
||||
return
|
||||
if 'messages' not in results:
|
||||
results['messages'] = []
|
||||
enable_mv3_submissions = waffle.switch_is_active('enable-mv3-submissions')
|
||||
if not enable_mv3_submissions:
|
||||
msg = gettext(
|
||||
'Manifest V3 is currently not supported for upload. '
|
||||
'{start_href}Read more about the support timeline{end_href}.'
|
||||
)
|
||||
url = 'https://blog.mozilla.org/addons/2021/05/27/manifest-v3-update/'
|
||||
start_href = f'<a href="{url}" target="_blank" rel="noopener">'
|
||||
|
||||
new_error_message = msg.format(start_href=start_href, end_href='</a>')
|
||||
for index, message in enumerate(results['messages']):
|
||||
if message.get('instancePath') == '/manifest_version':
|
||||
# if we find the linter manifest_version=3 warning, replace it
|
||||
results['messages'][index]['message'] = new_error_message
|
||||
break
|
||||
else:
|
||||
# otherwise insert a new error at the start of the errors
|
||||
insert_validation_message(
|
||||
results, message=new_error_message, msg_id='mv3_not_supported_yet'
|
||||
)
|
||||
elif channel == amo.CHANNEL_LISTED:
|
||||
# If submitting a listed upload and mv3 switch is on, we want to warn
|
||||
# about using unlisted instead for now.
|
||||
insert_validation_message(
|
||||
results,
|
||||
type_='warning',
|
||||
message=gettext('Manifest V3 compatibility warning'),
|
||||
description=[
|
||||
gettext(
|
||||
'Firefox is adding support for manifest version 3 (MV3) extensions '
|
||||
'in Firefox {version}, however, older versions of Firefox are only '
|
||||
'compatible with manifest version 2 (MV2) extensions. We recommend '
|
||||
'uploading Manifest V3 extensions as self-hosted for now to not '
|
||||
'break compatibility for your users.'
|
||||
).format(version=amo.DEFAULT_WEBEXT_MIN_VERSION_MV3_FIREFOX),
|
||||
linkify_and_clean(
|
||||
gettext(
|
||||
'For more information about the MV3 extension roll-out or '
|
||||
'self-hosting MV3 extensions, visit https://mzl.la/3hIwQXX'
|
||||
)
|
||||
),
|
||||
],
|
||||
msg_id='_MV3_COMPATIBILITY',
|
||||
)
|
||||
|
|
|
@ -255,7 +255,9 @@ def validate_file_path(path, channel):
|
|||
|
||||
log.info('Running linter on %s', path)
|
||||
results = run_addons_linter(path, channel=channel)
|
||||
annotations.annotate_validation_results(results, parsed_data)
|
||||
annotations.annotate_validation_results(
|
||||
results=results, parsed_data=parsed_data, channel=channel
|
||||
)
|
||||
return json.dumps(results)
|
||||
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ from copy import deepcopy
|
|||
|
||||
from waffle.testutils import override_switch
|
||||
|
||||
from olympia import amo
|
||||
from olympia.amo.tests import TestCase
|
||||
from olympia.constants.base import VALIDATOR_SKELETON_RESULTS
|
||||
from olympia.devhub.file_validation_annotations import annotate_validation_results
|
||||
|
@ -15,7 +16,9 @@ class TestDeniedOrigins(TestCase):
|
|||
DeniedInstallOrigin.objects.create(hostname_pattern='foo.com')
|
||||
results = deepcopy(VALIDATOR_SKELETON_RESULTS)
|
||||
data = {'install_origins': ['https://foo.com']}
|
||||
return_value = annotate_validation_results(results, data)
|
||||
return_value = annotate_validation_results(
|
||||
results=results, parsed_data=data, channel=amo.CHANNEL_UNLISTED
|
||||
)
|
||||
assert return_value == results
|
||||
assert results['errors'] == 0
|
||||
assert len(results['messages']) == 0
|
||||
|
@ -24,7 +27,9 @@ class TestDeniedOrigins(TestCase):
|
|||
DeniedInstallOrigin.objects.create(hostname_pattern='foo.com')
|
||||
results = deepcopy(VALIDATOR_SKELETON_RESULTS)
|
||||
data = {'install_origins': ['https://bar.com']}
|
||||
return_value = annotate_validation_results(results, data)
|
||||
return_value = annotate_validation_results(
|
||||
results=results, parsed_data=data, channel=amo.CHANNEL_UNLISTED
|
||||
)
|
||||
assert return_value == results
|
||||
assert results['errors'] == 0
|
||||
assert len(results['messages']) == 0
|
||||
|
@ -33,7 +38,9 @@ class TestDeniedOrigins(TestCase):
|
|||
DeniedInstallOrigin.objects.create(hostname_pattern='foo.com')
|
||||
results = deepcopy(VALIDATOR_SKELETON_RESULTS)
|
||||
data = {'install_origins': ['https://bar.com', 'https://example.com']}
|
||||
return_value = annotate_validation_results(results, data)
|
||||
return_value = annotate_validation_results(
|
||||
results=results, parsed_data=data, channel=amo.CHANNEL_UNLISTED
|
||||
)
|
||||
assert return_value == results
|
||||
assert results['errors'] == 0
|
||||
assert len(results['messages']) == 0
|
||||
|
@ -42,7 +49,9 @@ class TestDeniedOrigins(TestCase):
|
|||
DeniedInstallOrigin.objects.create(hostname_pattern='foo.com')
|
||||
results = deepcopy(VALIDATOR_SKELETON_RESULTS)
|
||||
data = {'install_origins': ['https://bar.com', 'https://foo.com']}
|
||||
return_value = annotate_validation_results(results, data)
|
||||
return_value = annotate_validation_results(
|
||||
results=results, parsed_data=data, channel=amo.CHANNEL_UNLISTED
|
||||
)
|
||||
assert return_value == results
|
||||
assert results['errors'] == 1
|
||||
assert results['messages'][0] == {
|
||||
|
@ -51,6 +60,7 @@ class TestDeniedOrigins(TestCase):
|
|||
'id': ['validation', 'messages', ''],
|
||||
'message': 'The install origin https://foo.com is not permitted.',
|
||||
'description': [],
|
||||
'extra': True, # This didn't come from the linter.
|
||||
'compatibility_type': None,
|
||||
}
|
||||
|
||||
|
@ -59,7 +69,9 @@ class TestDeniedOrigins(TestCase):
|
|||
DeniedInstallOrigin.objects.create(hostname_pattern='foo.*')
|
||||
results = deepcopy(VALIDATOR_SKELETON_RESULTS)
|
||||
data = {'install_origins': ['https://bar.com', 'https://foo.com']}
|
||||
return_value = annotate_validation_results(results, data)
|
||||
return_value = annotate_validation_results(
|
||||
results=results, parsed_data=data, channel=amo.CHANNEL_UNLISTED
|
||||
)
|
||||
assert return_value == results
|
||||
assert results['errors'] == 1
|
||||
assert results['messages'][0] == {
|
||||
|
@ -68,6 +80,7 @@ class TestDeniedOrigins(TestCase):
|
|||
'id': ['validation', 'messages', ''],
|
||||
'message': 'The install origin https://foo.com is not permitted.',
|
||||
'description': [],
|
||||
'extra': True, # This didn't come from the linter.
|
||||
'compatibility_type': None,
|
||||
}
|
||||
|
||||
|
@ -82,7 +95,9 @@ class TestDeniedOrigins(TestCase):
|
|||
'https://foo.com',
|
||||
]
|
||||
}
|
||||
return_value = annotate_validation_results(results, data)
|
||||
return_value = annotate_validation_results(
|
||||
results=results, parsed_data=data, channel=amo.CHANNEL_UNLISTED
|
||||
)
|
||||
assert return_value == results
|
||||
assert results['errors'] == 2
|
||||
assert results['messages'][0] == {
|
||||
|
@ -91,6 +106,7 @@ class TestDeniedOrigins(TestCase):
|
|||
'id': ['validation', 'messages', ''],
|
||||
'message': 'The install origin https://foo.fr is not permitted.',
|
||||
'description': [],
|
||||
'extra': True, # This didn't come from the linter.
|
||||
'compatibility_type': None,
|
||||
}
|
||||
assert results['messages'][1] == {
|
||||
|
@ -99,6 +115,7 @@ class TestDeniedOrigins(TestCase):
|
|||
'id': ['validation', 'messages', ''],
|
||||
'message': 'The install origin https://foo.com is not permitted.',
|
||||
'description': [],
|
||||
'extra': True, # This didn't come from the linter.
|
||||
'compatibility_type': None,
|
||||
}
|
||||
|
||||
|
@ -107,7 +124,9 @@ class TestDeniedOrigins(TestCase):
|
|||
DeniedInstallOrigin.objects.create(hostname_pattern='foo.*')
|
||||
results = deepcopy(VALIDATOR_SKELETON_RESULTS)
|
||||
data = {'install_origins': ['https://bar.com', 'https://foo.com']}
|
||||
return_value = annotate_validation_results(results, data)
|
||||
return_value = annotate_validation_results(
|
||||
results=results, parsed_data=data, channel=amo.CHANNEL_UNLISTED
|
||||
)
|
||||
assert return_value == results
|
||||
assert results['errors'] == 2
|
||||
assert results['messages'][0] == {
|
||||
|
@ -116,6 +135,7 @@ class TestDeniedOrigins(TestCase):
|
|||
'id': ['validation', 'messages', ''],
|
||||
'message': 'The install origin https://foo.com is not permitted.',
|
||||
'description': [],
|
||||
'extra': True, # This didn't come from the linter.
|
||||
'compatibility_type': None,
|
||||
}
|
||||
assert results['messages'][1] == {
|
||||
|
@ -124,6 +144,7 @@ class TestDeniedOrigins(TestCase):
|
|||
'id': ['validation', 'messages', ''],
|
||||
'message': 'The install origin https://bar.com is not permitted.',
|
||||
'description': [],
|
||||
'extra': True, # This didn't come from the linter.
|
||||
'compatibility_type': None,
|
||||
}
|
||||
|
||||
|
@ -131,7 +152,102 @@ class TestDeniedOrigins(TestCase):
|
|||
DeniedInstallOrigin.objects.create(hostname_pattern='foo.com')
|
||||
results = deepcopy(VALIDATOR_SKELETON_RESULTS)
|
||||
data = {}
|
||||
return_value = annotate_validation_results(results, data)
|
||||
return_value = annotate_validation_results(
|
||||
results=results, parsed_data=data, channel=amo.CHANNEL_UNLISTED
|
||||
)
|
||||
assert return_value == results
|
||||
assert results['errors'] == 0
|
||||
assert len(results['messages']) == 0
|
||||
|
||||
|
||||
class TestAddManifestVersionMessages(TestCase):
|
||||
def test_add_manifest_version_message_not_listed(self):
|
||||
results = deepcopy(amo.VALIDATOR_SKELETON_EXCEPTION_WEBEXT)
|
||||
results['messages'] = []
|
||||
results['metadata']['manifestVersion'] = 3
|
||||
data = {}
|
||||
annotate_validation_results(
|
||||
results=results, parsed_data=data, channel=amo.CHANNEL_UNLISTED
|
||||
)
|
||||
# mv3 submission switch is off so we should have added the message even
|
||||
# for an unlisted submission.
|
||||
assert len(results['messages']) == 1
|
||||
# It should be inserted at the top.
|
||||
assert 'https://blog.mozilla.org/addons/2021/05/27/manifest-v3-update/' in (
|
||||
results['messages'][0]['message']
|
||||
)
|
||||
|
||||
def test_add_manifest_version_message_not_mv3(self):
|
||||
results = deepcopy(amo.VALIDATOR_SKELETON_EXCEPTION_WEBEXT)
|
||||
results['messages'] = []
|
||||
results['metadata']['manifestVersion'] = 2
|
||||
data = {}
|
||||
annotate_validation_results(
|
||||
results=results, parsed_data=data, channel=amo.CHANNEL_LISTED
|
||||
)
|
||||
assert results['messages'] == []
|
||||
|
||||
def test_add_manifest_version_message_switch_enabled(self):
|
||||
results = deepcopy(amo.VALIDATOR_SKELETON_EXCEPTION_WEBEXT)
|
||||
results['messages'] = []
|
||||
results['metadata']['manifestVersion'] = 3
|
||||
data = {}
|
||||
with override_switch('enable-mv3-submissions', active=True):
|
||||
annotate_validation_results(
|
||||
results=results, parsed_data=data, channel=amo.CHANNEL_UNLISTED
|
||||
)
|
||||
assert results['messages'] == []
|
||||
|
||||
# For listed mv3, we want our message suggesting to use unlisted for
|
||||
# the time being.
|
||||
annotate_validation_results(
|
||||
results=results, parsed_data=data, channel=amo.CHANNEL_LISTED
|
||||
)
|
||||
assert len(results['messages']) == 1
|
||||
assert (
|
||||
results['messages'][0]['message'] == 'Manifest V3 compatibility warning'
|
||||
)
|
||||
assert 'https://mzl.la/3hIwQXX' in (
|
||||
# description is a list of strings, the link is in the second one.
|
||||
results['messages'][0]['description'][1]
|
||||
)
|
||||
|
||||
def test_add_manifest_version_message(self):
|
||||
results = deepcopy(amo.VALIDATOR_SKELETON_EXCEPTION_WEBEXT)
|
||||
len(results['messages']) == 1
|
||||
|
||||
# Add the error message when the manifest_version is 3 and the switch to
|
||||
# enable mv3 submissions is off (the default).
|
||||
# The manifest_version error isn't in VALIDATOR_SKELETON_EXCEPTION_WEBEXT.
|
||||
results['metadata']['manifestVersion'] = 3
|
||||
data = {}
|
||||
annotate_validation_results(
|
||||
results=results, parsed_data=data, channel=amo.CHANNEL_LISTED
|
||||
)
|
||||
assert len(results['messages']) == 2 # we added it
|
||||
# It should be inserted at the top.
|
||||
assert 'https://blog.mozilla.org/addons/2021/05/27/manifest-v3-update/' in (
|
||||
results['messages'][0]['message']
|
||||
)
|
||||
|
||||
def test_add_manifest_version_message_replace(self):
|
||||
results = deepcopy(amo.VALIDATOR_SKELETON_EXCEPTION_WEBEXT)
|
||||
# When the linter error is already there, replace it
|
||||
results['messages'] = [
|
||||
{
|
||||
'message': '"/manifest_version" should be <= 2',
|
||||
'description': ['Your JSON file could not be parsed.'],
|
||||
'instancePath': '/manifest_version',
|
||||
'type': 'error',
|
||||
'tier': 1,
|
||||
}
|
||||
]
|
||||
results['metadata']['manifestVersion'] = 3
|
||||
data = {}
|
||||
annotate_validation_results(
|
||||
results=results, parsed_data=data, channel=amo.CHANNEL_LISTED
|
||||
)
|
||||
assert len(results['messages']) == 1 # we replaced it and not added it.
|
||||
assert 'https://blog.mozilla.org/addons/2021/05/27/manifest-v3-update/' in (
|
||||
results['messages'][0]['message']
|
||||
)
|
||||
|
|
|
@ -540,7 +540,9 @@ class TestValidateFilePath(ValidatorTestCase):
|
|||
assert run_addons_linter_mock.call_count == 1
|
||||
assert annotate_validation_results_mock.call_count == 1
|
||||
annotate_validation_results_mock.assert_called_with(
|
||||
run_addons_linter_mock.return_value, parse_addon_mock.return_value
|
||||
results=run_addons_linter_mock.return_value,
|
||||
parsed_data=parse_addon_mock.return_value,
|
||||
channel=amo.CHANNEL_UNLISTED,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import json
|
||||
import os.path
|
||||
from copy import deepcopy
|
||||
from datetime import datetime, timedelta
|
||||
from unittest import mock
|
||||
|
||||
|
@ -11,7 +10,6 @@ import pytest
|
|||
|
||||
from celery import chord
|
||||
from celery.result import AsyncResult
|
||||
from waffle.testutils import override_switch
|
||||
|
||||
from olympia import amo
|
||||
from olympia.addons.models import Addon
|
||||
|
@ -524,47 +522,6 @@ class TestValidator(UploadMixin, TestCase):
|
|||
assert scanners_chord.body.name == 'olympia.scanners.tasks.call_mad_api'
|
||||
|
||||
|
||||
def test_add_manifest_version_error():
|
||||
validation = deepcopy(amo.VALIDATOR_SKELETON_EXCEPTION_WEBEXT)
|
||||
len(validation['messages']) == 1
|
||||
|
||||
# Add the error message when the manifest_version is 3.
|
||||
# The manifest_version error isn't in VALIDATOR_SKELETON_EXCEPTION_WEBEXT.
|
||||
validation['metadata']['manifestVersion'] = 3
|
||||
utils.add_manifest_version_error(validation)
|
||||
assert 'https://blog.mozilla.org/addons/2021/05/27/manifest-v3-update/' in (
|
||||
validation['messages'][0]['message']
|
||||
)
|
||||
assert len(validation['messages']) == 2 # we added it
|
||||
|
||||
# When the linter error is already there, replace it
|
||||
validation['messages'] = [
|
||||
{
|
||||
'message': '"/manifest_version" should be <= 2',
|
||||
'description': ['Your JSON file could not be parsed.'],
|
||||
'dataPath': '/manifest_version',
|
||||
'type': 'error',
|
||||
'tier': 1,
|
||||
}
|
||||
]
|
||||
utils.add_manifest_version_error(validation)
|
||||
assert 'https://blog.mozilla.org/addons/2021/05/27/manifest-v3-update/' in (
|
||||
validation['messages'][0]['message']
|
||||
)
|
||||
assert len(validation['messages']) == 1 # we replaced it
|
||||
|
||||
# Not if the mv3 waffle switch is enabled though
|
||||
with override_switch('enable-mv3-submissions', active=True):
|
||||
validation['messages'] = []
|
||||
utils.add_manifest_version_error(validation)
|
||||
assert validation['messages'] == []
|
||||
|
||||
# Or if the manifest_version != 3
|
||||
validation['metadata']['manifestVersion'] = 2
|
||||
utils.add_manifest_version_error(validation)
|
||||
assert validation['messages'] == []
|
||||
|
||||
|
||||
class TestCreateVersionForUpload(UploadMixin, TestCase):
|
||||
fixtures = ['base/addon_3615']
|
||||
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
import json
|
||||
from copy import deepcopy
|
||||
from datetime import datetime
|
||||
|
||||
from django.core.files.storage import default_storage as storage
|
||||
from django.urls import reverse
|
||||
|
||||
from unittest import mock
|
||||
import waffle
|
||||
|
||||
from unittest import mock
|
||||
from pyquery import PyQuery as pq
|
||||
|
||||
from olympia import amo
|
||||
|
@ -187,21 +185,6 @@ class TestUploadErrors(UploadMixin, TestCase):
|
|||
xpi_info = check_xpi_info({'guid': long_guid, 'version': '1.0'})
|
||||
assert xpi_info['guid'] == long_guid
|
||||
|
||||
def test_mv3_error_added(self):
|
||||
validation = deepcopy(amo.VALIDATOR_SKELETON_EXCEPTION_WEBEXT)
|
||||
validation['metadata']['manifestVersion'] = 3
|
||||
xpi = self.get_upload(
|
||||
'webextension_mv3.xpi',
|
||||
with_validation=True,
|
||||
validation=json.dumps(validation),
|
||||
user=self.user,
|
||||
)
|
||||
|
||||
res = self.client.get(reverse('devhub.upload_detail', args=[xpi.uuid, 'json']))
|
||||
assert b'https://blog.mozilla.org/addons/2021/05/27/manifest-v3-update/' in (
|
||||
res.content
|
||||
)
|
||||
|
||||
|
||||
class TestFileValidation(TestCase):
|
||||
fixtures = ['base/users', 'devhub/addon-validation-1']
|
||||
|
|
|
@ -310,40 +310,6 @@ def wizard_unsupported_properties(data, wizard_fields):
|
|||
return unsupported
|
||||
|
||||
|
||||
def add_manifest_version_error(validation):
|
||||
mv = validation.get('metadata', {}).get('manifestVersion')
|
||||
if (
|
||||
mv != 3
|
||||
or waffle.switch_is_active('enable-mv3-submissions')
|
||||
or 'messages' not in validation
|
||||
):
|
||||
return
|
||||
msg = gettext(
|
||||
'Manifest V3 is currently not supported for upload. '
|
||||
'{start_href}Read more about the support timeline{end_href}.'
|
||||
)
|
||||
url = 'https://blog.mozilla.org/addons/2021/05/27/manifest-v3-update/'
|
||||
start_href = f'<a href="{url}" target="_blank" rel="noopener">'
|
||||
|
||||
new_error_message = msg.format(start_href=start_href, end_href='</a>')
|
||||
for index, message in enumerate(validation['messages']):
|
||||
if message.get('dataPath') == '/manifest_version':
|
||||
# if we find the linter manifest_version=3 warning, replace it
|
||||
validation['messages'][index]['message'] = new_error_message
|
||||
break
|
||||
else:
|
||||
# otherwise insert a new error at the start of the errors
|
||||
validation['messages'].insert(
|
||||
0,
|
||||
{
|
||||
'type': 'error',
|
||||
'message': new_error_message,
|
||||
'tier': 1,
|
||||
'fatal': True,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@transaction.atomic
|
||||
def create_version_for_upload(addon, upload, channel, parsed_data=None):
|
||||
fileupload_exists = addon.fileupload_set.filter(
|
||||
|
|
|
@ -56,7 +56,6 @@ from olympia.api.models import APIKey, APIKeyConfirmation
|
|||
from olympia.devhub.decorators import dev_required, no_admin_disabled
|
||||
from olympia.devhub.models import BlogPost, RssKey
|
||||
from olympia.devhub.utils import (
|
||||
add_manifest_version_error,
|
||||
extract_theme_properties,
|
||||
wizard_unsupported_properties,
|
||||
)
|
||||
|
@ -757,6 +756,10 @@ def json_upload_detail(request, upload, addon_slug=None):
|
|||
i,
|
||||
{
|
||||
'type': 'error',
|
||||
# Actual validation messages coming from the linter are
|
||||
# already escaped because they are coming from
|
||||
# `processed_validation`, but we need to do that for
|
||||
# those coming from ValidationError exceptions as well.
|
||||
'message': escape_all(msg),
|
||||
'tier': 1,
|
||||
'fatal': True,
|
||||
|
@ -768,7 +771,6 @@ def json_upload_detail(request, upload, addon_slug=None):
|
|||
return json_view.error(result)
|
||||
else:
|
||||
result['addon_type'] = pkg.get('type', '')
|
||||
add_manifest_version_error(result['validation'])
|
||||
return result
|
||||
|
||||
|
||||
|
|
|
@ -1009,64 +1009,39 @@ pre.email_comment {
|
|||
color: #777777;
|
||||
}
|
||||
|
||||
#upload-file .submission-checklist {
|
||||
#upload-file .submission-warning {
|
||||
margin: 10px;
|
||||
padding: 10px;
|
||||
padding: 10px 10px 10px 52px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid #F0B500;
|
||||
}
|
||||
|
||||
#upload-file .submission-checklist h5 {
|
||||
#upload-file .submission-warning h5 {
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
#upload-file .submission-checklist h5:before {
|
||||
#upload-file .submission-warning h5:before {
|
||||
background-image: url('../../img/developers/test-warning.png');
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin-left: -42px;
|
||||
margin-right: 10px;
|
||||
content: " ";
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
#upload-file .submission-checklist ul {
|
||||
#upload-file .submission-warning ul {
|
||||
margin-left: 0;
|
||||
}
|
||||
#upload-file .submission-checklist li {
|
||||
#upload-file .submission-warning li {
|
||||
float: none;
|
||||
}
|
||||
#upload-file .submission-checklist a.review-process-overview {
|
||||
#upload-file .submission-warning a.review-process-overview {
|
||||
font-style: italic;
|
||||
display: block;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
#upload-file .important-warning {
|
||||
margin: 10px;
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid #F0B500;
|
||||
}
|
||||
|
||||
#upload-file .important-warning h5 {
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
#upload-file .important-warning h5:before {
|
||||
background-image: url('../../img/developers/test-warning-important.png');
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin-right: 10px;
|
||||
content: " ";
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
#upload-file .important-warning a.review-process-overview {
|
||||
display: block;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
|
||||
/* @end */
|
||||
|
||||
/* @group Recent Activity */
|
||||
|
|
|
@ -539,10 +539,67 @@
|
|||
|
||||
$('<strong>').text(message).appendTo(upload_results);
|
||||
|
||||
let checklistWarningsIds = [
|
||||
'NO_DOCUMENT_WRITE',
|
||||
'DANGEROUS_EVAL',
|
||||
'NO_IMPLIED_EVAL',
|
||||
'UNSAFE_VAR_ASSIGNMENT',
|
||||
'MANIFEST_CSP',
|
||||
],
|
||||
mv3NoticeId = '_MV3_COMPATIBILITY',
|
||||
checklistMessages = [],
|
||||
mv3CompatibilityMessage,
|
||||
// this.id is in the form ["abc_def_ghi', 'foo_bar', 'something'],
|
||||
// we usually only match one of the elements.
|
||||
matchId = function (id) {
|
||||
return this.hasOwnProperty('id') && _.contains(this.id, id);
|
||||
};
|
||||
|
||||
if (results.validation.messages) {
|
||||
for (var i = 0; i < results.validation.messages.length; i++) {
|
||||
let current = results.validation.messages[i];
|
||||
|
||||
if (current.extra) {
|
||||
// We want to ignore messages that are not coming from the
|
||||
// linter in the logic that decides whether or not to show the
|
||||
// submission checklist box. Those are tagged with extra: true.
|
||||
messageCount--;
|
||||
}
|
||||
|
||||
// Check for warnings we want to higlight specifically.
|
||||
let matched = _.find(checklistWarningsIds, matchId, current);
|
||||
if (matched) {
|
||||
checklistMessages.push(gettext(current.message));
|
||||
// We want only once every possible warning hit.
|
||||
checklistWarningsIds.splice(
|
||||
checklistWarningsIds.indexOf(matched),
|
||||
1,
|
||||
);
|
||||
if (!checklistWarningsIds.length) break;
|
||||
}
|
||||
|
||||
// Manifest v3 warning is a custom one added by addons-server
|
||||
// that should be added once, regardless of whether or not we're
|
||||
// displaying the submission warning box.
|
||||
if (_.find([mv3NoticeId], matchId, current)) {
|
||||
let mv3CompatibilityBox = $('<div>')
|
||||
.attr('class', 'submission-warning')
|
||||
.appendTo(upload_results);
|
||||
$('<h5>').text(current.message).appendTo(mv3CompatibilityBox);
|
||||
// That description is split into several paragraphs and can
|
||||
// contain HTML for links.
|
||||
current.description.forEach(function (item) {
|
||||
$('<p>').html(item).appendTo(mv3CompatibilityBox);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (messageCount > 0) {
|
||||
// Validation checklist
|
||||
var checklist_box = $('<div>')
|
||||
.attr('class', 'submission-checklist')
|
||||
// Validation checklist should be displayed if there is at least
|
||||
// one message coming from the linter.
|
||||
let checklist_box = $('<div>')
|
||||
.attr('class', 'submission-warning')
|
||||
.appendTo(upload_results),
|
||||
checklist = [
|
||||
gettext(
|
||||
|
@ -551,25 +608,7 @@
|
|||
gettext(
|
||||
'If your add-on requires an account to a website in order to be fully tested, include a test username and password in the Notes to Reviewer (this can be done in the next step).',
|
||||
),
|
||||
],
|
||||
warnings_id = [
|
||||
'NO_DOCUMENT_WRITE',
|
||||
'DANGEROUS_EVAL',
|
||||
'NO_IMPLIED_EVAL',
|
||||
'UNSAFE_VAR_ASSIGNMENT',
|
||||
'MANIFEST_CSP',
|
||||
'set_innerHTML',
|
||||
'namespace_pollution',
|
||||
'dangerous_global',
|
||||
],
|
||||
current,
|
||||
matched,
|
||||
messages = [],
|
||||
// this.id is in the form ["testcases_javascript_instanceactions", "_call_expression", "createelement_variable"],
|
||||
// we usually only match one of the elements.
|
||||
matchId = function (id) {
|
||||
return this.hasOwnProperty('id') && _.contains(this.id, id);
|
||||
};
|
||||
];
|
||||
|
||||
$('<h5>')
|
||||
.text(gettext('Add-on submission checklist'))
|
||||
|
@ -582,28 +621,18 @@
|
|||
)
|
||||
.appendTo(checklist_box);
|
||||
if (results.validation.metadata.contains_binary_extension) {
|
||||
messages.push(
|
||||
checklistMessages.push(
|
||||
gettext(
|
||||
'Minified, concatenated or otherwise machine-generated scripts (excluding known libraries) need to have their sources submitted separately for review. Make sure that you use the source code upload field to avoid having your submission rejected.',
|
||||
),
|
||||
);
|
||||
}
|
||||
for (var i = 0; i < results.validation.messages.length; i++) {
|
||||
current = results.validation.messages[i];
|
||||
matched = _.find(warnings_id, matchId, current);
|
||||
if (matched) {
|
||||
messages.push(gettext(current.message));
|
||||
// We want only once every possible warning hit.
|
||||
warnings_id.splice(warnings_id.indexOf(matched), 1);
|
||||
if (!warnings_id.length) break;
|
||||
}
|
||||
}
|
||||
var checklist_ul = $('<ul>');
|
||||
$.each(checklist, function (i) {
|
||||
$('<li>').text(checklist[i]).appendTo(checklist_ul);
|
||||
});
|
||||
checklist_ul.appendTo(checklist_box);
|
||||
if (messages.length) {
|
||||
if (checklistMessages.length) {
|
||||
$('<h6>')
|
||||
.text(
|
||||
gettext(
|
||||
|
@ -612,12 +641,13 @@
|
|||
)
|
||||
.appendTo(checklist_box);
|
||||
var messages_ul = $('<ul>');
|
||||
$.each(messages, function (i) {
|
||||
// Note: validation messages are supposed to be already escaped by
|
||||
// devhub.views.json_upload_detail(), which does an escape_all()
|
||||
// call on messages. So we need to use html() and not text() to
|
||||
// display them, since they can contain HTML entities.
|
||||
$('<li>').html(messages[i]).appendTo(messages_ul);
|
||||
$.each(checklistMessages, function (i) {
|
||||
// Note: validation messages can contain HTML, in the form of
|
||||
// links or entities, because devhub.views.json_upload_detail()
|
||||
// uses processed_validation with escapes and linkifies linter
|
||||
// messages (and escape_all() on non-linter messages).
|
||||
// So we need to use html() and not text() to display them.
|
||||
$('<li>').html(checklistMessages[i]).appendTo(messages_ul);
|
||||
});
|
||||
messages_ul.appendTo(checklist_box);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче