commit 737fe2f23978cc2f92a4b41bc69e31d37b6cd882 parent 1b88dfe6e9138c8acde9124d64e1e40f4c5621af Author: mike a. <mavduevskiy@mozilla.com> Date: Wed, 17 Dec 2025 01:03:21 +0000 Bug 2005089 - Part 2: Add sample relay project r=android-reviewers,gmalekpour Differential Revision: https://phabricator.services.mozilla.com/D275866 Diffstat:
31 files changed, 831 insertions(+), 0 deletions(-)
diff --git a/mobile/android/android-components/.buildconfig.yml b/mobile/android/android-components/.buildconfig.yml @@ -1912,6 +1912,29 @@ projects: - components:support-utils - components:tooling-lint - components:ui-icons + components:samples-firefox-relay: + description: A simple app demoing Firefox Relay integration. + path: samples/firefox-relay + publish: false + upstream_dependencies: + - components:compose-base + - components:concept-base + - components:concept-fetch + - components:concept-storage + - components:concept-sync + - components:lib-dataprotect + - components:lib-fetch-httpurlconnection + - components:lib-publicsuffixlist + - components:lib-state + - components:service-firefox-accounts + - components:service-firefox-relay + - components:support-appservices + - components:support-base + - components:support-ktx + - components:support-utils + - components:tooling-lint + - components:ui-colors + - components:ui-icons components:samples-glean: description: An app demoing how to use the Glean library to collect and send telemetry data. diff --git a/mobile/android/android-components/samples/firefox-relay/.gitignore b/mobile/android/android-components/samples/firefox-relay/.gitignore @@ -0,0 +1 @@ +/build diff --git a/mobile/android/android-components/samples/firefox-relay/README.md b/mobile/android/android-components/samples/firefox-relay/README.md @@ -0,0 +1,17 @@ +# [Android Components](../../README.md) > Samples > Firefox Relay + + + +## Concepts + +The main concepts shown in the sample app are: + +* Usage of the `FxRelay` component. +* Login to Firefox Accounts that provides the session token to access Relay api's. +* Getting the list of `RelayAddress` from the `RelayClient`. + +## License + + 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/ diff --git a/mobile/android/android-components/samples/firefox-relay/build.gradle b/mobile/android/android-components/samples/firefox-relay/build.gradle @@ -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/. */ + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' + +android { + compileSdk { version = release(config.compileSdkMajorVersion) { minorApiLevel = config.compileSdkMinorVersion } } + + defaultConfig { + applicationId "org.mozilla.samples.relay" + minSdk config.minSdkVersion + targetSdk config.targetSdkVersion + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled = false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + + splits { + abi { + enable = true + reset() + include "armeabi-v7a", "arm64-v8a", "x86_64" + } + } + + namespace = 'org.mozilla.samples.relay' + +} + +dependencies { + implementation project(':components:lib-fetch-httpurlconnection') + implementation project(':components:service-firefox-accounts') + implementation project(':components:support-appservices') + implementation project(':components:support-base') + implementation project(':components:support-ktx') + implementation project(":components:service-firefox-relay") + + implementation libs.androidx.appcompat + implementation libs.androidx.browser + implementation libs.androidx.constraintlayout + implementation libs.androidx.core.ktx + implementation libs.kotlinx.coroutines +} diff --git a/mobile/android/android-components/samples/firefox-relay/gradle.properties b/mobile/android/android-components/samples/firefox-relay/gradle.properties diff --git a/mobile/android/android-components/samples/firefox-relay/lint-baseline.xml b/mobile/android/android-components/samples/firefox-relay/lint-baseline.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- 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/. --> +<issues format="6" by="lint 8.13.0" type="baseline" client="gradle" dependencies="false" name="AGP (8.13.0)" variant="all" version="8.13.0"> + + <issue + id="ButtonStyleXmlDetector" + message="All buttons must have a style, try using NeutralButton or similar." + errorLine1=" <Button" + errorLine2=" ~~~~~~"> + <location + file="src/main/res/layout/activity_main.xml" + line="23" + column="10"/> + </issue> + + <issue + id="ButtonStyleXmlDetector" + message="All buttons must have a style, try using NeutralButton or similar." + errorLine1=" <Button" + errorLine2=" ~~~~~~"> + <location + file="src/main/res/layout/activity_main.xml" + line="30" + column="10"/> + </issue> + + <issue + id="ButtonStyleXmlDetector" + message="All buttons must have a style, try using NeutralButton or similar." + errorLine1=" <Button" + errorLine2=" ~~~~~~"> + <location + file="src/main/res/layout/activity_main.xml" + line="37" + column="10"/> + </issue> + + <issue + id="ButtonStyleXmlDetector" + message="All buttons must have a style, try using NeutralButton or similar." + errorLine1=" <Button" + errorLine2=" ~~~~~~"> + <location + file="src/main/res/layout/activity_main.xml" + line="44" + column="10"/> + </issue> + +</issues> diff --git a/mobile/android/android-components/samples/firefox-relay/proguard-rules.pro b/mobile/android/android-components/samples/firefox-relay/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/mobile/android/android-components/samples/firefox-relay/src/main/AndroidManifest.xml b/mobile/android/android-components/samples/firefox-relay/src/main/AndroidManifest.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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/. --> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools"> + + <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> + + <application + android:allowBackup="true" + android:fullBackupContent="@xml/backup_rules" + android:icon="@mipmap/ic_launcher" + android:roundIcon="@mipmap/ic_launcher_round" + android:label="@string/app_name" + android:supportsRtl="true" + android:theme="@style/Theme.AppCompat.Light.DarkActionBar" + android:dataExtractionRules="@xml/data_extraction_rules" + tools:targetApi="s"> + <activity + android:name="org.mozilla.samples.relay.MainActivity" + android:launchMode="singleTask" + android:windowSoftInputMode="adjustResize" + android:exported="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <category android:name="android.intent.category.BROWSABLE" /> + <category android:name="android.intent.category.DEFAULT" /> + <data + android:host="*" + android:scheme="fxaclient" /> + </intent-filter> + </activity> + </application> +</manifest> diff --git a/mobile/android/android-components/samples/firefox-relay/src/main/java/org/mozilla/samples/relay/LoginFragment.kt b/mobile/android/android-components/samples/firefox-relay/src/main/java/org/mozilla/samples/relay/LoginFragment.kt @@ -0,0 +1,113 @@ +/* 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.samples.relay + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Bitmap +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.webkit.CookieManager +import android.webkit.WebView +import android.webkit.WebViewClient +import androidx.core.net.toUri +import androidx.fragment.app.Fragment + +class LoginFragment : Fragment() { + + private lateinit var authUrl: String + private lateinit var redirectUrl: String + private var webView: WebView? = null + private var listener: OnLoginCompleteListener? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + arguments?.let { + authUrl = it.getString(AUTH_URL) + ?: throw IllegalStateException("Fragment $this arguments.authUrl is not set.") + redirectUrl = it.getString(REDIRECT_URL) + ?: throw IllegalStateException("Fragment $this arguments.redirectUrl is not set.") + } + } + + @SuppressLint("SetJavaScriptEnabled") + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + val view: View = inflater.inflate(R.layout.fragment_view, container, false) + val webView = view.findViewById<WebView>(R.id.webview) + // Need JS, cookies and localStorage. + webView.settings.domStorageEnabled = true + webView.settings.javaScriptEnabled = true + CookieManager.getInstance().setAcceptCookie(true) + + webView.webViewClient = object : WebViewClient() { + override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { + if (url != null && url.startsWith(redirectUrl)) { + val uri = url.toUri() + val code = uri.getQueryParameter("code") + val state = uri.getQueryParameter("state") + val action = uri.getQueryParameter("action") ?: "" + if (code != null && state != null) { + listener?.onLoginComplete(code, state, action, this@LoginFragment) + } + } + + super.onPageStarted(view, url, favicon) + } + } + webView.loadUrl(authUrl) + + this@LoginFragment.webView?.destroy() + this@LoginFragment.webView = webView + + return view + } + + @Suppress("TooGenericExceptionThrown") + override fun onAttach(context: Context) { + super.onAttach(context) + if (context is OnLoginCompleteListener) { + listener = context + } else { + throw IllegalStateException("$context must implement OnLoginCompleteListener") + } + } + + override fun onDetach() { + super.onDetach() + listener = null + } + + override fun onPause() { + super.onPause() + webView?.onPause() + } + + override fun onResume() { + super.onResume() + webView?.onResume() + } + + interface OnLoginCompleteListener { + /** + * A callback invoked when we get a successful redirect from the auth server. + */ + fun onLoginComplete(code: String, state: String, action: String, fragment: LoginFragment) + } + + companion object { + const val AUTH_URL = "authUrl" + const val REDIRECT_URL = "redirectUrl" + + fun create(authUrl: String, redirectUrl: String): LoginFragment = + LoginFragment().apply { + arguments = Bundle().apply { + putString(AUTH_URL, authUrl) + putString(REDIRECT_URL, redirectUrl) + } + } + } +} diff --git a/mobile/android/android-components/samples/firefox-relay/src/main/java/org/mozilla/samples/relay/MainActivity.kt b/mobile/android/android-components/samples/firefox-relay/src/main/java/org/mozilla/samples/relay/MainActivity.kt @@ -0,0 +1,179 @@ +/* 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.samples.relay + +import android.os.Bundle +import android.view.View +import android.widget.TextView +import android.widget.Toast +import androidx.activity.enableEdgeToEdge +import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope +import kotlinx.coroutines.launch +import mozilla.appservices.fxaclient.FxaConfig +import mozilla.appservices.fxaclient.FxaServer +import mozilla.components.concept.sync.AccountObserver +import mozilla.components.concept.sync.AuthType +import mozilla.components.concept.sync.DeviceConfig +import mozilla.components.concept.sync.DeviceType +import mozilla.components.concept.sync.OAuthAccount +import mozilla.components.concept.sync.Profile +import mozilla.components.lib.fetch.httpurlconnection.HttpURLConnectionClient +import mozilla.components.service.fxa.FxaAuthData +import mozilla.components.service.fxa.PeriodicSyncConfig +import mozilla.components.service.fxa.SyncConfig +import mozilla.components.service.fxa.SyncEngine +import mozilla.components.service.fxa.manager.FxaAccountManager +import mozilla.components.service.fxa.manager.SCOPE_PROFILE +import mozilla.components.service.fxa.manager.SCOPE_SESSION +import mozilla.components.service.fxa.manager.SCOPE_SYNC +import mozilla.components.service.fxa.sync.SyncReason +import mozilla.components.service.fxa.toAuthType +import mozilla.components.service.fxrelay.FxRelay +import mozilla.components.support.AppServicesInitializer +import mozilla.components.support.base.log.Log +import mozilla.components.support.base.log.sink.AndroidLogSink +import mozilla.components.support.ktx.android.view.setupPersistentInsets +import mozilla.components.support.rusthttp.RustHttpConfig +import mozilla.components.support.rustlog.RustLog +import kotlin.collections.setOf + +const val CLIENT_ID = "3c49430b43dfba77" +const val CONFIG_URL = "https://accounts.firefox.com" +const val REDIRECT_URL = "$CONFIG_URL/oauth/success/3c49430b43dfba77" +const val RELAY_URL = "https://relay.firefox.com" +const val SCOPE_RELAY = "https://identity.mozilla.com/apps/relay" + +/** + * The main activity of the project. + */ +open class MainActivity : AppCompatActivity(), LoginFragment.OnLoginCompleteListener { + private val accountManager by lazy { + FxaAccountManager( + applicationContext, + FxaConfig(FxaServer.Release, CLIENT_ID, REDIRECT_URL), + DeviceConfig("A-C Relay Sample", DeviceType.MOBILE, setOf()), + SyncConfig(setOf(SyncEngine.Passwords), PeriodicSyncConfig()), + setOf( + SCOPE_SYNC, + SCOPE_SESSION, + SCOPE_RELAY, + SCOPE_PROFILE, + ), + ) + } + + private val accountObserver = object : AccountObserver { + override fun onAuthenticated(account: OAuthAccount, authType: AuthType) { + lifecycleScope.launch { + accountManager.syncNow(SyncReason.User) + } + } + + override fun onProfileUpdated(profile: Profile) { + lifecycleScope.launch { + displayProfile(profile = profile) + } + } + + override fun onAuthenticationProblems() { + lifecycleScope.launch { + Toast.makeText(this@MainActivity, "Account auth problem", Toast.LENGTH_LONG).show() + } + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + enableEdgeToEdge() + window.setupPersistentInsets(true) + + // initializing app services + AppServicesInitializer.init(AppServicesInitializer.Config(null)) + RustHttpConfig.setClient(lazy { HttpURLConnectionClient() }) + + // enabling logging + RustLog.enable() + Log.addSink(AndroidLogSink()) + + // initializing account manager + accountManager.register(accountObserver, owner = this, autoPause = true) + lifecycleScope.launch { + accountManager.start() + } + + initViews() + } + + private fun initViews() { + findViewById<View>(R.id.buttonWebView).setOnClickListener { + lifecycleScope.launch { + val authUrl = accountManager.beginAuthentication(entrypoint = SampleFxAEntryPoint.HomeMenu) + if (authUrl == null) { + Toast.makeText( + this@MainActivity, + "Couldn't get the authUrl. Already logged in?", + Toast.LENGTH_LONG, + ).show() + return@launch + } + openWebView(authUrl) + } + } + + findViewById<View>(R.id.buttonLogout).setOnClickListener { + lifecycleScope.launch { + accountManager.logout() + val txtView: TextView = findViewById(R.id.txtView) + txtView.text = getString(R.string.logged_out) + } + } + + findViewById<View>(R.id.buttonRelayAddresses).setOnClickListener { + lifecycleScope.launch { + val account = accountManager.authenticatedAccount() + val relay = FxRelay( + serverUrl = RELAY_URL, + authToken = account?.getAccessToken(SCOPE_RELAY)?.token, + ) + val addressList = relay.fetchAllAddresses() + Toast.makeText( + applicationContext, + "Fetched ${addressList.size} addresses", + Toast.LENGTH_SHORT, + ).show() + } + } + } + + override fun onDestroy() { + super.onDestroy() + accountManager.unregister(accountObserver) + } + + override fun onLoginComplete(code: String, state: String, action: String, fragment: LoginFragment) { + lifecycleScope.launch { + val authType = action.takeIf { it.isNotEmpty() }?.toAuthType() ?: AuthType.Signin + accountManager.finishAuthentication( + FxaAuthData(authType, code = code, state = state), + ) + supportFragmentManager.popBackStack() + } + } + + private fun openWebView(url: String) { + supportFragmentManager.beginTransaction().apply { + replace(R.id.container, LoginFragment.create(url, REDIRECT_URL)) + addToBackStack(null) + commit() + } + } + + private fun displayProfile(profile: Profile) { + val txtView: TextView = findViewById(R.id.txtView) + txtView.text = getString(R.string.signed_in, "${profile.displayName ?: ""} ${profile.email}") + } +} diff --git a/mobile/android/android-components/samples/firefox-relay/src/main/java/org/mozilla/samples/relay/SampleFxAEntryPoint.kt b/mobile/android/android-components/samples/firefox-relay/src/main/java/org/mozilla/samples/relay/SampleFxAEntryPoint.kt @@ -0,0 +1,14 @@ +/* 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.samples.relay + +import mozilla.components.concept.sync.FxAEntryPoint + +/** + * An implementation of [FxAEntryPoint] for the sample application. + */ +enum class SampleFxAEntryPoint(override val entryName: String) : FxAEntryPoint { + HomeMenu("home-menu"), +} diff --git a/mobile/android/android-components/samples/firefox-relay/src/main/res/drawable/ic_launcher_background.xml b/mobile/android/android-components/samples/firefox-relay/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,173 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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/. --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="108dp" + android:height="108dp" + android:viewportWidth="108" + android:viewportHeight="108"> + <path + android:fillColor="#3DDC84" + android:pathData="M0,0h108v108h-108z" /> + <path + android:fillColor="#00000000" + android:pathData="M9,0L9,108" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M19,0L19,108" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M29,0L29,108" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M39,0L39,108" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M49,0L49,108" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M59,0L59,108" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M69,0L69,108" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M79,0L79,108" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M89,0L89,108" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M99,0L99,108" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M0,9L108,9" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M0,19L108,19" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M0,29L108,29" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M0,39L108,39" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M0,49L108,49" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M0,59L108,59" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M0,69L108,69" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M0,79L108,79" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M0,89L108,89" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M0,99L108,99" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M19,29L89,29" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M19,39L89,39" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M19,49L89,49" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M19,59L89,59" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M19,69L89,69" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M19,79L89,79" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M29,19L29,89" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M39,19L39,89" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M49,19L49,89" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M59,19L59,89" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M69,19L69,89" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + <path + android:fillColor="#00000000" + android:pathData="M79,19L79,89" + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> +</vector> diff --git a/mobile/android/android-components/samples/firefox-relay/src/main/res/drawable/ic_launcher_foreground.xml b/mobile/android/android-components/samples/firefox-relay/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,33 @@ +<!-- 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/. --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt" + android:width="108dp" + android:height="108dp" + android:viewportWidth="108" + android:viewportHeight="108"> + <path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z"> + <aapt:attr name="android:fillColor"> + <gradient + android:endX="85.84757" + android:endY="92.4963" + android:startX="42.9492" + android:startY="49.59793" + android:type="linear"> + <item + android:color="#44000000" + android:offset="0.0" /> + <item + android:color="#00000000" + android:offset="1.0" /> + </gradient> + </aapt:attr> + </path> + <path + android:fillColor="#FFFFFF" + android:fillType="nonZero" + android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z" + android:strokeWidth="1" + android:strokeColor="#00000000" /> +</vector> +\ No newline at end of file diff --git a/mobile/android/android-components/samples/firefox-relay/src/main/res/layout/activity_main.xml b/mobile/android/android-components/samples/firefox-relay/src/main/res/layout/activity_main.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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/. --> + +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + android:id="@+id/container" + tools:context="org.mozilla.samples.relay.MainActivity"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_alignParentStart="true" + android:layout_alignParentTop="true" + android:orientation="vertical" + android:id="@+id/buttonList" + tools:context="org.mozilla.samples.fxa.MainActivity"> + + <Button + android:id="@+id/buttonWebView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/sign_in_webview" + android:textAlignment="center" /> + + <Button + android:id="@+id/buttonLogout" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/log_out" + android:textAlignment="center" /> + + <Button + android:id="@+id/buttonRelayAddresses" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/relay_addresses" + android:textAlignment="center" /> + + <TextView + android:id="@+id/txtView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:text="" /> + </LinearLayout> +</RelativeLayout> diff --git a/mobile/android/android-components/samples/firefox-relay/src/main/res/layout/fragment_view.xml b/mobile/android/android-components/samples/firefox-relay/src/main/res/layout/fragment_view.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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/. --> + +<WebView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/webview" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context=".LoginFragment" /> diff --git a/mobile/android/android-components/samples/firefox-relay/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/mobile/android/android-components/samples/firefox-relay/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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/. --> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@drawable/ic_launcher_background" /> + <foreground android:drawable="@drawable/ic_launcher_foreground" /> + <monochrome android:drawable="@drawable/ic_launcher_foreground" /> +</adaptive-icon> diff --git a/mobile/android/android-components/samples/firefox-relay/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/mobile/android/android-components/samples/firefox-relay/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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/. --> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@drawable/ic_launcher_background" /> + <foreground android:drawable="@drawable/ic_launcher_foreground" /> + <monochrome android:drawable="@drawable/ic_launcher_foreground" /> +</adaptive-icon> diff --git a/mobile/android/android-components/samples/firefox-relay/src/main/res/mipmap-hdpi/ic_launcher.webp b/mobile/android/android-components/samples/firefox-relay/src/main/res/mipmap-hdpi/ic_launcher.webp diff --git a/mobile/android/android-components/samples/firefox-relay/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/mobile/android/android-components/samples/firefox-relay/src/main/res/mipmap-hdpi/ic_launcher_round.webp diff --git a/mobile/android/android-components/samples/firefox-relay/src/main/res/mipmap-mdpi/ic_launcher.webp b/mobile/android/android-components/samples/firefox-relay/src/main/res/mipmap-mdpi/ic_launcher.webp diff --git a/mobile/android/android-components/samples/firefox-relay/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/mobile/android/android-components/samples/firefox-relay/src/main/res/mipmap-mdpi/ic_launcher_round.webp diff --git a/mobile/android/android-components/samples/firefox-relay/src/main/res/mipmap-xhdpi/ic_launcher.webp b/mobile/android/android-components/samples/firefox-relay/src/main/res/mipmap-xhdpi/ic_launcher.webp diff --git a/mobile/android/android-components/samples/firefox-relay/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/mobile/android/android-components/samples/firefox-relay/src/main/res/mipmap-xhdpi/ic_launcher_round.webp diff --git a/mobile/android/android-components/samples/firefox-relay/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/mobile/android/android-components/samples/firefox-relay/src/main/res/mipmap-xxhdpi/ic_launcher.webp diff --git a/mobile/android/android-components/samples/firefox-relay/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/mobile/android/android-components/samples/firefox-relay/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp diff --git a/mobile/android/android-components/samples/firefox-relay/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/mobile/android/android-components/samples/firefox-relay/src/main/res/mipmap-xxxhdpi/ic_launcher.webp diff --git a/mobile/android/android-components/samples/firefox-relay/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/mobile/android/android-components/samples/firefox-relay/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp diff --git a/mobile/android/android-components/samples/firefox-relay/src/main/res/values/strings.xml b/mobile/android/android-components/samples/firefox-relay/src/main/res/values/strings.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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/. --> +<resources> + <string name="app_name" translatable="false">Relay Android Demo</string> + <string name="sign_in_webview" translatable="false">FxA sign in: webview</string> + <!-- %1$s is the account's display name. --> + <string name="signed_in" translatable="false">Signed in: %1$s</string> + <string name="log_out" translatable="false">FxA Log Out</string> + <string name="relay_addresses" translatable="false">Relay Addresses</string> + <string name="logged_out" translatable="false">Logged out!</string> +</resources> diff --git a/mobile/android/android-components/samples/firefox-relay/src/main/res/xml/backup_rules.xml b/mobile/android/android-components/samples/firefox-relay/src/main/res/xml/backup_rules.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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/. --> + +<full-backup-content> + <include domain="sharedpref" path="."/> +</full-backup-content> diff --git a/mobile/android/android-components/samples/firefox-relay/src/main/res/xml/data_extraction_rules.xml b/mobile/android/android-components/samples/firefox-relay/src/main/res/xml/data_extraction_rules.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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/. --> +<data-extraction-rules> + <cloud-backup> + <include domain="sharedpref" path="."/> + </cloud-backup> +</data-extraction-rules> diff --git a/taskcluster/config.yml b/taskcluster/config.yml @@ -295,6 +295,7 @@ treeherder: 'samples-crash': 'samples-crash' 'samples-dataprotect': 'samples-dataprotect' 'samples-firefox-accounts': 'samples-firefox-accounts' + 'samples-firefox-relay': 'samples-firefox-relay' 'samples-glean-library': 'samples-glean-library' 'samples-glean': 'samples-glean' 'samples-sync-logins': 'samples-sync-logins'