Implement the mechanics of fxa login on android, but don't show ui fo… (#1000)
* Implement the mechanics of fxa login on android, but don't show ui for it yet. Also, scopedKeys are not yet implemented. * Hopefully fix the package-lock conflict? * WIP on android scoped keys * Finish implementing login. * created android/user.js to handle android logins
This commit is contained in:
parent
ffac4ae5b1
commit
cab6f1bafb
17 changed files with 592 additions and 304 deletions
|
@ -8,7 +8,6 @@
|
|||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.support.v7.app.AppCompatActivity
|
|||
import android.os.Bundle
|
||||
import im.delight.android.webview.AdvancedWebView
|
||||
import android.graphics.Bitmap
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.annotation.SuppressLint
|
||||
import android.net.Uri
|
||||
|
@ -13,7 +14,13 @@ import android.webkit.WebMessage
|
|||
import android.util.Log
|
||||
import android.util.Base64
|
||||
import android.webkit.ConsoleMessage
|
||||
import android.webkit.JavascriptInterface
|
||||
import android.webkit.WebChromeClient
|
||||
import mozilla.components.service.fxa.Config
|
||||
import mozilla.components.service.fxa.FirefoxAccount
|
||||
import mozilla.components.service.fxa.OAuthInfo
|
||||
import mozilla.components.service.fxa.Profile
|
||||
import mozilla.components.service.fxa.FxaResult
|
||||
|
||||
internal class LoggingWebChromeClient : WebChromeClient() {
|
||||
override fun onConsoleMessage(cm: ConsoleMessage): Boolean {
|
||||
|
@ -23,9 +30,18 @@ internal class LoggingWebChromeClient : WebChromeClient() {
|
|||
}
|
||||
}
|
||||
|
||||
class WebAppInterface(private val mContext: MainActivity) {
|
||||
@JavascriptInterface
|
||||
fun beginOAuthFlow() {
|
||||
mContext.beginOAuthFlow();
|
||||
}
|
||||
}
|
||||
|
||||
class MainActivity : AppCompatActivity(), AdvancedWebView.Listener {
|
||||
private var mWebView: AdvancedWebView? = null
|
||||
private var mToShare: String? = null
|
||||
private var mToCall: String? = null
|
||||
private var mAccount: FirefoxAccount? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
@ -34,14 +50,17 @@ class MainActivity : AppCompatActivity(), AdvancedWebView.Listener {
|
|||
mWebView = findViewById<WebView>(R.id.webview) as AdvancedWebView
|
||||
mWebView!!.setListener(this, this)
|
||||
mWebView!!.setWebChromeClient(LoggingWebChromeClient())
|
||||
mWebView!!.addJavascriptInterface(WebAppInterface(this), "Android")
|
||||
|
||||
val webSettings = mWebView!!.getSettings()
|
||||
webSettings.setUserAgentString("Send Android")
|
||||
webSettings.setAllowUniversalAccessFromFileURLs(true)
|
||||
webSettings.setJavaScriptEnabled(true)
|
||||
|
||||
val intent = getIntent()
|
||||
val action = intent.getAction()
|
||||
val type = intent.getType()
|
||||
|
||||
if (Intent.ACTION_SEND.equals(action) && type != null) {
|
||||
if (type.equals("text/plain")) {
|
||||
val sharedText = intent.getStringExtra(Intent.EXTRA_TEXT)
|
||||
|
@ -51,12 +70,25 @@ class MainActivity : AppCompatActivity(), AdvancedWebView.Listener {
|
|||
val imageUri = intent.getParcelableExtra(Intent.EXTRA_STREAM) as Uri
|
||||
Log.w("INTENT", "image/ " + imageUri)
|
||||
mToShare = "data:text/plain;base64," + Base64.encodeToString(imageUri.path.toByteArray(), 16).trim()
|
||||
|
||||
// TODO Currently this causes a Permission Denied error
|
||||
// val stream = contentResolver.openInputStream(imageUri)
|
||||
}
|
||||
}
|
||||
mWebView!!.loadUrl("file:///android_asset/android.html")
|
||||
|
||||
}
|
||||
|
||||
fun beginOAuthFlow() {
|
||||
Config.custom("https://send-fxa.dev.lcip.org").then(fun (value: Config): FxaResult<Unit> {
|
||||
mAccount = FirefoxAccount(value, "12cc4070a481bc73", "fxaclient://android.redirect")
|
||||
mAccount?.beginOAuthFlow(arrayOf("profile", "https://identity.mozilla.com/apps/send"), true)?.then(fun (url: String): FxaResult<Unit> {
|
||||
Log.w("CONFIG", "GOT A URL " + url)
|
||||
this@MainActivity.runOnUiThread({
|
||||
mWebView!!.loadUrl(url)
|
||||
})
|
||||
return FxaResult.fromValue(Unit)
|
||||
})
|
||||
Log.w("CONFIG", "CREATED FIREFOXACCOUNT")
|
||||
return FxaResult.fromValue(Unit)
|
||||
})
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
|
@ -94,7 +126,48 @@ class MainActivity : AppCompatActivity(), AdvancedWebView.Listener {
|
|||
}
|
||||
|
||||
override fun onPageStarted(url: String, favicon: Bitmap?) {
|
||||
if (url.startsWith("fxaclient")) {
|
||||
// We load this here so the user doesn't see an ugly screen that says "can't handle fxaclient urls"...
|
||||
mWebView!!.loadUrl("file:///android_asset/android.html")
|
||||
|
||||
val parsed = Uri.parse(url)
|
||||
val code = parsed.getQueryParameter("code")
|
||||
val state = parsed.getQueryParameter("state")
|
||||
|
||||
code?.let { code ->
|
||||
state?.let { state ->
|
||||
mAccount?.completeOAuthFlow(code, state)?.whenComplete { info ->
|
||||
//displayAndPersistProfile(code, state)
|
||||
val profile = mAccount?.getProfile(false)?.then(fun (profile: Profile): FxaResult<Unit> {
|
||||
val accessToken = info.accessToken
|
||||
val keys = info.keys
|
||||
val avatar = profile.avatar
|
||||
val displayName = profile.displayName
|
||||
val email = profile.email
|
||||
val uid = profile.uid
|
||||
val toPass = "{\"accessToken\": \"${accessToken}}\", \"keys\": '${keys}', \"avatar\": \"${avatar}\", \"displayName\": \"${displayName}\", \"email\": \"${email}\", \"uid\": \"${uid}\"}"
|
||||
mToCall = "finishLogin(${toPass})"
|
||||
this@MainActivity.runOnUiThread({
|
||||
// But then we also reload this here because we need to make sure onPageFinished runs after mToCall has been set.
|
||||
// We can't guarantee that onPageFinished has already been called at this point.
|
||||
mWebView!!.loadUrl("file:///android_asset/android.html")
|
||||
})
|
||||
|
||||
|
||||
return FxaResult.fromValue(Unit)
|
||||
})
|
||||
|
||||
// TODO get k from it.keys
|
||||
// TODO get profile from mAccount.getProfile
|
||||
// TODO get access_token
|
||||
|
||||
//mToShare = "data:text/plain;base64," + Base64.encodeToString(toSend.toByteArray(), 16).trim()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Log.w("MAIN", "onPageStarted");
|
||||
// account.completeOAuthFlow()
|
||||
}
|
||||
|
||||
override fun onPageFinished(url: String) {
|
||||
|
@ -102,14 +175,22 @@ class MainActivity : AppCompatActivity(), AdvancedWebView.Listener {
|
|||
if (mToShare != null) {
|
||||
Log.w("INTENT", mToShare)
|
||||
|
||||
val webView = findViewById<WebView>(R.id.webview) as AdvancedWebView
|
||||
webView.postWebMessage(WebMessage(mToShare), Uri.EMPTY)
|
||||
mWebView?.postWebMessage(WebMessage(mToShare), Uri.EMPTY)
|
||||
mToShare = null
|
||||
}
|
||||
if (mToCall != null) {
|
||||
this@MainActivity.runOnUiThread({
|
||||
mWebView?.evaluateJavascript(mToCall, fun (value: String) {
|
||||
// noop
|
||||
})
|
||||
})
|
||||
|
||||
mToCall = null
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPageError(errorCode: Int, description: String, failingUrl: String) {
|
||||
Log.w("MAIN", "onPageError")
|
||||
Log.w("MAIN", "onPageError " + description)
|
||||
}
|
||||
|
||||
override fun onDownloadRequested(url: String, suggestedFilename: String, mimeType: String, contentLength: Long, contentDisposition: String, userAgent: String) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue