Beispiel #1
0
def test_extract_theme_properties(zip_file):
    versions = {
        amo.DEFAULT_WEBEXT_MAX_VERSION,
        amo.DEFAULT_STATIC_THEME_MIN_VERSION_FIREFOX,
        amo.DEFAULT_STATIC_THEME_MIN_VERSION_ANDROID,
    }
    for version in versions:
        AppVersion.objects.create(application=amo.FIREFOX.id, version=version)
        AppVersion.objects.create(application=amo.ANDROID.id, version=version)

    addon = addon_factory(type=amo.ADDON_STATICTHEME)
    result = utils.extract_theme_properties(
        addon, addon.current_version.channel)
    assert result == {}  # There's no file, but it be should safely handled.

    # Add the zip in the right place
    zip_file = os.path.join(settings.ROOT, zip_file)
    copy_stored_file(zip_file, addon.current_version.all_files[0].file_path)
    result = utils.extract_theme_properties(
        addon, addon.current_version.channel)
    assert result == {
        "colors": {
            "frame": "#adb09f",
            "tab_background_text": "#000"
        },
        "images": {
            "theme_frame": "weta.png"
        }
    }
Beispiel #2
0
    def from_upload(cls,
                    upload,
                    version,
                    platform,
                    is_beta=False,
                    parsed_data=None):
        if parsed_data is None:
            parsed_data = {}
        addon = version.addon

        file_ = cls(version=version, platform=platform)
        upload.path = force_bytes(nfd_str(upload.path))
        ext = os.path.splitext(upload.path)[1]
        if ext == '.jar':
            ext = '.xpi'
        file_.filename = file_.generate_filename(extension=ext or '.xpi')
        # Size in bytes.
        file_.size = storage.size(upload.path)
        data = cls.get_jetpack_metadata(upload.path)
        if 'sdkVersion' in data and data['sdkVersion']:
            file_.jetpack_version = data['sdkVersion'][:10]
        file_.no_restart = parsed_data.get('no_restart', False)
        file_.strict_compatibility = parsed_data.get('strict_compatibility',
                                                     False)
        file_.is_multi_package = parsed_data.get('is_multi_package', False)
        file_.is_experiment = parsed_data.get('is_experiment', False)
        file_.is_webextension = parsed_data.get('is_webextension', False)

        if (is_beta and addon.status == amo.STATUS_PUBLIC
                and version.channel == amo.RELEASE_CHANNEL_LISTED):
            file_.status = amo.STATUS_BETA

        file_.hash = file_.generate_hash(upload.path)
        file_.original_hash = file_.hash

        if upload.validation:
            validation = json.loads(upload.validation)
            if validation['metadata'].get('requires_chrome'):
                file_.requires_chrome = True

        file_.save()

        log.debug('New file: %r from %r' % (file_, upload))
        # Move the uploaded file from the temp location.
        copy_stored_file(
            upload.path,
            os.path.join(version.path_prefix, nfd_str(file_.filename)))

        if upload.validation:
            # Import loop.
            from olympia.devhub.tasks import annotate_validation_results
            from olympia.devhub.utils import ValidationAnnotator

            validation = annotate_validation_results(validation)
            FileValidation.from_json(file_, validation)

            # Copy annotations from any previously approved file.
            ValidationAnnotator(file_).update_annotations()

        return file_
Beispiel #3
0
    def from_upload(cls, upload, version, parsed_data=None):
        """
        Create a File instance from a FileUpload, a Version and the parsed_data
        generated by parse_addon().

        Note that it's the caller's responsability to ensure the file is valid.
        We can't check for that here because an admin may have overridden the
        validation results."""
        assert parsed_data is not None

        file_ = cls(version=version)
        upload_path = force_str(nfd_str(upload.path))
        ext = force_str(os.path.splitext(upload_path)[1])
        file_.filename = file_.generate_filename(extension=ext or '.xpi')
        # Size in bytes.
        file_.size = storage.size(upload_path)
        file_.is_restart_required = parsed_data.get('is_restart_required', False)
        file_.strict_compatibility = parsed_data.get('strict_compatibility', False)
        file_.is_experiment = parsed_data.get('is_experiment', False)
        file_.is_webextension = parsed_data.get('is_webextension', False)
        file_.is_mozilla_signed_extension = parsed_data.get(
            'is_mozilla_signed_extension', False
        )

        file_.hash = file_.generate_hash(upload_path)
        file_.original_hash = file_.hash
        file_.manifest_version = parsed_data.get(
            'manifest_version', DEFAULT_MANIFEST_VERSION
        )
        file_.save()

        if file_.is_webextension:
            permissions = list(parsed_data.get('permissions', []))
            optional_permissions = list(parsed_data.get('optional_permissions', []))

            # devtools_page isn't in permissions block but treated as one
            # if a custom devtools page is added by an addon
            if 'devtools_page' in parsed_data:
                permissions.append('devtools')

            # Add content_scripts host matches too.
            for script in parsed_data.get('content_scripts', []):
                permissions.extend(script.get('matches', []))
            if permissions or optional_permissions:
                WebextPermission.objects.create(
                    permissions=permissions,
                    optional_permissions=optional_permissions,
                    file=file_,
                )

        log.info(f'New file: {file_!r} from {upload!r}')

        # Move the uploaded file from the temp location.
        copy_stored_file(upload_path, file_.current_file_path)

        if upload.validation:
            validation = json.loads(upload.validation)
            FileValidation.from_json(file_, validation)

        return file_
Beispiel #4
0
def test_extract_theme_properties(zip_file):
    versions = {
        amo.DEFAULT_WEBEXT_MAX_VERSION,
        amo.DEFAULT_STATIC_THEME_MIN_VERSION_FIREFOX,
        amo.DEFAULT_STATIC_THEME_MIN_VERSION_ANDROID,
    }
    for version in versions:
        AppVersion.objects.create(application=amo.FIREFOX.id, version=version)
        AppVersion.objects.create(application=amo.ANDROID.id, version=version)

    addon = addon_factory(type=amo.ADDON_STATICTHEME)
    result = utils.extract_theme_properties(addon,
                                            addon.current_version.channel)
    assert result == {}  # There's no file, but it be should safely handled.

    # Add the zip in the right place
    zip_file = os.path.join(settings.ROOT, zip_file)
    copy_stored_file(zip_file, addon.current_version.all_files[0].file_path)
    result = utils.extract_theme_properties(addon,
                                            addon.current_version.channel)
    assert result == {
        "colors": {
            "frame": "#adb09f",
            "tab_background_text": "#000"
        },
        "images": {
            "theme_frame": "weta.png"
        }
    }
Beispiel #5
0
 def _mock_xpi_side_effect(self, lwt, upload_path):
     xpi_path = os.path.join(
         settings.ROOT,
         'src/olympia/devhub/tests/addons/mozilla_static_theme.zip')
     copy_stored_file(xpi_path, upload_path)
     assert not os.path.isdir(upload_path)
     return mock.DEFAULT
Beispiel #6
0
def test_recreate_theme_previews():
    xpi_path = os.path.join(
        settings.ROOT, 'src/olympia/devhub/tests/addons/mozilla_static_theme.zip'
    )

    addon_without_previews = addon_factory(type=amo.ADDON_STATICTHEME)
    copy_stored_file(xpi_path, addon_without_previews.current_version.file.file_path)
    addon_with_previews = addon_factory(type=amo.ADDON_STATICTHEME)
    copy_stored_file(xpi_path, addon_with_previews.current_version.file.file_path)
    VersionPreview.objects.create(
        version=addon_with_previews.current_version,
        sizes={'image': [123, 456], 'thumbnail': [34, 45]},
    )

    assert addon_without_previews.current_previews.count() == 0
    assert addon_with_previews.current_previews.count() == 1
    recreate_theme_previews([addon_without_previews.id, addon_with_previews.id])
    assert addon_without_previews.reload().current_previews.count() == 2
    assert addon_with_previews.reload().current_previews.count() == 2
    sizes = addon_without_previews.current_previews.values_list('sizes', flat=True)
    renderings = amo.THEME_PREVIEW_RENDERINGS
    assert list(sizes) == [
        {
            'image': list(renderings['firefox']['full']),
            'thumbnail': list(renderings['firefox']['thumbnail']),
            'image_format': renderings['firefox']['image_format'],
            'thumbnail_format': renderings['firefox']['thumbnail_format'],
        },
        {
            'image': list(renderings['amo']['full']),
            'thumbnail': list(renderings['amo']['thumbnail']),
            'image_format': renderings['amo']['image_format'],
            'thumbnail_format': renderings['amo']['thumbnail_format'],
        },
    ]
Beispiel #7
0
    def test_can_not_delete_without_discovery_edit_permission(self):
        uploaded_photo = get_uploaded_file('transparent.png')
        item = PrimaryHeroImage.objects.create(custom_image=uploaded_photo)
        src = os.path.join(
            settings.MEDIA_ROOT, 'hero-featured-image', 'transparent.png')
        dest = os.path.join(
            settings.MEDIA_ROOT, 'hero-featured-image', 'thumbs',
            'transparent.png')
        copy_stored_file(src, dest)
        delete_url = reverse(
            'admin:discovery_primaryheroimageupload_delete', args=(item.pk,)
        )
        user = user_factory()
        self.grant_permission(user, 'Admin:Tools')
        self.client.login(email=user.email)
        # Can not access delete confirmation page.
        response = self.client.get(delete_url, follow=True)
        assert response.status_code == 403
        assert PrimaryHeroImage.objects.filter(pk=item.pk).exists()
        assert os.path.exists(os.path.join(
            settings.MEDIA_ROOT, 'hero-featured-image', 'transparent.png'))
        assert os.path.exists(os.path.join(
            settings.MEDIA_ROOT, 'hero-featured-image', 'thumbs',
            'transparent.png'))

        # Can not actually delete either.
        response = self.client.post(
            delete_url, data={'post': 'yes'}, follow=True)
        assert response.status_code == 403
        assert PrimaryHeroImage.objects.filter(pk=item.pk).exists()
        assert os.path.exists(os.path.join(
            settings.MEDIA_ROOT, 'hero-featured-image', 'transparent.png'))
        assert os.path.exists(os.path.join(
            settings.MEDIA_ROOT, 'hero-featured-image',
            'thumbs', 'transparent.png'))
