Exemple #1
0
def all_downloads(request, channel):
    if channel is None:
        channel = "release"
    if channel == "developer":
        channel = "alpha"
    if channel == "organizations":
        channel = "esr"

    version = firefox_desktop.latest_version(channel)
    query = request.GET.get("q")

    channel_names = {
        "release": _("Firefox"),
        "beta": _("Firefox Beta"),
        "alpha": _("Developer Edition"),
        "esr": _("Firefox Extended Support Release"),
    }

    context = {
        "full_builds_version": version.split(".", 1)[0],
        "full_builds": firefox_desktop.get_filtered_full_builds(channel, version, query),
        "test_builds": firefox_desktop.get_filtered_test_builds(channel, version, query),
        "query": query,
        "channel": channel,
        "channel_name": channel_names[channel],
    }

    if channel == "esr":
        next_version = firefox_desktop.latest_version("esr_next")
        if next_version:
            context["full_builds_next_version"] = next_version.split(".", 1)[0]
            context["full_builds_next"] = firefox_desktop.get_filtered_full_builds("esr_next", next_version, query)
            context["test_builds_next"] = firefox_desktop.get_filtered_test_builds("esr_next", next_version, query)
    return l10n_utils.render(request, "firefox/all.html", context)
Exemple #2
0
def latest_notes(request, product='firefox', platform=None, channel=None):
    if not platform:
        platform = 'desktop'

    if not channel:
        channel = 'release'
    if channel in ['aurora', 'developer']:
        channel = 'alpha'
    if channel == 'organizations':
        channel = 'esr'

    if product == 'thunderbird':
        version = thunderbird_desktop.latest_version(channel)
    elif platform == 'android':
        version = firefox_android.latest_version(channel)
    elif platform == 'ios':
        version = firefox_ios.latest_version(channel)
    else:
        version = firefox_desktop.latest_version(channel)

    if channel == 'beta':
        version = re.sub(r'b\d+$', 'beta', version)
    if channel == 'esr':
        version = re.sub(r'esr$', '', version)

    dir = 'auroranotes' if channel == 'alpha' else 'releasenotes'
    path = [product, version, dir]
    locale = getattr(request, 'locale', None)
    if product == 'firefox' and platform != 'desktop':
        path.insert(1, platform)
    if locale:
        path.insert(0, locale)
    return HttpResponseRedirect('/' + '/'.join(path) + '/')
Exemple #3
0
def latest_sysreq(request, channel, product):
    if product == 'firefox' and channel == 'developer':
        channel = 'alpha'
    if channel == 'organizations':
        channel = 'esr'

    if product == 'thunderbird':
        version = thunderbird_desktop.latest_version(channel)
    elif product == 'mobile':
        version = firefox_android.latest_version(channel)
    elif product == 'ios':
        version = firefox_ios.latest_version(channel)
    else:
        version = firefox_desktop.latest_version(channel)

    if channel == 'beta':
        version = re.sub(r'b\d+$', 'beta', version)
    if channel == 'esr':
        version = re.sub(r'^(\d+).+', r'\1.0', version)

    dir = 'system-requirements'
    path = [product, version, dir]
    locale = getattr(request, 'locale', None)
    if locale:
        path.insert(0, locale)
    return HttpResponseRedirect('/' + '/'.join(path) + '/')
Exemple #4
0
def releases_index(request, product):
    releases = {}
    # Starting with Firefox 10, ESR had been offered every 7 major releases, but
    # Firefox 59 wasn't ESR. Firefox 60 became the next ESR instead, and since
    # then ESR is offered every 8 major releases.
    esr_major_versions = (range(10, 59, 7) +
        range(60, int(firefox_desktop.latest_version().split('.')[0]), 8))

    if product == 'Firefox':
        major_releases = firefox_desktop.firefox_history_major_releases
        minor_releases = firefox_desktop.firefox_history_stability_releases

    for release in major_releases:
        major_version = float(re.findall(r'^\d+\.\d+', release)[0])
        # The version numbering scheme of Firefox changes sometimes. The second
        # number has not been used since Firefox 4, then reintroduced with
        # Firefox ESR 24 (Bug 870540). On this index page, 24.1.x should be
        # fallen under 24.0. This pattern is a tricky part.
        converter = '%g' if int(major_version) in esr_major_versions else '%s'
        major_pattern = r'^' + re.escape(converter % round(major_version, 1))
        releases[major_version] = {
            'major': release,
            'minor': sorted(filter(lambda x: re.findall(major_pattern, x),
                                   minor_releases),
                            key=lambda x: map(lambda y: int(y), x.split('.')))
        }

    return l10n_utils.render(
        request, '{product}/releases/index.html'.format(product=product.lower()),
        {'releases': sorted(releases.items(), reverse=True)}
    )
