def test_no_manifest_at_root(self): with self.assertRaises(forms.ValidationError) as exc: WebAppParser().parse( self.packaged_app_path('no-manifest-at-root.zip')) m = exc.exception.messages[0] assert m.startswith('The file "manifest.webapp" was not found'), ( 'Unexpected: %s' % m)
def test_name_with_translations_fallback(self, get_json_data): get_json_data.return_value = { 'name': 'Blah', 'description': 'Blah Description', 'developer': { 'name': 'Mozilla Marketplace Testing' }, 'default_locale': 'en-US', 'locales': { 'fr': { 'description': 'Blah Description (fr)', }, 'es': { 'name': 'Blah (es)', } } } # The argument to parse() is supposed to be a filename, it doesn't # matter here though since we are mocking get_json_data(). parsed_results = WebAppParser().parse('') eq_(parsed_results['name'].get('fr'), 'Blah') # Falls back to default. eq_(parsed_results['name'].get('es'), 'Blah (es)') eq_(parsed_results['name'].get('en-US'), 'Blah') eq_(parsed_results['name'].get('de'), None) eq_(parsed_results['default_locale'], 'en-US')
def test_name_with_translations_and_short_languages(self, get_json_data): get_json_data.return_value = { 'name': 'Blah', 'developer': { 'name': 'Mozilla Marketplace Testing' }, 'default_locale': 'en', # Will be transformed to en-US. 'locales': { 'fr': { 'name': 'Blah (fr)', }, 'pt': { 'name': 'Blah (pt)', } } } # The argument to parse() is supposed to be a filename, it doesn't # matter here though since we are mocking get_json_data(). parsed_results = WebAppParser().parse('') eq_(parsed_results['name'].get('fr'), 'Blah (fr)') eq_(parsed_results['name'].get('pt-PT'), 'Blah (pt)') eq_(parsed_results['name'].get('en-US'), 'Blah') eq_(parsed_results['name'].get('de'), None) eq_(parsed_results['name'].get('pt'), None) eq_(parsed_results['name'].get('en'), None) eq_(parsed_results['default_locale'], 'en-US')
def test_non_ascii(self): wm = json.dumps(dict(name=u'まつもとゆきひろ', version='1.0', developer=dict(name=u'まつもとゆきひろ')), encoding='shift-jis') wp = WebAppParser().parse(self.webapp(contents=wm)) eq_(wp['name'], {'en-US': u'まつもとゆきひろ'})
def test_no_locales(self): wp = WebAppParser().parse( self.webapp( dict(name='foo', version='1.0', description='description', developer=dict(name='bar')))) eq_(wp['description']['en-US'], u'description')
def clean_upload(self): upload = self.cleaned_data['upload'] errors = [] if upload.size > self.max_size: errors.append({ 'type': 'error', 'message': _('Packaged app too large for submission. Packages ' 'must be smaller than %s.' % filesizeformat( self.max_size)), 'tier': 1, }) # Immediately raise an error, do not process the rest of the view, # which would read the file. raise self.persist_errors(errors, upload) manifest = None try: # Be careful to keep this as in-memory zip reading. safe_zip = SafeUnzip(upload, 'r') safe_zip.is_valid() # Will throw ValidationError if necessary. manifest = safe_zip.extract_path('manifest.webapp') except forms.ValidationError as e: errors.append({ 'type': 'error', 'message': ''.join(e.messages), 'tier': 1, }) except Exception as e: errors.append({ 'type': 'error', 'message': _('Error extracting manifest from zip file.'), 'tier': 1, }) finally: safe_zip.close() origin = None if manifest: try: origin = WebAppParser.decode_manifest(manifest).get('origin') except forms.ValidationError as e: errors.append({ 'type': 'error', 'message': ''.join(e.messages), 'tier': 1, }) if origin: try: verify_app_domain(origin, packaged=True, exclude=self.addon) except forms.ValidationError, e: errors.append({ 'type': 'error', 'message': ''.join(e.messages), 'tier': 1, })
def test_parse_packaged_BOM(self): wp = WebAppParser().parse(self.packaged_app_path('mozBOM.zip')) eq_(wp['guid'], None) eq_(wp['name']['en-US'], u'Packaged MozBOM ょ') eq_(wp['description']['en-US'], u'Exciting BOM action!') eq_(wp['description']['es'], u'¡Acción BOM!') eq_(wp['description']['it'], u'Azione BOM!') eq_(wp['version'], '1.0') eq_(wp['default_locale'], 'en-US')
def test_parse(self): wp = WebAppParser().parse(self.webapp_path) eq_(wp['guid'], None) eq_(wp['description']['en-US'], u'Exciting Open Web development action!') # UTF-8 byte string decoded to unicode. eq_(wp['description']['es'], u'\xa1Acci\xf3n abierta emocionante del desarrollo del Web!') eq_(wp['description']['it'], u'Azione aperta emozionante di sviluppo di fotoricettore!') eq_(wp['version'], '1.0') eq_(wp['default_locale'], 'en-US')
def test_developer_name(self, get_json_data): get_json_data.return_value = { 'name': 'Blah', 'developer': { 'name': 'Mozilla Marketplace Testing' } } # The argument to parse() is supposed to be a filename, it doesn't # matter here though since we are mocking get_json_data(). parsed_results = WebAppParser().parse('') eq_(parsed_results['developer_name'], 'Mozilla Marketplace Testing')
def test_empty_developer_object(self, get_json_data): get_json_data.return_value = {'name': 'Blah', 'developer': {}} with self.assertRaises(forms.ValidationError) as e: # The argument to parse() is supposed to be a filename, it doesn't # matter here though since we are mocking get_json_data(). WebAppParser().parse('') eq_(e.exception.messages, [ "Developer name is required in the manifest" " in order to display it on the app's " "listing." ])
def test_parse_packaged(self): wp = WebAppParser().parse(self.packaged_app_path('mozball.zip')) eq_(wp['guid'], None) eq_(wp['name']['en-US'], u'Packaged MozillaBall ょ') eq_(wp['description']['en-US'], u'Exciting Open Web development action!') eq_(wp['description']['es'], u'¡Acción abierta emocionante del desarrollo del Web!') eq_(wp['description']['it'], u'Azione aperta emozionante di sviluppo di fotoricettore!') eq_(wp['version'], '1.0') eq_(wp['default_locale'], 'en-US')
def test_no_manifest_at_root(self): path = self.packaged_app_path('no-manifest-at-root.zip') if storage_is_remote(): with open(path) as local_f: with storage.open(path, 'w') as remote_f: copyfileobj(local_f, remote_f) with self.assertRaises(forms.ValidationError) as exc: WebAppParser().parse(path) m = exc.exception.messages[0] assert m.startswith('The file "manifest.webapp" was not found'), ( 'Unexpected: %s' % m)
def generate_packaged_app(namedict, apptype, categories, developer_name, privacy_policy=None, device_types=(), permissions=(), versions=(), default_locale='en-US', package_file=None, status=4, **kw): now = datetime.datetime.now() app = app_factory(categories=categories, name=namedict[default_locale], complete=False, rated=True, is_packaged=True, privacy_policy=privacy_policy, version_kw={ 'version': '1.0', 'reviewed': now if status >= 4 else None, '_developer_name': developer_name}, file_kw={'status': status}) if device_types: for dt in device_types: app.addondevicetype_set.create(device_type=DEVICE_CHOICES_IDS[dt]) else: app.addondevicetype_set.create(device_type=1) f = app.latest_version.all_files[0] f.update(filename=f.generate_filename()) fp = os.path.join(app.latest_version.path_prefix, f.filename) if package_file: package_file_file = open(package_file) manifest = WebAppParser().get_json_data(package_file_file) AppManifest.objects.create( version=app.latest_version, manifest=json.dumps(manifest)) # copy package_file to storage like a normal app. private_storage.save(fp, package_file_file) app.update_version() return app with private_storage.open(fp, 'w') as out: generate_app_package(app, out, apptype, permissions, namedict, version=app.latest_version) for i, vspec in enumerate(versions, 1): st = STATUS_CHOICES_API_LOOKUP[vspec.get("status", "public")] rtime = (now + datetime.timedelta(i)) v = version_factory(version="1." + str(i), addon=app, reviewed=rtime if st >= 4 else None, nomination=rtime if st > 0 else None, created=rtime, file_kw={'status': st}, _developer_name=developer_name) f = v.files.all()[0] f.update(filename=f.generate_filename()) fp = os.path.join(app.latest_version.path_prefix, f.filename) with private_storage.open(fp, 'w') as out: generate_app_package(app, out, vspec.get("type", apptype), vspec.get("permissions", permissions), namedict, version=v) app.update_version() return app
def test_no_manifest_at_root(self): path = self.packaged_app_path('no-manifest-at-root.zip') if storage_is_remote(): copy_stored_file(path, path, src_storage=local_storage, dst_storage=private_storage) with self.assertRaises(forms.ValidationError) as exc: WebAppParser().parse(private_storage.open(path)) m = exc.exception.messages[0] assert m.startswith('The file "manifest.webapp" was not found'), ( 'Unexpected: %s' % m)
def test_parse_packaged_BOM(self): path = self.packaged_app_path('mozBOM.zip') if storage_is_remote(): with open(path) as local_f: with storage.open(path, 'w') as remote_f: copyfileobj(local_f, remote_f) wp = WebAppParser().parse(path) eq_(wp['guid'], None) eq_(wp['name']['en-US'], u'Packaged MozBOM ょ') eq_(wp['description']['en-US'], u'Exciting BOM action!') eq_(wp['description']['es'], u'¡Acción BOM!') eq_(wp['description']['it'], u'Azione BOM!') eq_(wp['version'], '1.0') eq_(wp['default_locale'], 'en-US')
def test_parse_packaged_BOM(self): path = self.packaged_app_path('mozBOM.zip') if storage_is_remote(): copy_stored_file(path, path, src_storage=local_storage, dst_storage=private_storage) wp = WebAppParser().parse(private_storage.open(path)) eq_(wp['guid'], None) eq_(wp['name']['en-US'], u'Packaged MozBOM ょ') eq_(wp['description']['en-US'], u'Exciting BOM action!') eq_(wp['description']['es'], u'¡Acción BOM!') eq_(wp['description']['it'], u'Azione BOM!') eq_(wp['version'], '1.0') eq_(wp['default_locale'], 'en-US')
def test_parse_packaged(self): path = self.packaged_app_path('mozball.zip') if storage_is_remote(): with open(path) as local_f: with storage.open(path, 'w') as remote_f: copyfileobj(local_f, remote_f) wp = WebAppParser().parse(path) eq_(wp['guid'], None) eq_(wp['name']['en-US'], u'Packaged MozillaBall ょ') eq_(wp['description']['en-US'], u'Exciting Open Web development action!') eq_(wp['description']['es'], u'¡Acción abierta emocionante del desarrollo del Web!') eq_(wp['description']['it'], u'Azione aperta emozionante di sviluppo di fotoricettore!') eq_(wp['version'], '1.0') eq_(wp['default_locale'], 'en-US')
def clean_upload(self): upload = self.cleaned_data["upload"] errors = [] if upload.size > self.max_size: errors.append( { "type": "error", "message": _( "Packaged app too large for submission. Packages " "must be smaller than %s." % filesizeformat(self.max_size) ), "tier": 1, } ) # Immediately raise an error, do not process the rest of the view, # which would read the file. raise self.persist_errors(errors, upload) manifest = None try: # Be careful to keep this as in-memory zip reading. manifest = ZipFile(upload, "r").read("manifest.webapp") except Exception as e: errors.append({"type": "error", "message": _("Error extracting manifest from zip file."), "tier": 1}) origin = None if manifest: try: origin = WebAppParser.decode_manifest(manifest).get("origin") except forms.ValidationError as e: errors.append({"type": "error", "message": "".join(e.messages), "tier": 1}) if origin: try: verify_app_domain(origin, packaged=True, exclude=self.addon) except forms.ValidationError, e: errors.append({"type": "error", "message": "".join(e.messages), "tier": 1})
def import_manifests(ids, **kw): for app in Webapp.objects.filter(id__in=ids): for version in app.versions.all(): try: file_ = version.files.latest() if file_.status == amo.STATUS_DISABLED: file_path = file_.guarded_file_path else: file_path = file_.file_path manifest = WebAppParser().get_json_data(file_path) m, c = AppManifest.objects.get_or_create( version=version, manifest=json.dumps(manifest)) if c: task_log.info( '[Webapp:%s] Imported manifest for version %s' % ( app.id, version.id)) else: task_log.info( '[Webapp:%s] App manifest exists for version %s' % ( app.id, version.id)) except Exception as e: task_log.info('[Webapp:%s] Error loading manifest for version ' '%s: %s' % (app.id, version.id, e))
def test_utf8_bom(self): wm = codecs.BOM_UTF8 + json.dumps(self.manifest, encoding='utf8') wp = WebAppParser().parse(self.webapp(contents=wm)) eq_(wp['version'], '1.0')
def test_syntax_error(self): with self.assertRaises(forms.ValidationError) as exc: WebAppParser().parse(self.webapp(contents='}]')) m = exc.exception.messages[0] assert m.startswith('The webapp manifest is not valid JSON.'), ( 'Unexpected: %s' % m)
def test_no_description(self): wp = WebAppParser().parse( self.webapp( dict(name='foo', version='1.0', developer=dict(name='bar')))) eq_(wp['description'], {})