Beispiel #8
0
def test_recreate_theme_previews():
    xpi_path = os.path.join(
        settings.ROOT,
        'src/olympia/devhub/tests/addons/mozilla_static_theme.zip')

    addon_without_previews = addon_factory(type=amo.ADDON_STATICTHEME)
    copy_stored_file(
        xpi_path,
        addon_without_previews.current_version.all_files[0].file_path)
    addon_with_previews = addon_factory(type=amo.ADDON_STATICTHEME)
    copy_stored_file(
        xpi_path,
        addon_with_previews.current_version.all_files[0].file_path)
    VersionPreview.objects.create(
        version=addon_with_previews.current_version,
        sizes={'image': [123, 456], 'thumbnail': [34, 45]})

    assert addon_without_previews.current_previews.count() == 0
    assert addon_with_previews.current_previews.count() == 1
    recreate_theme_previews(
        [addon_without_previews.id, addon_with_previews.id])
    assert addon_without_previews.reload().current_previews.count() == 3
    assert addon_with_previews.reload().current_previews.count() == 3
    sizes = addon_without_previews.current_previews.values_list(
        'sizes', flat=True)
    assert list(sizes) == [
        {'image': list(amo.THEME_PREVIEW_SIZES['header']['full']),
         'thumbnail': list(amo.THEME_PREVIEW_SIZES['header']['thumbnail'])},
        {'image': list(amo.THEME_PREVIEW_SIZES['list']['full']),
         'thumbnail': list(amo.THEME_PREVIEW_SIZES['list']['thumbnail'])},
        {'image': list(amo.THEME_PREVIEW_SIZES['single']['full']),
         'thumbnail': list(amo.THEME_PREVIEW_SIZES['single']['thumbnail'])}]
Beispiel #9
0
def approve_rereview(theme):
    """Replace original theme with pending theme on filesystem."""
    # If reuploaded theme, replace old theme design.
    storage = LocalFileStorage()
    rereview = theme.rereviewqueuetheme_set.all()
    reupload = rereview[0]

    if reupload.header_path != reupload.theme.header_path:
        create_persona_preview_images(
            src=reupload.header_path,
            full_dst=[
                reupload.theme.thumb_path,
                reupload.theme.icon_path],
            set_modified_on=reupload.theme.addon.serializable_reference())

        if not reupload.theme.is_new():
            # Legacy themes also need a preview_large.jpg.
            # Modern themes use preview.png for both thumb and preview so there
            # is no problem there.
            copy_stored_file(reupload.theme.thumb_path,
                             reupload.theme.preview_path, storage=storage)

        move_stored_file(
            reupload.header_path, reupload.theme.header_path, storage=storage)

    theme = reupload.theme
    rereview.delete()
    theme_checksum(theme)
    theme.addon.increment_theme_version_number()
Beispiel #10
0
def approve_rereview(theme):
    """Replace original theme with pending theme on filesystem."""
    # If reuploaded theme, replace old theme design.
    storage = LocalFileStorage()
    rereview = theme.rereviewqueuetheme_set.all()
    reupload = rereview[0]

    if reupload.header_path != reupload.theme.header_path:
        create_persona_preview_images(
            src=reupload.header_path,
            full_dst=[reupload.theme.thumb_path, reupload.theme.icon_path],
            set_modified_on=reupload.theme.addon.serializable_reference())

        if not reupload.theme.is_new():
            # Legacy themes also need a preview_large.jpg.
            # Modern themes use preview.png for both thumb and preview so there
            # is no problem there.
            copy_stored_file(reupload.theme.thumb_path,
                             reupload.theme.preview_path,
                             storage=storage)

        move_stored_file(reupload.header_path,
                         reupload.theme.header_path,
                         storage=storage)

    theme = reupload.theme
    rereview.delete()
    theme_checksum(theme)
    theme.addon.increment_theme_version_number()
Beispiel #11
0
 def _mock_xpi_side_effect(self, lwt, upload_path):
     xpi_path = os.path.join(
         settings.ROOT,
         'src/olympia/devhub/tests/addons/mozilla_static_theme.zip')
     copy_stored_file(xpi_path, upload_path)
     assert not os.path.isdir(upload_path)
     return mock.DEFAULT
Beispiel #12
0
def create_custom_icon_from_predefined(addon_ids, **kwargs):
    addons = Addon.objects.filter(id__in=addon_ids).no_transforms()
    hashes = {}

    predefined = os.path.join(settings.ROOT, 'static', 'img', 'addon-icons')
    _, icons = storage.listdir(predefined)
    for icon in icons:
        if b'32' in icon and b'default' not in icon:
            icon_name = force_str(icon.split(b'-')[0])
            with open(os.path.join(predefined, force_str(icon)), 'rb') as fd:
                hashes[icon_name] = hashlib.md5(fd.read()).hexdigest()[:8]

    for addon in addons:
        type_split = addon.icon_type.split('/') if addon.icon_type else []
        if len(type_split) != 2 or type_split[0] != 'icon':
            continue
        icon_name = type_split[1]

        destination = addon.get_icon_dir()
        for size in (32, 64, 128):
            src = os.path.join(predefined, f'{icon_name}-{size}.png')
            if not os.path.exists(src):
                break
            copy_stored_file(
                src,
                os.path.join(destination, f'{addon.id}-{size}.png'),
            )
        else:
            addon.update(icon_type='image/png', icon_hash=hashes.get(icon_name, ''))
Beispiel #13
0
def test_recreate_theme_previews():
    xpi_path = os.path.join(
        settings.ROOT,
        'src/olympia/devhub/tests/addons/mozilla_static_theme.zip')

    addon_without_previews = addon_factory(type=amo.ADDON_STATICTHEME)
    copy_stored_file(
        xpi_path,
        addon_without_previews.current_version.all_files[0].file_path)
    addon_with_previews = addon_factory(type=amo.ADDON_STATICTHEME)
    copy_stored_file(
        xpi_path,
        addon_with_previews.current_version.all_files[0].file_path)
    VersionPreview.objects.create(
        version=addon_with_previews.current_version,
        sizes={'image': [123, 456], 'thumbnail': [34, 45]})

    assert addon_without_previews.current_previews.count() == 0
    assert addon_with_previews.current_previews.count() == 1
    recreate_theme_previews(
        [addon_without_previews.id, addon_with_previews.id])
    assert addon_without_previews.reload().current_previews.count() == 3
    assert addon_with_previews.reload().current_previews.count() == 3
    sizes = addon_without_previews.current_previews.values_list(
        'sizes', flat=True)
    assert list(sizes) == [
        {'image': list(amo.THEME_PREVIEW_SIZES['header']['full']),
         'thumbnail': list(amo.THEME_PREVIEW_SIZES['header']['thumbnail'])},
        {'image': list(amo.THEME_PREVIEW_SIZES['list']['full']),
         'thumbnail': list(amo.THEME_PREVIEW_SIZES['list']['thumbnail'])},
        {'image': list(amo.THEME_PREVIEW_SIZES['single']['full']),
         'thumbnail': list(amo.THEME_PREVIEW_SIZES['single']['thumbnail'])}]
Beispiel #14
0
    def from_upload(cls,
                    upload,
                    version,
                    platform,
                    is_beta=False,
                    parsed_data=None):
        if parsed_data is None:
            parsed_data = {}
        addon = version.addon

        file_ = cls(version=version, platform=platform)
        upload.path = force_bytes(nfd_str(upload.path))
        ext = os.path.splitext(upload.path)[1]
        if ext == '.jar':
            ext = '.xpi'
        file_.filename = file_.generate_filename(extension=ext or '.xpi')
        # Size in bytes.
        file_.size = storage.size(upload.path)
        data = cls.get_jetpack_metadata(upload.path)
        if 'sdkVersion' in data and data['sdkVersion']:
            file_.jetpack_version = data['sdkVersion'][:10]
        file_.no_restart = parsed_data.get('no_restart', False)
        file_.strict_compatibility = parsed_data.get('strict_compatibility',
                                                     False)
        file_.is_multi_package = parsed_data.get('is_multi_package', False)
        file_.is_experiment = parsed_data.get('is_experiment', False)
        file_.is_webextension = parsed_data.get('is_webextension', False)

        if (is_beta and addon.status == amo.STATUS_PUBLIC
                and version.channel == amo.RELEASE_CHANNEL_LISTED):
            file_.status = amo.STATUS_BETA

        file_.hash = file_.generate_hash(upload.path)
        file_.original_hash = file_.hash

        if upload.validation:
            validation = json.loads(upload.validation)
            if validation['metadata'].get('requires_chrome'):
                file_.requires_chrome = True

        file_.save()
        if file_.is_webextension:
            permissions = list(parsed_data.get('permissions', []))
            # Add content_scripts host matches too.
            for script in parsed_data.get('content_scripts', []):
                permissions.extend(script.get('matches', []))
            if permissions:
                WebextPermission.objects.create(permissions=permissions,
                                                file=file_)

        log.debug('New file: %r from %r' % (file_, upload))
        # Move the uploaded file from the temp location.
        copy_stored_file(
            upload.path,
            os.path.join(version.path_prefix, nfd_str(file_.filename)))

        if upload.validation:
            FileValidation.from_json(file_, validation)

        return file_