Exemple #5
0
def all_downloads(request, platform, channel):
    if platform is None:
        platform = 'desktop'
    if platform == 'desktop':
        product = firefox_desktop
    if platform == 'android':
        product = firefox_android

    if channel is None:
        channel = 'release'
    if channel in ['developer', 'aurora']:
        channel = 'alpha'
    if channel == 'organizations':
        channel = 'esr'

    # Since the regex in urls.py matches various URL patterns, we have to handle
    # nonexistent pages here as 404 Not Found
    if platform == 'ios':
        raise Http404
    if platform == 'android' and channel == 'esr':
        raise Http404

    # Aurora for Android is gone; the population has been migrated to Nightly.
    # Redirect /firefox/android/aurora/all/ to /firefox/android/nightly/all/
    if platform == 'android' and channel == 'alpha':
        return HttpResponsePermanentRedirect(
            reverse('firefox.all',
                    kwargs={
                        'platform': 'android',
                        'channel': 'nightly'
                    }))

    version = product.latest_version(channel)
    query = request.GET.get('q')

    context = {
        'platform': platform,
        'platforms': product.platforms(channel),
        'full_builds_version': version.split('.', 1)[0],
        'full_builds':
        product.get_filtered_full_builds(channel, version, query),
        'test_builds':
        product.get_filtered_test_builds(channel, version, query),
        'query': query,
        'channel': channel,
        'channel_label': product.channel_labels.get(channel, 'Firefox'),
    }

    if platform == 'desktop' and channel == 'esr':
        next_version = firefox_desktop.latest_version('esr_next')
        if next_version:
            context['full_builds_next_version'] = next_version.split('.', 1)[0]
            context[
                'full_builds_next'] = firefox_desktop.get_filtered_full_builds(
                    'esr_next', next_version, query)
            context[
                'test_builds_next'] = firefox_desktop.get_filtered_test_builds(
                    'esr_next', next_version, query)
    return l10n_utils.render(request, 'firefox/all.html', context)
Exemple #6
0
def all_downloads(request, channel):
    if channel is None:
        channel = 'release'
    if channel == 'developer':
        channel = 'alpha'
    if channel == 'organizations':
        channel = 'esr'

    version = firefox_desktop.latest_version(channel)
    query = request.GET.get('q')

    channel_names = {
        'release': _('Firefox'),
        'beta': _('Firefox Beta'),
        'alpha': _('Developer Edition'),
        'esr': _('Firefox Extended Support Release'),
    }

    context = {
        'full_builds_version':
        version.split('.', 1)[0],
        'full_builds':
        firefox_desktop.get_filtered_full_builds(channel, version, query),
        'test_builds':
        firefox_desktop.get_filtered_test_builds(channel, version, query),
        'query':
        query,
        'channel':
        channel,
        'channel_name':
        channel_names[channel]
    }

    if channel == 'esr':
        next_version = firefox_desktop.latest_version('esr_next')
        if next_version:
            context['full_builds_next_version'] = next_version.split('.', 1)[0]
            context[
                'full_builds_next'] = firefox_desktop.get_filtered_full_builds(
                    'esr_next', next_version, query)
            context[
                'test_builds_next'] = firefox_desktop.get_filtered_test_builds(
                    'esr_next', next_version, query)
    return l10n_utils.render(request, 'firefox/all.html', context)
