From 0c8b2a8a1ee435fbce3e5a3ca33745fe60ce846e Mon Sep 17 00:00:00 2001 From: Emily Kager Date: Tue, 12 Feb 2019 11:13:09 -0800 Subject: [PATCH] Closes #449 - Adds Basic About Page with Dated Version Name --- app/build.gradle | 8 +-- .../mozilla/fenix/AppRequestInterceptor.kt | 41 ++++++++++++++ .../java/org/mozilla/fenix/components/Core.kt | 2 + .../main/java/org/mozilla/fenix/ext/String.kt | 16 ++++++ .../org/mozilla/fenix/settings/AboutPage.kt | 53 +++++++++++++++++++ .../fenix/settings/SettingsFragment.kt | 29 +++++++++- app/src/main/res/raw/about.html | 49 +++++++++++++++++ app/src/main/res/values/strings.xml | 6 +++ buildSrc/src/main/java/Config.kt | 27 ++++++++++ 9 files changed, 226 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/org/mozilla/fenix/AppRequestInterceptor.kt create mode 100644 app/src/main/java/org/mozilla/fenix/ext/String.kt create mode 100644 app/src/main/java/org/mozilla/fenix/settings/AboutPage.kt create mode 100644 app/src/main/res/raw/about.html create mode 100644 buildSrc/src/main/java/Config.kt diff --git a/app/build.gradle b/app/build.gradle index 91969d20f..9df434e57 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -12,10 +12,10 @@ android { compileSdkVersion 28 defaultConfig { applicationId "org.mozilla.fenix" - minSdkVersion 21 - targetSdkVersion 28 - versionCode 1 - versionName "1.0" + minSdkVersion Config.minSdkVersion + targetSdkVersion Config.targetSdkVersion + versionCode Config.versionCode + versionName Config.versionName + Config.generateVersionSuffix() testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { diff --git a/app/src/main/java/org/mozilla/fenix/AppRequestInterceptor.kt b/app/src/main/java/org/mozilla/fenix/AppRequestInterceptor.kt new file mode 100644 index 000000000..121ed5559 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/AppRequestInterceptor.kt @@ -0,0 +1,41 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix + +import android.content.Context +import mozilla.components.browser.errorpages.ErrorPages +import mozilla.components.browser.errorpages.ErrorType +import mozilla.components.concept.engine.EngineSession +import mozilla.components.concept.engine.request.RequestInterceptor +import org.mozilla.fenix.settings.AboutPage +import org.mozilla.fenix.settings.SettingsFragment + +class AppRequestInterceptor(private val context: Context) : RequestInterceptor { + override fun onLoadRequest( + session: EngineSession, + uri: String + ): RequestInterceptor.InterceptionResponse? { + return when (uri) { + SettingsFragment.aboutURL -> { + val page = AboutPage.createAboutPage(context) + return RequestInterceptor.InterceptionResponse.Content(page, encoding = base64) + } + + else -> null + } + } + + override fun onErrorRequest( + session: EngineSession, + errorType: ErrorType, + uri: String? + ): RequestInterceptor.ErrorResponse? { + return RequestInterceptor.ErrorResponse(ErrorPages.createErrorPage(context, errorType)) + } + + companion object { + const val base64 = "base64" + } +} diff --git a/app/src/main/java/org/mozilla/fenix/components/Core.kt b/app/src/main/java/org/mozilla/fenix/components/Core.kt index de81ba774..cc9c18f42 100644 --- a/app/src/main/java/org/mozilla/fenix/components/Core.kt +++ b/app/src/main/java/org/mozilla/fenix/components/Core.kt @@ -16,6 +16,7 @@ import mozilla.components.concept.engine.Engine import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy import mozilla.components.feature.session.HistoryDelegate import mozilla.components.lib.crash.handler.CrashHandlerService +import org.mozilla.fenix.AppRequestInterceptor import org.mozilla.geckoview.GeckoRuntime import org.mozilla.geckoview.GeckoRuntimeSettings @@ -32,6 +33,7 @@ class Core(private val context: Context) { val prefs = PreferenceManager.getDefaultSharedPreferences(context) val defaultSettings = DefaultSettings( + requestInterceptor = AppRequestInterceptor(context), remoteDebuggingEnabled = false, testingModeEnabled = false, trackingProtectionPolicy = createTrackingProtectionPolicy(prefs), diff --git a/app/src/main/java/org/mozilla/fenix/ext/String.kt b/app/src/main/java/org/mozilla/fenix/ext/String.kt new file mode 100644 index 000000000..04421f26f --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/ext/String.kt @@ -0,0 +1,16 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.mozilla.fenix.ext + +/** + * Replaces the keys with the values with the map provided. + */ +fun String.replace(pairs: Map): String { + var result = this + pairs.forEach { (l, r) -> result = result.replace(l, r) } + return result +} diff --git a/app/src/main/java/org/mozilla/fenix/settings/AboutPage.kt b/app/src/main/java/org/mozilla/fenix/settings/AboutPage.kt new file mode 100644 index 000000000..250779625 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/settings/AboutPage.kt @@ -0,0 +1,53 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.mozilla.fenix.settings + +import android.content.Context +import android.content.pm.PackageManager +import androidx.annotation.RawRes +import org.mozilla.fenix.R +import org.mozilla.fenix.ext.replace +import org.mozilla.geckoview.BuildConfig + +object AboutPage { + fun createAboutPage(context: Context): String { + val substitutionMap = mutableMapOf() + val appName = context.resources.getString(R.string.app_name) + + try { + val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0) + val geckoVersion = packageInfo.versionCode.toString() + " \uD83E\uDD8E " + + BuildConfig.MOZ_APP_VERSION + "-" + BuildConfig.MOZ_APP_BUILDID + String.format( + "%s (Build #%s)", + packageInfo.versionName, + geckoVersion + ).also { aboutVersion -> + substitutionMap["%about-version%"] = aboutVersion + } + } catch (e: PackageManager.NameNotFoundException) { + // Nothing to do if we can't find the package name. + } + + context.resources.getString(R.string.about_content, appName).also { content -> + substitutionMap["%about-content%"] = content + } + + return loadResourceFile(context, R.raw.about, substitutionMap) + } + + private fun loadResourceFile( + context: Context, + @RawRes resId: Int, + replacements: Map + ): String { + context.resources.openRawResource(resId) + .bufferedReader() + .use { it.readText() } + .also { return it.replace(replacements) } + } +} diff --git a/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt index 7992a5ba3..3be68ac2c 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt @@ -9,12 +9,16 @@ import android.os.Bundle import android.provider.Settings import android.widget.Toast import androidx.appcompat.app.AppCompatActivity +import androidx.navigation.Navigation import androidx.preference.Preference import androidx.preference.Preference.OnPreferenceClickListener import androidx.preference.PreferenceFragmentCompat +import mozilla.components.browser.session.Session import org.mozilla.fenix.R +import org.mozilla.fenix.R.string.pref_key_about import org.mozilla.fenix.R.string.pref_key_make_default_browser import org.mozilla.fenix.ext.getPreferenceKey +import org.mozilla.fenix.ext.requireComponents class SettingsFragment : PreferenceFragmentCompat() { @@ -35,10 +39,14 @@ class SettingsFragment : PreferenceFragmentCompat() { private fun setupPreferences() { val makeDefaultBrowserKey = context?.getPreferenceKey(pref_key_make_default_browser) + val aboutKey = context?.getPreferenceKey(pref_key_about) val preferenceMakeDefaultBrowser = findPreference(makeDefaultBrowserKey) + val preferenceAbout = findPreference(aboutKey) - preferenceMakeDefaultBrowser.onPreferenceClickListener = getClickListenerForMakeDefaultBrowser() + preferenceMakeDefaultBrowser.onPreferenceClickListener = + getClickListenerForMakeDefaultBrowser() + preferenceAbout.onPreferenceClickListener = getAboutPageListener() } private val defaultClickListener = OnPreferenceClickListener { preference -> @@ -59,4 +67,23 @@ class SettingsFragment : PreferenceFragmentCompat() { defaultClickListener } } + + private fun getAboutPageListener(): OnPreferenceClickListener { + return OnPreferenceClickListener { + requireComponents.core.sessionManager.add(Session(aboutURL), true) + view?.let { + Navigation.findNavController(it) + .navigate( + SettingsFragmentDirections.actionGlobalBrowser( + requireComponents.core.sessionManager.selectedSession?.id + ) + ) + } + true + } + } + + companion object { + const val aboutURL = "about:version" + } } diff --git a/app/src/main/res/raw/about.html b/app/src/main/res/raw/about.html new file mode 100644 index 000000000..0396efb8d --- /dev/null +++ b/app/src/main/res/raw/about.html @@ -0,0 +1,49 @@ + + + + + + + + +

Fenix

+

%about-version%

+ %about-content% + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0ef5b0c19..f2802a0f6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -131,4 +131,10 @@ History item menu + + + %1$s puts you in control.

+

%1$s is produced by Mozilla. Our mission is to foster a healthy, open Internet.
+ ]]> diff --git a/buildSrc/src/main/java/Config.kt b/buildSrc/src/main/java/Config.kt new file mode 100644 index 000000000..616695148 --- /dev/null +++ b/buildSrc/src/main/java/Config.kt @@ -0,0 +1,27 @@ +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +object Config { + const val versionCode = 1 + const val versionName = "1.0" + + // Synchronized build configuration for all modules + const val compileSdkVersion = 28 + const val minSdkVersion = 21 + const val targetSdkVersion = 28 + + @JvmStatic + fun generateVersionSuffix(): String { + val today = Date() + // Append the year (2 digits) and week in year (2 digits). This will make it easier to distinguish versions and + // identify ancient versions when debugging issues. However this will still keep the same version number during + // the week so that we do not end up with a lot of versions in tools like Sentry. As an extra this matches the + // sections we use in the changelog (weeks). + return SimpleDateFormat(".yyww", Locale.US).format(today) + } +}