Beispiel #15
0
    def from_upload(cls, upload, version, platform, parsed_data=None):
        """
        Create a File instance from a FileUpload, a Version, a platform id
        and the parsed_data generated by parse_addon().

        Note that it's the caller's responsability to ensure the file is valid.
        We can't check for that here because an admin may have overridden the
        validation results."""
        assert parsed_data is not None

        file_ = cls(version=version, platform=platform)
        upload.path = force_bytes(nfd_str(upload.path))
        ext = os.path.splitext(upload.path)[1]
        if ext == '.jar':
            ext = '.xpi'
        file_.filename = file_.generate_filename(extension=ext or '.xpi')
        # Size in bytes.
        file_.size = storage.size(upload.path)
        data = cls.get_jetpack_metadata(upload.path)
        if 'sdkVersion' in data and data['sdkVersion']:
            file_.jetpack_version = data['sdkVersion'][:10]
        file_.is_restart_required = parsed_data.get(
            'is_restart_required', False)
        file_.strict_compatibility = parsed_data.get(
            'strict_compatibility', False)
        file_.is_multi_package = parsed_data.get('is_multi_package', False)
        file_.is_experiment = parsed_data.get('is_experiment', False)
        file_.is_webextension = parsed_data.get('is_webextension', False)
        file_.is_mozilla_signed_extension = parsed_data.get(
            'is_mozilla_signed_extension', False)

        file_.hash = file_.generate_hash(upload.path)
        file_.original_hash = file_.hash

        if upload.validation:
            validation = json.loads(upload.validation)
            if validation['metadata'].get('requires_chrome'):
                file_.requires_chrome = True

        file_.save()
        if file_.is_webextension:
            permissions = list(parsed_data.get('permissions', []))
            # Add content_scripts host matches too.
            for script in parsed_data.get('content_scripts', []):
                permissions.extend(script.get('matches', []))
            if permissions:
                WebextPermission.objects.create(permissions=permissions,
                                                file=file_)

        log.debug('New file: %r from %r' % (file_, upload))
        # Move the uploaded file from the temp location.
        copy_stored_file(
            upload.path,
            os.path.join(version.path_prefix, nfd_str(file_.filename)))

        if upload.validation:
            FileValidation.from_json(file_, validation)

        return file_
Beispiel #16
0
    def from_upload(cls, upload, version, platform, parsed_data=None):
        """
        Create a File instance from a FileUpload, a Version, a platform id
        and the parsed_data generated by parse_addon().

        Note that it's the caller's responsability to ensure the file is valid.
        We can't check for that here because an admin may have overridden the
        validation results."""
        assert parsed_data is not None

        file_ = cls(version=version, platform=platform)
        upload.path = force_bytes(nfd_str(upload.path))
        ext = os.path.splitext(upload.path)[1]
        if ext == '.jar':
            ext = '.xpi'
        file_.filename = file_.generate_filename(extension=ext or '.xpi')
        # Size in bytes.
        file_.size = storage.size(upload.path)
        data = cls.get_jetpack_metadata(upload.path)
        if 'sdkVersion' in data and data['sdkVersion']:
            file_.jetpack_version = data['sdkVersion'][:10]
        file_.is_restart_required = parsed_data.get('is_restart_required',
                                                    False)
        file_.strict_compatibility = parsed_data.get('strict_compatibility',
                                                     False)
        file_.is_multi_package = parsed_data.get('is_multi_package', False)
        file_.is_experiment = parsed_data.get('is_experiment', False)
        file_.is_webextension = parsed_data.get('is_webextension', False)
        file_.is_mozilla_signed_extension = parsed_data.get(
            'is_mozilla_signed_extension', False)

        file_.hash = file_.generate_hash(upload.path)
        file_.original_hash = file_.hash

        if upload.validation:
            validation = json.loads(upload.validation)
            if validation['metadata'].get('requires_chrome'):
                file_.requires_chrome = True

        file_.save()
        if file_.is_webextension:
            permissions = list(parsed_data.get('permissions', []))
            # Add content_scripts host matches too.
            for script in parsed_data.get('content_scripts', []):
                permissions.extend(script.get('matches', []))
            if permissions:
                WebextPermission.objects.create(permissions=permissions,
                                                file=file_)

        log.debug('New file: %r from %r' % (file_, upload))
        # Move the uploaded file from the temp location.
        copy_stored_file(
            upload.path,
            os.path.join(version.path_prefix, nfd_str(file_.filename)))

        if upload.validation:
            FileValidation.from_json(file_, validation)

        return file_
Beispiel #17
0
    def from_upload(cls, upload, version, platform, is_beta=False,
                    parsed_data=None):
        if parsed_data is None:
            parsed_data = {}
        addon = version.addon

        file_ = cls(version=version, platform=platform)
        upload.path = force_bytes(nfd_str(upload.path))
        ext = os.path.splitext(upload.path)[1]
        if ext == '.jar':
            ext = '.xpi'
        file_.filename = file_.generate_filename(extension=ext or '.xpi')
        # Size in bytes.
        file_.size = storage.size(upload.path)
        data = cls.get_jetpack_metadata(upload.path)
        if 'sdkVersion' in data and data['sdkVersion']:
            file_.jetpack_version = data['sdkVersion'][:10]
        file_.is_restart_required = parsed_data.get(
            'is_restart_required', False)
        file_.strict_compatibility = parsed_data.get(
            'strict_compatibility', False)
        file_.is_multi_package = parsed_data.get('is_multi_package', False)
        file_.is_experiment = parsed_data.get('is_experiment', False)
        file_.is_webextension = parsed_data.get('is_webextension', False)
        file_.is_mozilla_signed_extension = parsed_data.get(
            'is_mozilla_signed_extension', False)

        if (is_beta and addon.status == amo.STATUS_PUBLIC and
                version.channel == amo.RELEASE_CHANNEL_LISTED):
            file_.status = amo.STATUS_BETA

        file_.hash = file_.generate_hash(upload.path)
        file_.original_hash = file_.hash

        if upload.validation:
            validation = json.loads(upload.validation)
            if validation['metadata'].get('requires_chrome'):
                file_.requires_chrome = True

        file_.save()
        if file_.is_webextension:
            permissions = list(parsed_data.get('permissions', []))
            # Add content_scripts host matches too.
            for script in parsed_data.get('content_scripts', []):
                permissions.extend(script.get('matches', []))
            if permissions:
                WebextPermission.objects.create(permissions=permissions,
                                                file=file_)

        log.debug('New file: %r from %r' % (file_, upload))
        # Move the uploaded file from the temp location.
        copy_stored_file(
            upload.path,
            os.path.join(version.path_prefix, nfd_str(file_.filename)))

        if upload.validation:
            FileValidation.from_json(file_, validation)

        return file_
Beispiel #18
0
    def from_upload(cls, upload, version, platform, is_beta=False,
                    parse_data={}):
        addon = version.addon

        file_ = cls(version=version, platform=platform)
        upload.path = smart_path(nfd_str(upload.path))
        ext = os.path.splitext(upload.path)[1]
        if ext == '.jar':
            ext = '.xpi'
        file_.filename = file_.generate_filename(extension=ext or '.xpi')
        # Size in bytes.
        file_.size = storage.size(upload.path)
        data = cls.get_jetpack_metadata(upload.path)
        if 'sdkVersion' in data and data['sdkVersion']:
            file_.jetpack_version = data['sdkVersion'][:10]
        if file_.jetpack_version:
            Tag(tag_text='jetpack').save_tag(addon)
        file_.no_restart = parse_data.get('no_restart', False)
        file_.strict_compatibility = parse_data.get('strict_compatibility',
                                                    False)
        file_.is_multi_package = parse_data.get('is_multi_package', False)
        file_.is_experiment = parse_data.get('is_experiment', False)
        file_.is_webextension = parse_data.get('is_webextension', False)

        if is_beta and addon.status == amo.STATUS_PUBLIC:
            file_.status = amo.STATUS_BETA

        file_.hash = file_.generate_hash(upload.path)
        file_.original_hash = file_.hash

        if upload.validation:
            validation = json.loads(upload.validation)
            if validation['metadata'].get('requires_chrome'):
                file_.requires_chrome = True

        file_.save()

        log.debug('New file: %r from %r' % (file_, upload))
        # Move the uploaded file from the temp location.
        destinations = [version.path_prefix]
        if file_.status in amo.MIRROR_STATUSES:
            destinations.append(version.mirror_path_prefix)
        for dest in destinations:
            copy_stored_file(upload.path,
                             os.path.join(dest, nfd_str(file_.filename)))

        if upload.validation:
            # Import loop.
            from olympia.devhub.tasks import annotate_validation_results
            from olympia.devhub.utils import ValidationAnnotator

            validation = annotate_validation_results(validation)
            FileValidation.from_json(file_, validation)

            # Copy annotations from any previously approved file.
            ValidationAnnotator(file_).update_annotations()

        return file_
Beispiel #19
0
    def from_upload(cls, upload, version, platform, is_beta=False,
                    parsed_data=None):
        if parsed_data is None:
            parsed_data = {}
        addon = version.addon

        file_ = cls(version=version, platform=platform)
        upload.path = force_bytes(nfd_str(upload.path))
        ext = os.path.splitext(upload.path)[1]
        if ext == '.jar':
            ext = '.xpi'
        file_.filename = file_.generate_filename(extension=ext or '.xpi')
        # Size in bytes.
        file_.size = storage.size(upload.path)
        data = cls.get_jetpack_metadata(upload.path)
        if 'sdkVersion' in data and data['sdkVersion']:
            file_.jetpack_version = data['sdkVersion'][:10]
        file_.no_restart = parsed_data.get('no_restart', False)
        file_.strict_compatibility = parsed_data.get('strict_compatibility',
                                                     False)
        file_.is_multi_package = parsed_data.get('is_multi_package', False)
        file_.is_experiment = parsed_data.get('is_experiment', False)
        file_.is_webextension = parsed_data.get('is_webextension', False)

        if (is_beta and addon.status == amo.STATUS_PUBLIC and
                version.channel == amo.RELEASE_CHANNEL_LISTED):
            file_.status = amo.STATUS_BETA

        file_.hash = file_.generate_hash(upload.path)
        file_.original_hash = file_.hash

        if upload.validation:
            validation = json.loads(upload.validation)
            if validation['metadata'].get('requires_chrome'):
                file_.requires_chrome = True

        file_.save()

        log.debug('New file: %r from %r' % (file_, upload))
        # Move the uploaded file from the temp location.
        copy_stored_file(
            upload.path,
            os.path.join(version.path_prefix, nfd_str(file_.filename)))

        if upload.validation:
            # Import loop.
            from olympia.devhub.tasks import annotate_validation_results
            from olympia.devhub.utils import ValidationAnnotator

            validation = annotate_validation_results(validation)
            FileValidation.from_json(file_, validation)

            # Copy annotations from any previously approved file.
            ValidationAnnotator(file_).update_annotations()

        return file_