Exemple #7
0
def all_downloads(request, platform, channel):
    if platform is None:
        platform = 'desktop'
    if platform == 'desktop':
        product = firefox_desktop
    if platform == 'android':
        product = firefox_android

    if channel is None:
        channel = 'release'
    if channel in ['developer', 'aurora']:
        channel = 'alpha'
    if channel == 'organizations':
        channel = 'esr'

    # Since the regex in urls.py matches various URL patterns, we have to handle
    # nonexistent pages here as 404 Not Found
    if platform == 'ios':
        raise Http404
    if platform == 'android' and channel == 'esr':
        raise Http404

    # Aurora for Android is gone; the population has been migrated to Nightly.
    # Redirect /firefox/android/aurora/all/ to /firefox/android/nightly/all/
    if platform == 'android' and channel == 'alpha':
        return HttpResponsePermanentRedirect(
            reverse('firefox.all', kwargs={'platform': 'android', 'channel': 'nightly'}))

    version = product.latest_version(channel)
    query = request.GET.get('q')

    context = {
        'platform': platform,
        'platforms': product.platforms(channel, True),
        'platform_cls': product.platform_classification,
        'full_builds_version': version.split('.', 1)[0],
        'full_builds': product.get_filtered_full_builds(channel, version, query),
        'test_builds': product.get_filtered_test_builds(channel, version, query),
        'query': query,
        'channel': channel,
        'channel_label': product.channel_labels.get(channel, 'Firefox'),
    }

    if platform == 'desktop' and channel == 'esr':
        next_version = firefox_desktop.latest_version('esr_next')
        if next_version:
            context['full_builds_next_version'] = next_version.split('.', 1)[0]
            context['full_builds_next'] = firefox_desktop.get_filtered_full_builds('esr_next',
                                                                                   next_version, query)
            context['test_builds_next'] = firefox_desktop.get_filtered_test_builds('esr_next',
                                                                                   next_version, query)
    return l10n_utils.render(request, 'firefox/all.html', context)
Exemple #8
0
def all_downloads(request, platform, channel):
    if platform is None:
        platform = 'desktop'
    if platform == 'desktop':
        product = firefox_desktop
    if platform == 'android':
        product = firefox_android

    if channel is None:
        channel = 'release'
    if channel in ['developer', 'aurora']:
        channel = 'alpha'
    if channel == 'organizations':
        channel = 'esr'

    # Since the regex in urls.py matches various URL patterns, we have to handle
    # nonexistent pages here as 404 Not Found
    if platform == 'ios':
        raise Http404
    if platform == 'android' and channel in ['alpha', 'esr']:
        raise Http404

    version = product.latest_version(channel)
    query = request.GET.get('q')

    context = {
        'platform': platform,
        'platforms': product.platforms(channel),
        'full_builds_version': version.split('.', 1)[0],
        'full_builds':
        product.get_filtered_full_builds(channel, version, query),
        'test_builds':
        product.get_filtered_test_builds(channel, version, query),
        'query': query,
        'channel': channel,
        'channel_label': product.channel_labels.get(channel, 'Firefox'),
    }

    if platform == 'desktop' and channel == 'esr':
        next_version = firefox_desktop.latest_version('esr_next')
        if next_version:
            context['full_builds_next_version'] = next_version.split('.', 1)[0]
            context[
                'full_builds_next'] = firefox_desktop.get_filtered_full_builds(
                    'esr_next', next_version, query)
            context[
                'test_builds_next'] = firefox_desktop.get_filtered_test_builds(
                    'esr_next', next_version, query)
    return l10n_utils.render(request, 'firefox/all.html', context)
Exemple #9
0
def all_downloads(request, channel):
    if channel is None:
        channel = 'release'
    if channel == 'developer':
        channel = 'alpha'
    if channel == 'organizations':
        channel = 'esr'

    version = firefox_desktop.latest_version(channel)
    query = request.GET.get('q')

    channel_names = {
        'release': _('Firefox'),
        'beta': _('Firefox Beta'),
        'alpha': _('Developer Edition'),
        'esr': _('Firefox Extended Support Release'),
    }

    context = {
        'full_builds_version': version.split('.', 1)[0],
        'full_builds': firefox_desktop.get_filtered_full_builds(channel, version, query),
        'test_builds': firefox_desktop.get_filtered_test_builds(channel, version, query),
        'query': query,
        'channel': channel,
        'channel_name': channel_names[channel]
    }

    if channel == 'esr':
        next_version = firefox_desktop.latest_version('esr_next')
        if next_version:
            context['full_builds_next_version'] = next_version.split('.', 1)[0]
            context['full_builds_next'] = firefox_desktop.get_filtered_full_builds('esr_next',
                                                                                   next_version, query)
            context['test_builds_next'] = firefox_desktop.get_filtered_test_builds('esr_next',
                                                                                   next_version, query)
    return l10n_utils.render(request, 'firefox/all.html', context)