Beispiel #20
0
    def save_model(self, request, obj, form, change):
        super().save_model(request, obj, form, change)

        size_thumb = (150, 120)
        size_full = (960, 640)

        with tempfile.NamedTemporaryFile(dir=settings.TMP_PATH) as tmp:
            resize_image(obj.custom_image.path, tmp.name, size_thumb, 'jpg')
            copy_stored_file(tmp.name, obj.thumbnail_path)

        with tempfile.NamedTemporaryFile(dir=settings.TMP_PATH) as tmp:
            resize_image(obj.custom_image.path, tmp.name, size_full, 'jpg')
            copy_stored_file(tmp.name, obj.custom_image.path)
Beispiel #21
0
 def unhide_disabled_file(self):
     if not self.filename:
         return
     src, dst = self.guarded_file_path, self.file_path
     self.mv(src, dst, 'Moving undisabled file: %s => %s')
     # Put files back on the mirrors if necessary.
     if storage.exists(self.file_path):
         destinations = [self.version.path_prefix]
         if self.status in amo.MIRROR_STATUSES:
             destinations.append(self.version.mirror_path_prefix)
         for dest in destinations:
             dest = os.path.join(dest, nfd_str(self.filename))
             log.info('Re-mirroring disabled/enabled file to %s' % dest)
             copy_stored_file(self.file_path, dest)
Beispiel #22
0
def file_factory(**kw):
    version = kw['version']
    filename = kw.pop('filename', '%s-%s.xpi' % (version.addon_id, version.id))
    status = kw.pop('status', amo.STATUS_APPROVED)

    file_ = File.objects.create(filename=filename, status=status, **kw)

    fixture_path = os.path.join(settings.ROOT,
                                'src/olympia/files/fixtures/files', filename)

    if os.path.exists(fixture_path):
        copy_stored_file(fixture_path, file_.current_file_path)

    return file_
Beispiel #23
0
 def unhide_disabled_file(self):
     if not self.filename:
         return
     src, dst = self.guarded_file_path, self.file_path
     self.mv(src, dst, 'Moving undisabled file: %s => %s')
     # Put files back on the mirrors if necessary.
     if storage.exists(self.file_path):
         destinations = [self.version.path_prefix]
         if self.status in amo.MIRROR_STATUSES:
             destinations.append(self.version.mirror_path_prefix)
         for dest in destinations:
             dest = os.path.join(dest, nfd_str(self.filename))
             log.info('Re-mirroring disabled/enabled file to %s' % dest)
             copy_stored_file(self.file_path, dest)
Beispiel #24
0
    def from_upload(cls, upload, version, platform, parsed_data=None):
        """
        Create a File instance from a FileUpload, a Version, a platform id
        and the parsed_data generated by parse_addon().

        Note that it's the caller's responsability to ensure the file is valid.
        We can't check for that here because an admin may have overridden the
        validation results."""
        assert parsed_data is not None

        file_ = cls(version=version, platform=platform)
        upload_path = force_text(nfd_str(upload.path))
        ext = force_text(os.path.splitext(upload_path)[1])
        file_.filename = file_.generate_filename(extension=ext or '.xpi')
        # Size in bytes.
        file_.size = storage.size(upload_path)
        file_.is_restart_required = parsed_data.get(
            'is_restart_required', False)
        file_.strict_compatibility = parsed_data.get(
            'strict_compatibility', False)
        file_.is_experiment = parsed_data.get('is_experiment', False)
        file_.is_webextension = parsed_data.get('is_webextension', False)
        file_.is_mozilla_signed_extension = parsed_data.get(
            'is_mozilla_signed_extension', False)

        file_.hash = file_.generate_hash(upload_path)
        file_.original_hash = file_.hash
        file_.save()

        if file_.is_webextension:
            permissions = list(parsed_data.get('permissions', []))
            # Add content_scripts host matches too.
            for script in parsed_data.get('content_scripts', []):
                permissions.extend(script.get('matches', []))
            if permissions:
                WebextPermission.objects.create(permissions=permissions,
                                                file=file_)

        log.info('New file: %r from %r' % (file_, upload))

        # Move the uploaded file from the temp location.
        copy_stored_file(upload_path, file_.current_file_path)

        if upload.validation:
            validation = json.loads(upload.validation)
            FileValidation.from_json(file_, validation)

        return file_
Beispiel #25
0
    def copy_to_mirror(self):
        if not self.filename:
            return
        try:
            if storage.exists(self.file_path):
                dst = self.mirror_file_path
                if not dst:
                    return

                log.info('Moving file to mirror: %s => %s'
                         % (self.file_path, dst))
                copy_stored_file(self.file_path, dst)
        except UnicodeEncodeError:
            log.info('Copy Failure: %s %s %s' %
                     (self.id, smart_str(self.filename),
                      smart_str(self.file_path)))
Beispiel #26
0
    def copy_to_mirror(self):
        if not self.filename:
            return
        try:
            if storage.exists(self.file_path):
                dst = self.mirror_file_path
                if not dst:
                    return

                log.info('Moving file to mirror: %s => %s' %
                         (self.file_path, dst))
                copy_stored_file(self.file_path, dst)
        except UnicodeEncodeError:
            log.info(
                'Copy Failure: %s %s %s' %
                (self.id, smart_str(self.filename), smart_str(self.file_path)))
Beispiel #27
0
def file_factory(**kw):
    version = kw['version']
    filename = kw.pop('filename', '%s-%s' % (version.addon_id, version.id))
    status = kw.pop('status', amo.STATUS_PUBLIC)
    platform = kw.pop('platform', amo.PLATFORM_ALL.id)

    file_ = File.objects.create(
        filename=filename, platform=platform, status=status, **kw)

    fixture_path = os.path.join(
        settings.ROOT, 'src/olympia/files/fixtures/files',
        filename)

    if os.path.exists(fixture_path):
        copy_stored_file(fixture_path, file_.current_file_path)

    return file_
Beispiel #28
0
def file_factory(**kw):
    version = kw['version']
    filename = kw.pop('filename', '%s-%s.xpi' % (version.addon_id, version.id))
    status = kw.pop('status', amo.STATUS_APPROVED)
    platform = kw.pop('platform', amo.PLATFORM_ALL.id)

    file_ = File.objects.create(
        filename=filename, platform=platform, status=status, **kw)

    fixture_path = os.path.join(
        settings.ROOT, 'src/olympia/files/fixtures/files',
        filename)

    if os.path.exists(fixture_path):
        copy_stored_file(fixture_path, file_.current_file_path)

    return file_
def test_extract_theme_properties():
    addon = addon_factory(type=amo.ADDON_STATICTHEME)
    result = utils.extract_theme_properties(addon,
                                            addon.current_version.channel)
    assert result == {}  # There's no file, but it be should safely handled.

    # Add the zip in the right place
    zip_file = os.path.join(
        settings.ROOT, 'src/olympia/devhub/tests/addons/static_theme.zip')
    copy_stored_file(zip_file, addon.current_version.all_files[0].file_path)
    result = utils.extract_theme_properties(addon,
                                            addon.current_version.channel)
    assert result['colors'] == {"accentcolor": "#adb09f", "textcolor": "#000"}
    assert result['images'] == {
        "headerURL":
        '%s%s//%s/%s/%s' % (settings.MEDIA_URL, 'addons', text_type(
            addon.id), text_type(addon.current_version.id), 'weta.png')
    }
Beispiel #30
0
def test_extract_theme_properties():
    addon = addon_factory(type=amo.ADDON_STATICTHEME)
    result = utils.extract_theme_properties(
        addon, addon.current_version.channel)
    assert result == {}  # There's no file, but it be should safely handled.

    # Add the zip in the right place
    zip_file = os.path.join(
        settings.ROOT, 'src/olympia/devhub/tests/addons/static_theme.zip')
    copy_stored_file(zip_file, addon.current_version.all_files[0].file_path)
    result = utils.extract_theme_properties(
        addon, addon.current_version.channel)
    assert result == {
        "colors": {
            "accentcolor": "#adb09f",
            "textcolor": "#000"
        },
        "images": {
            "headerURL": "weta.png"
        }
    }
Beispiel #31
0
def approve_rereview(theme):
    """Replace original theme with pending theme on filesystem."""
    # If reuploaded theme, replace old theme design.
    storage = LocalFileStorage()
    rereview = theme.rereviewqueuetheme_set.all()
    reupload = rereview[0]

    if reupload.header_path != reupload.theme.header_path:
        create_persona_preview_images(
            src=reupload.header_path,
            full_dst=[
                reupload.theme.thumb_path,
                reupload.theme.icon_path],
            set_modified_on=[reupload.theme.addon])

        if not reupload.theme.is_new():
            # Legacy themes also need a preview_large.jpg.
            # Modern themes use preview.png for both thumb and preview so there
            # is no problem there.
            copy_stored_file(reupload.theme.thumb_path,
                             reupload.theme.preview_path, storage=storage)

        move_stored_file(
            reupload.header_path, reupload.theme.header_path, storage=storage)

    theme = reupload.theme
    footer_path = theme.footer_path
    if reupload.footer_path != footer_path:
        if not footer_path:
            dst_root = os.path.join(user_media_path('addons'),
                                    str(theme.addon.id))
            footer_path = os.path.join(dst_root, 'footer.png')
            theme.footer = 'footer.png'
            theme.save()

        move_stored_file(
            reupload.footer_path, footer_path, storage=storage)
    rereview.delete()

    theme.addon.increment_theme_version_number()
Beispiel #32
0
def approve_rereview(theme):
    """Replace original theme with pending theme on filesystem."""
    # If reuploaded theme, replace old theme design.
    storage = LocalFileStorage()
    rereview = theme.rereviewqueuetheme_set.all()
    reupload = rereview[0]

    if reupload.header_path != reupload.theme.header_path:
        create_persona_preview_images(
            src=reupload.header_path,
            full_dst=[
                reupload.theme.thumb_path,
                reupload.theme.icon_path],
            set_modified_on=[reupload.theme.addon])

        if not reupload.theme.is_new():
            # Legacy themes also need a preview_large.jpg.
            # Modern themes use preview.png for both thumb and preview so there
            # is no problem there.
            copy_stored_file(reupload.theme.thumb_path,
                             reupload.theme.preview_path, storage=storage)

        move_stored_file(
            reupload.header_path, reupload.theme.header_path, storage=storage)

    theme = reupload.theme
    footer_path = theme.footer_path
    if reupload.footer_path != footer_path:
        if not footer_path:
            dst_root = os.path.join(user_media_path('addons'),
                                    str(theme.addon.id))
            footer_path = os.path.join(dst_root, 'footer.png')
            theme.footer = 'footer.png'
            theme.save()

        move_stored_file(
            reupload.footer_path, footer_path, storage=storage)
    rereview.delete()

    theme.addon.increment_theme_version_number()
 def test_copy_chunking(self):
     src = self.newfile('src.txt', '<contents>')
     dest = self.path('somedir/dest.txt')
     copy_stored_file(src, dest, chunk_size=1)
     assert self.contents(dest) == '<contents>'
 def test_non_ascii(self):
     src = self.newfile(u'kristi\u0107.txt',
                        u'ivan kristi\u0107'.encode('utf8'))
     dest = self.path(u'somedir/kristi\u0107.txt')
     copy_stored_file(src, dest)
     assert self.contents(dest) == 'ivan kristi\xc4\x87'
 def test_self_copy(self):
     src = self.newfile('src.txt', '<contents>')
     dest = self.path('src.txt')
     copy_stored_file(src, dest)
     assert self.contents(dest) == '<contents>'
Beispiel #36
0
 def test_copy(self):
     src = self.newfile('src.txt', u'<contents>')
     dest = self.path('somedir/dest.txt')
     copy_stored_file(src, dest)
     assert self.contents(dest) == b'<contents>'
 def test_copy_chunking(self):
     src = self.newfile("src.txt", "<contents>")
     dest = self.path("somedir/dest.txt")
     copy_stored_file(src, dest, chunk_size=1)
     eq_(self.contents(dest), "<contents>")
Beispiel #38
0
def test_generate_static_theme_preview_with_chrome_properties(
        write_svg_to_png_mock, resize_image_mock, pngcrush_image_mock,
        extract_colors_from_image_mock, index_addons_mock):
    write_svg_to_png_mock.return_value = True
    extract_colors_from_image_mock.return_value = [{
        'h': 9,
        's': 8,
        'l': 7,
        'ratio': 0.6
    }]
    theme_manifest = {
        "images": {
            "theme_frame": "transparent.gif"
        },
        "colors": {
            "frame": [123, 45, 67],  # 'accentcolor'
            "tab_background_text": [9, 87, 65],  # 'textcolor'
            "bookmark_text": [0, 0, 0],  # 'toolbar_text'
        }
    }
    addon = addon_factory()
    destination = addon.current_version.all_files[0].current_file_path
    zip_file = os.path.join(HEADER_ROOT, 'theme_images.zip')
    copy_stored_file(zip_file, destination)
    generate_static_theme_preview(theme_manifest, addon.current_version.pk)

    assert resize_image_mock.call_count == 3
    assert write_svg_to_png_mock.call_count == 3
    assert pngcrush_image_mock.call_count == 3

    # First check the header Preview is good
    header_preview = VersionPreview.objects.get(
        version=addon.current_version,
        position=amo.THEME_PREVIEW_SIZES['header']['position'])
    check_preview(header_preview, amo.THEME_PREVIEW_SIZES['header'],
                  write_svg_to_png_mock.call_args_list[0][0],
                  resize_image_mock.call_args_list[0][0],
                  pngcrush_image_mock.call_args_list[0][0])

    # Then the list Preview
    list_preview = VersionPreview.objects.get(
        version=addon.current_version,
        position=amo.THEME_PREVIEW_SIZES['list']['position'])
    check_preview(list_preview, amo.THEME_PREVIEW_SIZES['list'],
                  write_svg_to_png_mock.call_args_list[1][0],
                  resize_image_mock.call_args_list[1][0],
                  pngcrush_image_mock.call_args_list[1][0])

    # And finally the new single Preview
    single_preview = VersionPreview.objects.get(
        version=addon.current_version,
        position=amo.THEME_PREVIEW_SIZES['single']['position'])
    check_preview(single_preview, amo.THEME_PREVIEW_SIZES['single'],
                  write_svg_to_png_mock.call_args_list[2][0],
                  resize_image_mock.call_args_list[2][0],
                  pngcrush_image_mock.call_args_list[2][0])

    colors = []
    # check each of our colors above was converted to css codes
    chrome_colors = {
        'bookmark_text': 'toolbar_text',
        'frame': 'accentcolor',
        'tab_background_text': 'textcolor',
    }
    for (chrome_prop, firefox_prop) in chrome_colors.items():
        color_list = theme_manifest['colors'][chrome_prop]
        color = 'rgb(%s,%s,%s)' % tuple(color_list)
        colors.append('class="%s" fill="%s"' % (firefox_prop, color))

    header_svg = write_svg_to_png_mock.call_args_list[0][0][0]
    list_svg = write_svg_to_png_mock.call_args_list[1][0][0]
    single_svg = write_svg_to_png_mock.call_args_list[2][0][0]
    check_render(force_text(header_svg), 'transparent.gif', 1, 'xMaxYMin meet',
                 'image/gif', True, colors, 680, 92, 680)
    check_render(force_text(list_svg), 'transparent.gif', 1, 'xMaxYMin meet',
                 'image/gif', True, colors, 760, 92, 760)
    check_render(force_text(single_svg), 'transparent.gif', 1, 'xMaxYMin meet',
                 'image/gif', True, colors, 720, 92, 720)
Beispiel #39
0
def test_generate_preview_with_additional_backgrounds(
    convert_svg_to_png_mock,
    write_svg_to_png_mock,
    resize_image_mock,
    pngcrush_image_mock,
    extract_colors_from_image_mock,
    index_addons_mock,
):
    write_svg_to_png_mock.side_effect = write_empty_png
    convert_svg_to_png_mock.return_value = True
    extract_colors_from_image_mock.return_value = [{
        'h': 9,
        's': 8,
        'l': 7,
        'ratio': 0.6
    }]

    theme_manifest = {
        'images': {
            'theme_frame': 'empty.png',
            'additional_backgrounds': ['weta_for_tiling.png'],
        },
        'colors': {
            'textcolor': '#123456',
            # Just textcolor, to test the template defaults and fallbacks.
        },
        'properties': {
            'additional_backgrounds_alignment': ['top'],
            'additional_backgrounds_tiling': ['repeat-x'],
        },
    }
    addon = addon_factory()
    destination = addon.current_version.all_files[0].current_file_path
    zip_file = os.path.join(
        settings.ROOT,
        'src/olympia/devhub/tests/addons/static_theme_tiled.zip')
    copy_stored_file(zip_file, destination)
    generate_static_theme_preview(theme_manifest, addon.current_version.pk)

    # for svg preview we write the svg twice, 1st with write_svg, later with convert_svg
    assert resize_image_mock.call_count == 2
    assert write_svg_to_png_mock.call_count == 2
    assert convert_svg_to_png_mock.call_count == 1
    assert pngcrush_image_mock.call_count == 1

    # First check the firefox Preview is good
    firefox_preview = VersionPreview.objects.get(
        version=addon.current_version,
        position=amo.THEME_PREVIEW_RENDERINGS['firefox']['position'],
    )
    check_preview(
        firefox_preview,
        amo.THEME_PREVIEW_RENDERINGS['firefox'],
    )
    assert write_svg_to_png_mock.call_args_list[0][0][
        1] == firefox_preview.image_path
    check_thumbnail(
        firefox_preview,
        amo.THEME_PREVIEW_RENDERINGS['firefox'],
        firefox_preview.image_path,
        resize_image_mock.call_args_list[0],
        pngcrush_image_mock.call_args_list[0][0],
    )

    # And then the Preview used on AMO
    amo_preview = VersionPreview.objects.get(
        version=addon.current_version,
        position=amo.THEME_PREVIEW_RENDERINGS['amo']['position'],
    )
    check_preview(
        amo_preview,
        amo.THEME_PREVIEW_RENDERINGS['amo'],
    )
    assert convert_svg_to_png_mock.call_args_list[0][0][
        0] == amo_preview.image_path
    check_thumbnail(
        amo_preview,
        amo.THEME_PREVIEW_RENDERINGS['amo'],
        convert_svg_to_png_mock.call_args_list[0][0][1],
        resize_image_mock.call_args_list[1],
    )

    # These defaults are mostly defined in the xml template
    default_colors = (
        ('frame', 'fill',
         'rgba(229,230,232,1)'),  # amo.THEME_FRAME_COLOR_DEFAULT
        ('tab_background_text', 'fill',
         '#123456'),  # the only one defined in manifest
        ('bookmark_text', 'fill',
         '#123456'),  # should default to tab_background_text
        ('toolbar_field', 'fill', 'rgba(255,255,255,1)'),
        ('toolbar_field_text', 'fill', ''),
        ('tab_line', 'stroke', 'rgba(0,0,0,0.25)'),
        ('tab_selected toolbar', 'fill', 'rgba(255,255,255,0.6)'),
    )
    colors = [
        f'class="{key} {prop}" {prop}="{color}"'
        for (key, prop, color) in default_colors
    ]

    firefox_svg = write_svg_to_png_mock.call_args_list[0][0][0]
    interim_amo_svg = write_svg_to_png_mock.call_args_list[1][0][0]
    with open(amo_preview.image_path) as svg:
        amo_svg = svg.read()
    check_render_additional(force_str(firefox_svg), 680, colors)
    check_render_additional(force_str(interim_amo_svg), 720,
                            transparent_colors)
    check_render(
        force_str(amo_svg),
        'empty.jpg',
        92,
        'xMaxYMin slice',
        'image/jpeg',
        True,
        colors,
        720,
        92,
        720,
    )

    index_addons_mock.assert_called_with([addon.id])
 def test_self_copy(self):
     src = self.newfile("src.txt", "<contents>")
     dest = self.path("src.txt")
     copy_stored_file(src, dest)
     eq_(self.contents(dest), "<contents>")