Exemple #10
0
def all_downloads(request, platform, channel):
    if platform is None:
        platform = 'desktop'
    if platform == 'desktop':
        product = firefox_desktop
    if platform == 'android':
        product = firefox_android

    if channel is None:
        channel = 'release'
    if channel in ['developer', 'aurora']:
        channel = 'alpha'
    if channel == 'organizations':
        channel = 'esr'

    # Since the regex in urls.py matches various URL patterns, we have to handle
    # nonexistent pages here as 404 Not Found
    if platform == 'ios':
        raise Http404
    if platform == 'android' and channel in ['alpha', 'esr']:
        raise Http404

    version = product.latest_version(channel)
    query = request.GET.get('q')

    context = {
        'platform': platform,
        'platforms': product.platforms(channel),
        'full_builds_version': version.split('.', 1)[0],
        'full_builds': product.get_filtered_full_builds(channel, version, query),
        'test_builds': product.get_filtered_test_builds(channel, version, query),
        'query': query,
        'channel': channel,
        'channel_label': product.channel_labels.get(channel, 'Firefox'),
    }

    if platform == 'desktop' and channel == 'esr':
        next_version = firefox_desktop.latest_version('esr_next')
        if next_version:
            context['full_builds_next_version'] = next_version.split('.', 1)[0]
            context['full_builds_next'] = firefox_desktop.get_filtered_full_builds('esr_next',
                                                                                   next_version, query)
            context['test_builds_next'] = firefox_desktop.get_filtered_test_builds('esr_next',
                                                                                   next_version, query)
    return l10n_utils.render(request, 'firefox/all.html', context)
Exemple #11
0
def all_downloads(request, platform, channel):
    if platform is None:
        platform = "desktop"
    if platform == "desktop":
        product = firefox_desktop
    if platform == "android":
        product = firefox_android

    if channel is None:
        channel = "release"
    if channel in ["developer", "aurora"]:
        channel = "alpha"
    if channel == "organizations":
        channel = "esr"

    # Since the regex in urls.py matches various URL patterns, we have to handle
    # nonexistent pages here as 404 Not Found
    if platform == "ios":
        raise Http404
    if platform == "android" and channel in ["alpha", "esr"]:
        raise Http404

    version = product.latest_version(channel)
    query = request.GET.get("q")

    context = {
        "platform": platform,
        "platforms": product.platforms(channel),
        "full_builds_version": version.split(".", 1)[0],
        "full_builds": product.get_filtered_full_builds(channel, version, query),
        "test_builds": product.get_filtered_test_builds(channel, version, query),
        "query": query,
        "channel": channel,
        "channel_label": product.channel_labels.get(channel, "Firefox"),
    }

    if platform == "desktop" and channel == "esr":
        next_version = firefox_desktop.latest_version("esr_next")
        if next_version:
            context["full_builds_next_version"] = next_version.split(".", 1)[0]
            context["full_builds_next"] = firefox_desktop.get_filtered_full_builds("esr_next", next_version, query)
            context["test_builds_next"] = firefox_desktop.get_filtered_test_builds("esr_next", next_version, query)
    return l10n_utils.render(request, "firefox/all.html", context)
Exemple #12
0
def latest_sysreq(request, channel, product):
    if product == 'firefox' and channel == 'developer':
        channel = 'alpha'
    if channel == 'organizations':
        channel = 'esr'

    if product == 'thunderbird':
        version = thunderbird_get_latest_version(channel)
    elif product == 'mobile':
        version = firefox_android.latest_version(channel)
    else:
        version = firefox_desktop.latest_version(channel)

    if channel == 'beta':
        version = re.sub(r'b\d+$', 'beta', version)
    if channel == 'esr':
        version = re.sub(r'^(\d+).+', r'\1.0', version)

    dir = 'system-requirements'
    path = [product, version, dir]
    locale = getattr(request, 'locale', None)
    if locale:
        path.insert(0, locale)
    return HttpResponseRedirect('/' + '/'.join(path) + '/')
Exemple #13
0
def download_firefox(ctx, channel='release', platform='all',
                     dom_id=None, locale=None, force_direct=False,
                     force_full_installer=False, force_funnelcake=False,
                     alt_copy=None, button_color='button-green'):
    """ Output a "download firefox" button.

    :param ctx: context from calling template.
    :param channel: name of channel: 'release', 'beta', 'alpha', or 'nightly'.
    :param platform: Target platform: 'desktop', 'android', 'ios', or 'all'.
    :param dom_id: Use this string as the id attr on the element.
    :param locale: The locale of the download. Default to locale of request.
    :param force_direct: Force the download URL to be direct.
    :param force_full_installer: Force the installer download to not be
            the stub installer (for aurora).
    :param force_funnelcake: Force the download version for en-US Windows to be
            'latest', which bouncer will translate to the funnelcake build.
    :param alt_copy: Specifies alternate copy to use for download buttons.
    :param button_color: color of download button. Default to 'button-green'.
    """
    show_desktop = platform in ['all', 'desktop']
    show_android = platform in ['all', 'android']
    show_ios = platform in ['all', 'ios']
    alt_channel = '' if channel == 'release' else channel
    locale = locale or get_locale(ctx['request'])
    funnelcake_id = ctx.get('funnelcake_id', False)
    dom_id = dom_id or 'download-button-%s-%s' % (
        'desktop' if platform == 'all' else platform, channel)

    # Gather data about the build for each platform
    builds = []

    if show_desktop:
        version = firefox_desktop.latest_version(channel)
        builds = desktop_builds(channel, builds, locale, force_direct,
                                force_full_installer, force_funnelcake,
                                funnelcake_id)

    if show_android:
        version = firefox_android.latest_version(channel)
        builds = android_builds(channel, builds)

    if show_ios:
        version = firefox_ios.latest_version(channel)
        builds.append({'os': 'ios',
                       'os_pretty': 'iOS',
                       'download_link': firefox_ios.get_download_url()})

    # Get the native name for current locale
    langs = firefox_desktop.languages
    locale_name = langs[locale]['native'] if locale in langs else locale

    # Firefox 49+ requires OS X 10.9 Mavericks and later
    mavericks_required = show_desktop and int(version.split('.', 1)[0]) >= 49

    data = {
        'locale_name': locale_name,
        'version': version,
        'product': 'firefox-%s' % platform,
        'builds': builds,
        'id': dom_id,
        'channel': alt_channel,
        'show_desktop': show_desktop,
        'show_android': show_android,
        'show_ios': show_ios,
        'alt_copy': alt_copy,
        'button_color': button_color,
        'mavericks_required': mavericks_required,
    }

    html = render_to_string('firefox/includes/download-button.html', data,
                            request=ctx['request'])
    return jinja2.Markup(html)
Exemple #14
0
def download_firefox(
    ctx,
    channel="release",
    platform="all",
    dom_id=None,
    locale=None,
    force_direct=False,
    force_full_installer=False,
    force_funnelcake=False,
    alt_copy=None,
    button_class="mzp-t-xl",
    locale_in_transition=False,
    download_location=None,
):
    """Output a "download firefox" button.

    :param ctx: context from calling template.
    :param channel: name of channel: 'release', 'beta', 'alpha', or 'nightly'.
    :param platform: Target platform: 'desktop', 'android', 'ios', or 'all'.
    :param dom_id: Use this string as the id attr on the element.
    :param locale: The locale of the download. Default to locale of request.
    :param force_direct: Force the download URL to be direct.
    :param force_full_installer: Force the installer download to not be
            the stub installer (for aurora).
    :param force_funnelcake: Force the download version for en-US Windows to be
            'latest', which bouncer will translate to the funnelcake build.
    :param alt_copy: Specifies alternate copy to use for download buttons.
    :param button_class: Classes to add to the download button, contains size mzp-t-xl by default
    :param locale_in_transition: Include the page locale in transitional download link.
    :param download_location: Specify the location of download button for
            GA reporting: 'primary cta', 'nav', 'sub nav', or 'other'.
    """
    show_desktop = platform in ["all", "desktop"]
    show_android = platform in ["all", "android"]
    show_ios = platform in ["all", "ios"]
    alt_channel = "" if channel == "release" else channel
    locale = locale or get_locale(ctx["request"])
    funnelcake_id = ctx.get("funnelcake_id", False)
    dom_id = dom_id or f"download-button-{'desktop' if platform == 'all' else platform}-{channel}"

    # Gather data about the build for each platform
    builds = []

    if show_desktop:
        version = firefox_desktop.latest_version(channel)
        builds = desktop_builds(channel, builds, locale, force_direct,
                                force_full_installer, force_funnelcake,
                                funnelcake_id, locale_in_transition)

    if show_android:
        version = firefox_android.latest_version(channel)
        builds = android_builds(channel, builds)

    if show_ios:
        version = firefox_ios.latest_version(channel)
        builds.append({
            "os": "ios",
            "os_pretty": "iOS",
            "download_link": firefox_ios.get_download_url()
        })

    # Get the native name for current locale
    langs = firefox_desktop.languages
    locale_name = langs[locale]["native"] if locale in langs else locale

    data = {
        "locale_name": locale_name,
        "version": version,
        "product": f"firefox-{platform}",
        "builds": builds,
        "id": dom_id,
        "channel": alt_channel,
        "show_desktop": show_desktop,
        "show_android": show_android,
        "show_ios": show_ios,
        "alt_copy": alt_copy,
        "button_class": button_class,
        "download_location": download_location,
        "fluent_l10n": ctx["fluent_l10n"],
    }

    html = render_to_string("firefox/includes/download-button.html",
                            data,
                            request=ctx["request"])
    return jinja2.Markup(html)