Beispiel #41
0
def test_generate_preview_with_additional_backgrounds(
        write_svg_to_png_mock, resize_image_mock, pngcrush_image_mock,
        extract_colors_from_image_mock, index_addons_mock):
    write_svg_to_png_mock.return_value = True
    extract_colors_from_image_mock.return_value = [{
        'h': 9,
        's': 8,
        'l': 7,
        'ratio': 0.6
    }]

    theme_manifest = {
        "images": {
            "theme_frame": "empty.png",
            "additional_backgrounds": ["weta_for_tiling.png"],
        },
        "colors": {
            "textcolor": "#123456",
            # Just textcolor, to test the template defaults and fallbacks.
        },
        "properties": {
            "additional_backgrounds_alignment": ["top"],
            "additional_backgrounds_tiling": ["repeat-x"],
        },
    }
    addon = addon_factory()
    destination = addon.current_version.all_files[0].current_file_path
    zip_file = os.path.join(
        settings.ROOT,
        'src/olympia/devhub/tests/addons/static_theme_tiled.zip')
    copy_stored_file(zip_file, destination)
    generate_static_theme_preview(theme_manifest, addon.current_version.pk)

    assert resize_image_mock.call_count == 3
    assert write_svg_to_png_mock.call_count == 3
    assert pngcrush_image_mock.call_count == 3

    # First check the header Preview is good
    header_preview = VersionPreview.objects.get(
        version=addon.current_version,
        position=amo.THEME_PREVIEW_SIZES['header']['position'])
    check_preview(header_preview, amo.THEME_PREVIEW_SIZES['header'],
                  write_svg_to_png_mock.call_args_list[0][0],
                  resize_image_mock.call_args_list[0][0],
                  pngcrush_image_mock.call_args_list[0][0])

    # Then the list Preview
    list_preview = VersionPreview.objects.get(
        version=addon.current_version,
        position=amo.THEME_PREVIEW_SIZES['list']['position'])
    check_preview(list_preview, amo.THEME_PREVIEW_SIZES['list'],
                  write_svg_to_png_mock.call_args_list[1][0],
                  resize_image_mock.call_args_list[1][0],
                  pngcrush_image_mock.call_args_list[1][0])

    # And finally the new single Preview
    single_preview = VersionPreview.objects.get(
        version=addon.current_version,
        position=amo.THEME_PREVIEW_SIZES['single']['position'])
    check_preview(single_preview, amo.THEME_PREVIEW_SIZES['single'],
                  write_svg_to_png_mock.call_args_list[2][0],
                  resize_image_mock.call_args_list[2][0],
                  pngcrush_image_mock.call_args_list[2][0])

    # These defaults are mostly defined in the xml template
    default_colors = {
        "frame": "rgba(229,230,232,1)",  # amo.THEME_FRAME_COLOR_DEFAULT
        "tab_background_text": "#123456",  # the only one defined in 'manifest'
        "bookmark_text": "#123456",  # should default to tab_background_text
        "toolbar_field": "rgba(255,255,255,1)",
        "toolbar_field_text": "",
        "tab_line": "rgba(0,0,0,0.25)",
        "tab_selected": "rgba(0,0,0,0)",
    }
    colors = [
        'class="%s" fill="%s"' % (key, color)
        for (key, color) in default_colors.items()
    ]

    header_svg = write_svg_to_png_mock.call_args_list[0][0][0]
    list_svg = write_svg_to_png_mock.call_args_list[1][0][0]
    single_svg = write_svg_to_png_mock.call_args_list[2][0][0]
    check_render_additional(force_text(header_svg), 680, colors)
    check_render_additional(force_text(list_svg), 760, colors)
    check_render_additional(force_text(single_svg), 720, colors)

    index_addons_mock.assert_called_with([addon.id])
Beispiel #42
0
    def from_upload(cls,
                    upload,
                    version,
                    platform,
                    is_beta=False,
                    parse_data={}):
        addon = version.addon

        file_ = cls(version=version, platform=platform)
        upload.path = smart_path(nfd_str(upload.path))
        ext = os.path.splitext(upload.path)[1]
        if ext == '.jar':
            ext = '.xpi'
        file_.filename = file_.generate_filename(extension=ext or '.xpi')
        # Size in bytes.
        file_.size = storage.size(upload.path)
        data = cls.get_jetpack_metadata(upload.path)
        if 'sdkVersion' in data and data['sdkVersion']:
            file_.jetpack_version = data['sdkVersion'][:10]
        if file_.jetpack_version:
            Tag(tag_text='jetpack').save_tag(addon)
        file_.no_restart = parse_data.get('no_restart', False)
        file_.strict_compatibility = parse_data.get('strict_compatibility',
                                                    False)
        file_.is_multi_package = parse_data.get('is_multi_package', False)
        file_.is_experiment = parse_data.get('is_experiment', False)
        file_.is_webextension = parse_data.get('is_webextension', False)

        if is_beta and addon.status == amo.STATUS_PUBLIC:
            file_.status = amo.STATUS_BETA
        elif addon.trusted:
            # New files in trusted add-ons automatically receive the correct
            # approved status for their review class.
            if addon.status == amo.STATUS_PUBLIC:
                file_.status = amo.STATUS_PUBLIC
            elif addon.status in amo.LITE_STATUSES:
                file_.status = amo.STATUS_LITE

        file_.hash = file_.generate_hash(upload.path)
        file_.original_hash = file_.hash

        if upload.validation:
            validation = json.loads(upload.validation)
            if validation['metadata'].get('requires_chrome'):
                file_.requires_chrome = True

        file_.save()

        log.debug('New file: %r from %r' % (file_, upload))
        # Move the uploaded file from the temp location.
        destinations = [version.path_prefix]
        if file_.status in amo.MIRROR_STATUSES:
            destinations.append(version.mirror_path_prefix)
        for dest in destinations:
            copy_stored_file(upload.path,
                             os.path.join(dest, nfd_str(file_.filename)))

        if upload.validation:
            # Import loop.
            from olympia.devhub.tasks import annotate_validation_results
            from olympia.devhub.utils import ValidationAnnotator

            validation = annotate_validation_results(validation)
            FileValidation.from_json(file_, validation)

            # Copy annotations from any previously approved file.
            ValidationAnnotator(file_).update_annotations()

        return file_
 def test_self_copy(self):
     src = self.newfile('src.txt', '<contents>')
     dest = self.path('src.txt')
     copy_stored_file(src, dest)
     assert self.contents(dest) == '<contents>'
 def test_copy_chunking(self):
     src = self.newfile('src.txt', '<contents>')
     dest = self.path('somedir/dest.txt')
     copy_stored_file(src, dest, chunk_size=1)
     assert self.contents(dest) == '<contents>'
 def test_non_ascii(self):
     src = self.newfile(u'kristi\u0107.txt',
                        u'ivan kristi\u0107'.encode('utf8'))
     dest = self.path(u'somedir/kristi\u0107.txt')
     copy_stored_file(src, dest)
     assert self.contents(dest) == 'ivan kristi\xc4\x87'
Beispiel #46
0
def test_generate_static_theme_preview_with_alternative_properties(
    convert_svg_to_png_mock,
    write_svg_to_png_mock,
    resize_image_mock,
    pngcrush_image_mock,
    extract_colors_from_image_mock,
    index_addons_mock,
    manifest_images,
    manifest_colors,
    svg_colors,
):
    write_svg_to_png_mock.side_effect = write_empty_png
    convert_svg_to_png_mock.return_value = True
    extract_colors_from_image_mock.return_value = [{
        'h': 9,
        's': 8,
        'l': 7,
        'ratio': 0.6
    }]
    theme_manifest = {
        'images': manifest_images,
        'colors': manifest_colors,
    }
    addon = addon_factory()
    destination = addon.current_version.all_files[0].current_file_path
    zip_file = os.path.join(HEADER_ROOT, 'theme_images.zip')
    copy_stored_file(zip_file, destination)
    generate_static_theme_preview(theme_manifest, addon.current_version.pk)

    # for svg preview we write the svg twice, 1st with write_svg, later with convert_svg
    assert resize_image_mock.call_count == 2
    assert write_svg_to_png_mock.call_count == 2
    assert convert_svg_to_png_mock.call_count == 1
    assert pngcrush_image_mock.call_count == 1

    # First check the firefox Preview is good
    firefox_preview = VersionPreview.objects.get(
        version=addon.current_version,
        position=amo.THEME_PREVIEW_RENDERINGS['firefox']['position'],
    )
    check_preview(
        firefox_preview,
        amo.THEME_PREVIEW_RENDERINGS['firefox'],
    )
    assert write_svg_to_png_mock.call_args_list[0][0][
        1] == firefox_preview.image_path
    check_thumbnail(
        firefox_preview,
        amo.THEME_PREVIEW_RENDERINGS['firefox'],
        firefox_preview.image_path,
        resize_image_mock.call_args_list[0],
        pngcrush_image_mock.call_args_list[0][0],
    )

    # And then the Preview used on AMO
    amo_preview = VersionPreview.objects.get(
        version=addon.current_version,
        position=amo.THEME_PREVIEW_RENDERINGS['amo']['position'],
    )
    check_preview(
        amo_preview,
        amo.THEME_PREVIEW_RENDERINGS['amo'],
    )
    assert convert_svg_to_png_mock.call_args_list[0][0][
        0] == amo_preview.image_path
    check_thumbnail(
        amo_preview,
        amo.THEME_PREVIEW_RENDERINGS['amo'],
        convert_svg_to_png_mock.call_args_list[0][0][1],
        resize_image_mock.call_args_list[1],
    )

    colors = [
        'class="%(field)s %(prop)s" %(prop)s="%(color)s"' % {
            'field': key,
            'prop': 'stroke' if key == 'tab_line' else 'fill',
            'color': color,
        } for (key, color) in svg_colors.items()
    ]

    firefox_svg = write_svg_to_png_mock.call_args_list[0][0][0]
    interim_amo_svg = write_svg_to_png_mock.call_args_list[1][0][0]
    with open(amo_preview.image_path) as svg:
        amo_svg = svg.read()
    check_render(
        force_str(firefox_svg),
        'transparent.gif',
        1,
        'xMaxYMin meet',
        'image/gif',
        True,
        colors,
        680,
        92,
        680,
    )
    check_render(
        force_str(interim_amo_svg),
        'transparent.gif',
        1,
        'xMaxYMin meet',
        'image/gif',
        True,
        transparent_colors,
        720,
        92,
        720,
    )
    check_render(
        force_str(amo_svg),
        'empty.jpg',
        92,
        'xMaxYMin slice',
        'image/jpeg',
        True,
        colors,
        720,
        92,
        720,
    )
Beispiel #47
0
 def _mock_xpi_side_effect(self, addon, destination):
     xpi_path = os.path.join(
         settings.ROOT, 'src/olympia/files/fixtures/files/dict-webext.xpi')
     copy_stored_file(xpi_path, destination)
     assert not os.path.isdir(destination)
     return mock.DEFAULT
Beispiel #48
0
def test_generate_static_theme_preview(
        write_svg_to_png_mock, resize_image_mock, pngcrush_image_mock,
        extract_colors_from_image_mock, index_addons_mock,
        header_url, header_height, preserve_aspect_ratio, mimetype, valid_img):
    write_svg_to_png_mock.return_value = True
    extract_colors_from_image_mock.return_value = [
        {'h': 9, 's': 8, 'l': 7, 'ratio': 0.6}
    ]
    theme_manifest = {
        "images": {
        },
        "colors": {
            "frame": "#918e43",
            "tab_background_text": "#3deb60",
            "bookmark_text": "#b5ba5b",
            "toolbar_field": "#cc29cc",
            "toolbar_field_text": "#17747d",
            "tab_line": "#00db12",
            "tab_selected": "#40df39",
        }
    }
    if header_url is not None:
        theme_manifest['images']['theme_frame'] = header_url
    addon = addon_factory()
    destination = addon.current_version.all_files[0].current_file_path
    zip_file = os.path.join(HEADER_ROOT, 'theme_images.zip')
    copy_stored_file(zip_file, destination)
    generate_static_theme_preview(theme_manifest, addon.current_version.pk)

    assert resize_image_mock.call_count == 3
    assert write_svg_to_png_mock.call_count == 3
    assert pngcrush_image_mock.call_count == 3

    # First check the header Preview is good
    header_preview = VersionPreview.objects.get(
        version=addon.current_version,
        position=amo.THEME_PREVIEW_SIZES['header']['position'])
    check_preview(
        header_preview, amo.THEME_PREVIEW_SIZES['header'],
        write_svg_to_png_mock.call_args_list[0][0],
        resize_image_mock.call_args_list[0][0],
        pngcrush_image_mock.call_args_list[0][0])

    # Then the list Preview
    list_preview = VersionPreview.objects.get(
        version=addon.current_version,
        position=amo.THEME_PREVIEW_SIZES['list']['position'])
    check_preview(
        list_preview, amo.THEME_PREVIEW_SIZES['list'],
        write_svg_to_png_mock.call_args_list[1][0],
        resize_image_mock.call_args_list[1][0],
        pngcrush_image_mock.call_args_list[1][0])

    # And finally the new single Preview
    single_preview = VersionPreview.objects.get(
        version=addon.current_version,
        position=amo.THEME_PREVIEW_SIZES['single']['position'])
    check_preview(
        single_preview, amo.THEME_PREVIEW_SIZES['single'],
        write_svg_to_png_mock.call_args_list[2][0],
        resize_image_mock.call_args_list[2][0],
        pngcrush_image_mock.call_args_list[2][0])

    # Now check the svg renders
    header_svg = write_svg_to_png_mock.call_args_list[0][0][0]
    list_svg = write_svg_to_png_mock.call_args_list[1][0][0]
    single_svg = write_svg_to_png_mock.call_args_list[2][0][0]
    colors = ['class="%s" fill="%s"' % (key, color)
              for (key, color) in theme_manifest['colors'].items()]
    preserve_aspect_ratio = (
        (preserve_aspect_ratio, ) * 3
        if not isinstance(preserve_aspect_ratio, tuple)
        else preserve_aspect_ratio)
    check_render(force_text(header_svg), header_url, header_height,
                 preserve_aspect_ratio[0], mimetype, valid_img, colors,
                 680, 92, 680)
    check_render(force_text(list_svg), header_url, header_height,
                 preserve_aspect_ratio[1], mimetype, valid_img, colors,
                 760, 92, 760)
    check_render(force_text(single_svg), header_url, header_height,
                 preserve_aspect_ratio[2], mimetype, valid_img, colors,
                 720, 92, 720)

    index_addons_mock.assert_called_with([addon.id])
Beispiel #49
0
def test_generate_static_theme_preview_with_alternative_properties(
        write_svg_to_png_mock, resize_image_mock, pngcrush_image_mock,
        extract_colors_from_image_mock, index_addons_mock, manifest_images,
        manifest_colors, svg_colors):
    write_svg_to_png_mock.return_value = True
    extract_colors_from_image_mock.return_value = [{
        'h': 9,
        's': 8,
        'l': 7,
        'ratio': 0.6
    }]
    theme_manifest = {
        "images": manifest_images,
        "colors": manifest_colors,
    }
    addon = addon_factory()
    destination = addon.current_version.all_files[0].current_file_path
    zip_file = os.path.join(HEADER_ROOT, 'theme_images.zip')
    copy_stored_file(zip_file, destination)
    generate_static_theme_preview(theme_manifest, addon.current_version.pk)

    assert resize_image_mock.call_count == 3
    assert write_svg_to_png_mock.call_count == 3
    assert pngcrush_image_mock.call_count == 3

    # First check the header Preview is good
    header_preview = VersionPreview.objects.get(
        version=addon.current_version,
        position=amo.THEME_PREVIEW_SIZES['header']['position'])
    check_preview(header_preview, amo.THEME_PREVIEW_SIZES['header'],
                  write_svg_to_png_mock.call_args_list[0][0],
                  resize_image_mock.call_args_list[0][0],
                  pngcrush_image_mock.call_args_list[0][0])

    # Then the list Preview
    list_preview = VersionPreview.objects.get(
        version=addon.current_version,
        position=amo.THEME_PREVIEW_SIZES['list']['position'])
    check_preview(list_preview, amo.THEME_PREVIEW_SIZES['list'],
                  write_svg_to_png_mock.call_args_list[1][0],
                  resize_image_mock.call_args_list[1][0],
                  pngcrush_image_mock.call_args_list[1][0])

    # And finally the new single Preview
    single_preview = VersionPreview.objects.get(
        version=addon.current_version,
        position=amo.THEME_PREVIEW_SIZES['single']['position'])
    check_preview(single_preview, amo.THEME_PREVIEW_SIZES['single'],
                  write_svg_to_png_mock.call_args_list[2][0],
                  resize_image_mock.call_args_list[2][0],
                  pngcrush_image_mock.call_args_list[2][0])

    colors = [
        'class="%s" fill="%s"' % (key, color)
        for (key, color) in svg_colors.items()
    ]

    header_svg = write_svg_to_png_mock.call_args_list[0][0][0]
    list_svg = write_svg_to_png_mock.call_args_list[1][0][0]
    single_svg = write_svg_to_png_mock.call_args_list[2][0][0]
    check_render(force_text(header_svg), 'transparent.gif', 1, 'xMaxYMin meet',
                 'image/gif', True, colors, 680, 92, 680)
    check_render(force_text(list_svg), 'transparent.gif', 1, 'xMaxYMin meet',
                 'image/gif', True, colors, 760, 92, 760)
    check_render(force_text(single_svg), 'transparent.gif', 1, 'xMaxYMin meet',
                 'image/gif', True, colors, 720, 92, 720)