def latest_firefox_versions(request):
    return {
        'latest_firefox_version': firefox_desktop.latest_version(),
        'esr_firefox_versions': firefox_desktop.esr_minor_versions,
    }
Exemple #16
0
def download_firefox(ctx,
                     channel='release',
                     platform='all',
                     dom_id=None,
                     locale=None,
                     force_direct=False,
                     force_full_installer=False,
                     force_funnelcake=False,
                     alt_copy=None,
                     button_color='button-green',
                     locale_in_transition=False):
    """ Output a "download firefox" button.

    :param ctx: context from calling template.
    :param channel: name of channel: 'release', 'beta', 'alpha', or 'nightly'.
    :param platform: Target platform: 'desktop', 'android', 'ios', or 'all'.
    :param dom_id: Use this string as the id attr on the element.
    :param locale: The locale of the download. Default to locale of request.
    :param force_direct: Force the download URL to be direct.
    :param force_full_installer: Force the installer download to not be
            the stub installer (for aurora).
    :param force_funnelcake: Force the download version for en-US Windows to be
            'latest', which bouncer will translate to the funnelcake build.
    :param alt_copy: Specifies alternate copy to use for download buttons.
    :param button_color: color of download button. Default to 'button-green'.
    """
    show_desktop = platform in ['all', 'desktop']
    show_android = platform in ['all', 'android']
    show_ios = platform in ['all', 'ios']
    alt_channel = '' if channel == 'release' else channel
    locale = locale or get_locale(ctx['request'])
    funnelcake_id = ctx.get('funnelcake_id', False)
    dom_id = dom_id or 'download-button-%s-%s' % (
        'desktop' if platform == 'all' else platform, channel)

    # Gather data about the build for each platform
    builds = []

    if show_desktop:
        version = firefox_desktop.latest_version(channel)
        builds = desktop_builds(channel, builds, locale, force_direct,
                                force_full_installer, force_funnelcake,
                                funnelcake_id, locale_in_transition)

    if show_android:
        version = firefox_android.latest_version(channel)
        builds = android_builds(channel, builds)

    if show_ios:
        version = firefox_ios.latest_version(channel)
        builds.append({
            'os': 'ios',
            'os_pretty': 'iOS',
            'download_link': firefox_ios.get_download_url()
        })

    # Get the native name for current locale
    langs = firefox_desktop.languages
    locale_name = langs[locale]['native'] if locale in langs else locale

    data = {
        'locale_name': locale_name,
        'version': version,
        'product': 'firefox-%s' % platform,
        'builds': builds,
        'id': dom_id,
        'channel': alt_channel,
        'show_desktop': show_desktop,
        'show_android': show_android,
        'show_ios': show_ios,
        'alt_copy': alt_copy,
        'button_color': button_color,
    }

    html = render_to_string('firefox/includes/download-button.html',
                            data,
                            request=ctx['request'])
    return jinja2.Markup(html)
Exemple #17
0
def latest_firefox_versions(request):
    return {
        "latest_firefox_version": firefox_desktop.latest_version(),
        "esr_firefox_versions": firefox_desktop.esr_minor_versions,
    }