Beispiel #50
0
def test_generate_preview_with_additional_backgrounds(
        write_svg_to_png_mock, resize_image_mock, pngcrush_image_mock,
        extract_colors_from_image_mock, index_addons_mock):
    write_svg_to_png_mock.return_value = True
    extract_colors_from_image_mock.return_value = [
        {'h': 9, 's': 8, 'l': 7, 'ratio': 0.6}
    ]

    theme_manifest = {
        "images": {
            "theme_frame": "empty.png",
            "additional_backgrounds": ["weta_for_tiling.png"],
        },
        "colors": {
            "textcolor": "#123456",
            # Just textcolor, to test the template defaults and fallbacks.
        },
        "properties": {
            "additional_backgrounds_alignment": ["top"],
            "additional_backgrounds_tiling": ["repeat-x"],
        },
    }
    addon = addon_factory()
    destination = addon.current_version.all_files[0].current_file_path
    zip_file = os.path.join(
        settings.ROOT,
        'src/olympia/devhub/tests/addons/static_theme_tiled.zip')
    copy_stored_file(zip_file, destination)
    generate_static_theme_preview(theme_manifest, addon.current_version.pk)

    assert resize_image_mock.call_count == 3
    assert write_svg_to_png_mock.call_count == 3
    assert pngcrush_image_mock.call_count == 3

    # First check the header Preview is good
    header_preview = VersionPreview.objects.get(
        version=addon.current_version,
        position=amo.THEME_PREVIEW_SIZES['header']['position'])
    check_preview(
        header_preview, amo.THEME_PREVIEW_SIZES['header'],
        write_svg_to_png_mock.call_args_list[0][0],
        resize_image_mock.call_args_list[0][0],
        pngcrush_image_mock.call_args_list[0][0])

    # Then the list Preview
    list_preview = VersionPreview.objects.get(
        version=addon.current_version,
        position=amo.THEME_PREVIEW_SIZES['list']['position'])
    check_preview(
        list_preview, amo.THEME_PREVIEW_SIZES['list'],
        write_svg_to_png_mock.call_args_list[1][0],
        resize_image_mock.call_args_list[1][0],
        pngcrush_image_mock.call_args_list[1][0])

    # And finally the new single Preview
    single_preview = VersionPreview.objects.get(
        version=addon.current_version,
        position=amo.THEME_PREVIEW_SIZES['single']['position'])
    check_preview(
        single_preview, amo.THEME_PREVIEW_SIZES['single'],
        write_svg_to_png_mock.call_args_list[2][0],
        resize_image_mock.call_args_list[2][0],
        pngcrush_image_mock.call_args_list[2][0])

    # These defaults are mostly defined in the xml template
    default_colors = {
        "frame": "rgba(229,230,232,1)",  # amo.THEME_FRAME_COLOR_DEFAULT
        "tab_background_text": "#123456",  # the only one defined in 'manifest'
        "bookmark_text": "#123456",  # should default to tab_background_text
        "toolbar_field": "rgba(255,255,255,1)",
        "toolbar_field_text": "",
        "tab_line": "rgba(0,0,0,0.25)",
        "tab_selected": "rgba(0,0,0,0)",
    }
    colors = ['class="%s" fill="%s"' % (key, color)
              for (key, color) in default_colors.items()]

    header_svg = write_svg_to_png_mock.call_args_list[0][0][0]
    list_svg = write_svg_to_png_mock.call_args_list[1][0][0]
    single_svg = write_svg_to_png_mock.call_args_list[2][0][0]
    check_render_additional(force_text(header_svg), 680, colors)
    check_render_additional(force_text(list_svg), 760, colors)
    check_render_additional(force_text(single_svg), 720, colors)

    index_addons_mock.assert_called_with([addon.id])
Beispiel #51
0
def test_generate_static_theme_preview(write_svg_to_png_mock,
                                       resize_image_mock, pngcrush_image_mock,
                                       extract_colors_from_image_mock,
                                       index_addons_mock, header_url,
                                       header_height, preserve_aspect_ratio,
                                       mimetype, valid_img):
    write_svg_to_png_mock.return_value = True
    extract_colors_from_image_mock.return_value = [{
        'h': 9,
        's': 8,
        'l': 7,
        'ratio': 0.6
    }]
    theme_manifest = {
        "images": {},
        "colors": {
            "frame": "#918e43",
            "tab_background_text": "#3deb60",
            "bookmark_text": "#b5ba5b",
            "toolbar_field": "#cc29cc",
            "toolbar_field_text": "#17747d",
            "tab_line": "#00db12",
            "tab_selected": "#40df39",
        }
    }
    if header_url is not None:
        theme_manifest['images']['theme_frame'] = header_url
    addon = addon_factory()
    destination = addon.current_version.all_files[0].current_file_path
    zip_file = os.path.join(HEADER_ROOT, 'theme_images.zip')
    copy_stored_file(zip_file, destination)
    generate_static_theme_preview(theme_manifest, addon.current_version.pk)

    assert resize_image_mock.call_count == 3
    assert write_svg_to_png_mock.call_count == 3
    assert pngcrush_image_mock.call_count == 3

    # First check the header Preview is good
    header_preview = VersionPreview.objects.get(
        version=addon.current_version,
        position=amo.THEME_PREVIEW_SIZES['header']['position'])
    check_preview(header_preview, amo.THEME_PREVIEW_SIZES['header'],
                  write_svg_to_png_mock.call_args_list[0][0],
                  resize_image_mock.call_args_list[0][0],
                  pngcrush_image_mock.call_args_list[0][0])

    # Then the list Preview
    list_preview = VersionPreview.objects.get(
        version=addon.current_version,
        position=amo.THEME_PREVIEW_SIZES['list']['position'])
    check_preview(list_preview, amo.THEME_PREVIEW_SIZES['list'],
                  write_svg_to_png_mock.call_args_list[1][0],
                  resize_image_mock.call_args_list[1][0],
                  pngcrush_image_mock.call_args_list[1][0])

    # And finally the new single Preview
    single_preview = VersionPreview.objects.get(
        version=addon.current_version,
        position=amo.THEME_PREVIEW_SIZES['single']['position'])
    check_preview(single_preview, amo.THEME_PREVIEW_SIZES['single'],
                  write_svg_to_png_mock.call_args_list[2][0],
                  resize_image_mock.call_args_list[2][0],
                  pngcrush_image_mock.call_args_list[2][0])

    # Now check the svg renders
    header_svg = write_svg_to_png_mock.call_args_list[0][0][0]
    list_svg = write_svg_to_png_mock.call_args_list[1][0][0]
    single_svg = write_svg_to_png_mock.call_args_list[2][0][0]
    colors = [
        'class="%s" fill="%s"' % (key, color)
        for (key, color) in theme_manifest['colors'].items()
    ]
    preserve_aspect_ratio = ((preserve_aspect_ratio, ) *
                             3 if not isinstance(preserve_aspect_ratio, tuple)
                             else preserve_aspect_ratio)
    check_render(force_text(header_svg), header_url, header_height,
                 preserve_aspect_ratio[0], mimetype, valid_img, colors, 680,
                 92, 680)
    check_render(force_text(list_svg), header_url, header_height,
                 preserve_aspect_ratio[1], mimetype, valid_img, colors, 760,
                 92, 760)
    check_render(force_text(single_svg), header_url, header_height,
                 preserve_aspect_ratio[2], mimetype, valid_img, colors, 720,
                 92, 720)

    index_addons_mock.assert_called_with([addon.id])
Beispiel #52
0
def test_generate_static_theme_preview_with_alternative_properties(
        write_svg_to_png_mock, resize_image_mock, pngcrush_image_mock,
        extract_colors_from_image_mock, index_addons_mock,
        manifest_images, manifest_colors, svg_colors):
    write_svg_to_png_mock.return_value = True
    extract_colors_from_image_mock.return_value = [
        {'h': 9, 's': 8, 'l': 7, 'ratio': 0.6}
    ]
    theme_manifest = {
        "images": manifest_images,
        "colors": manifest_colors,
    }
    addon = addon_factory()
    destination = addon.current_version.all_files[0].current_file_path
    zip_file = os.path.join(HEADER_ROOT, 'theme_images.zip')
    copy_stored_file(zip_file, destination)
    generate_static_theme_preview(theme_manifest, addon.current_version.pk)

    assert resize_image_mock.call_count == 3
    assert write_svg_to_png_mock.call_count == 3
    assert pngcrush_image_mock.call_count == 3

    # First check the header Preview is good
    header_preview = VersionPreview.objects.get(
        version=addon.current_version,
        position=amo.THEME_PREVIEW_SIZES['header']['position'])
    check_preview(
        header_preview, amo.THEME_PREVIEW_SIZES['header'],
        write_svg_to_png_mock.call_args_list[0][0],
        resize_image_mock.call_args_list[0][0],
        pngcrush_image_mock.call_args_list[0][0])

    # Then the list Preview
    list_preview = VersionPreview.objects.get(
        version=addon.current_version,
        position=amo.THEME_PREVIEW_SIZES['list']['position'])
    check_preview(
        list_preview, amo.THEME_PREVIEW_SIZES['list'],
        write_svg_to_png_mock.call_args_list[1][0],
        resize_image_mock.call_args_list[1][0],
        pngcrush_image_mock.call_args_list[1][0])

    # And finally the new single Preview
    single_preview = VersionPreview.objects.get(
        version=addon.current_version,
        position=amo.THEME_PREVIEW_SIZES['single']['position'])
    check_preview(
        single_preview, amo.THEME_PREVIEW_SIZES['single'],
        write_svg_to_png_mock.call_args_list[2][0],
        resize_image_mock.call_args_list[2][0],
        pngcrush_image_mock.call_args_list[2][0])

    colors = ['class="%s" fill="%s"' % (key, color)
              for (key, color) in svg_colors.items()]

    header_svg = write_svg_to_png_mock.call_args_list[0][0][0]
    list_svg = write_svg_to_png_mock.call_args_list[1][0][0]
    single_svg = write_svg_to_png_mock.call_args_list[2][0][0]
    check_render(force_text(header_svg), 'transparent.gif', 1,
                 'xMaxYMin meet', 'image/gif', True, colors, 680, 92, 680)
    check_render(force_text(list_svg), 'transparent.gif', 1,
                 'xMaxYMin meet', 'image/gif', True, colors, 760, 92, 760)
    check_render(force_text(single_svg), 'transparent.gif', 1,
                 'xMaxYMin meet', 'image/gif', True, colors, 720, 92, 720)
 def test_non_ascii(self):
     src = self.newfile(u"kristi\u0107.txt", u"ivan kristi\u0107".encode("utf8"))
     dest = self.path(u"somedir/kristi\u0107.txt")
     copy_stored_file(src, dest)
     eq_(self.contents(dest), "ivan kristi\xc4\x87")
Beispiel #54
0
 def _mock_xpi_side_effect(self, addon, destination):
     xpi_path = os.path.join(
         settings.ROOT, 'src/olympia/files/fixtures/files/dict-webext.xpi')
     copy_stored_file(xpi_path, destination)
     assert not os.path.isdir(destination)
     return mock.DEFAULT