11package org.mozilla.firefoxsend
22
3-
4- import android.support.v7.app.AppCompatActivity
5- import android.os.Bundle
6- import im.delight.android.webview.AdvancedWebView
7- import android.graphics.Bitmap
8- import android.content.Intent
93import android.annotation.SuppressLint
104import android.content.ComponentName
5+ import android.content.Intent
6+ import android.graphics.Bitmap
117import android.net.Uri
12- import android.webkit.WebView
13- import android.webkit.WebMessage
14- import android.util.Log
8+ import android.os.Bundle
9+ import android.support.v7.app.AppCompatActivity
1510import android.util.Base64
11+ import android.util.Log
1612import android.view.View
17- import android.webkit.ConsoleMessage
18- import android.webkit.JavascriptInterface
19- import android.webkit.WebChromeClient
13+ import android.webkit.*
14+ import im.delight. android.webview.AdvancedWebView
15+ import kotlinx. android.synthetic.main.activity_main.*
2016import mozilla.components.service.fxa.Config
2117import mozilla.components.service.fxa.FirefoxAccount
22- import mozilla.components.service.fxa.Profile
2318import mozilla.components.service.fxa.FxaResult
19+ import org.json.JSONObject
2420
2521internal class LoggingWebChromeClient : WebChromeClient () {
2622 override fun onConsoleMessage (cm : ConsoleMessage ): Boolean {
27- Log .w( " CONTENT " , String .format(" %s @ %d: %s" ,
23+ Log .d( TAG , String .format(" %s @ %d: %s" ,
2824 cm.message(), cm.lineNumber(), cm.sourceId()))
2925 return true
3026 }
27+
28+ companion object {
29+ private const val TAG = " CONTENT"
30+ }
3131}
3232
3333class WebAppInterface (private val mContext : MainActivity ) {
3434 @JavascriptInterface
3535 fun beginOAuthFlow () {
36- mContext.beginOAuthFlow();
36+ mContext.beginOAuthFlow()
3737 }
3838
3939 @JavascriptInterface
@@ -43,176 +43,176 @@ class WebAppInterface(private val mContext: MainActivity) {
4343}
4444
4545class MainActivity : AppCompatActivity (), AdvancedWebView.Listener {
46- private var mWebView : AdvancedWebView ? = null
46+
4747 private var mToShare: String? = null
4848 private var mToCall: String? = null
4949 private var mAccount: FirefoxAccount ? = null
5050
51+ @SuppressLint(" SetJavaScriptEnabled" )
5152 override fun onCreate (savedInstanceState : Bundle ? ) {
5253 super .onCreate(savedInstanceState)
5354 setContentView(R .layout.activity_main)
5455
55- // https://developers.google.com/web/tools/chrome-devtools/remote-debugging/webviews
56- // WebView.setWebContentsDebuggingEnabled(true); // TODO only dev builds
57-
58- mWebView = findViewById<WebView >(R .id.webview) as AdvancedWebView
59- mWebView!! .setListener(this , this )
60- mWebView!! .setWebChromeClient(LoggingWebChromeClient ())
61- mWebView!! .addJavascriptInterface(WebAppInterface (this ), " Android" )
62- mWebView!! .setLayerType(View .LAYER_TYPE_HARDWARE , null );
63-
64- val webSettings = mWebView!! .getSettings()
65- webSettings.setUserAgentString(" Send Android" )
66- webSettings.setAllowUniversalAccessFromFileURLs(true )
67- webSettings.setJavaScriptEnabled(true )
68-
69- val intent = getIntent()
70- val action = intent.getAction()
71- val type = intent.getType()
56+ WebView .setWebContentsDebuggingEnabled(BuildConfig .DEBUG )
57+ webView.apply {
58+ setListener(this @MainActivity, this @MainActivity)
59+ addJavascriptInterface(WebAppInterface (this @MainActivity), JS_INTERFACE_NAME )
60+ setLayerType(View .LAYER_TYPE_HARDWARE , null )
61+ webChromeClient = LoggingWebChromeClient ()
62+
63+ settings.apply {
64+ userAgentString = " Send Android"
65+ allowUniversalAccessFromFileURLs = true
66+ javaScriptEnabled = true
67+ }
68+ }
7269
73- if (Intent .ACTION_SEND .equals(action) && type != null ) {
74- if (type.equals(" text/plain" )) {
70+ val type = intent.type
71+ if (Intent .ACTION_SEND == intent.action && type != null ) {
72+ if (type == " text/plain" ) {
7573 val sharedText = intent.getStringExtra(Intent .EXTRA_TEXT )
76- Log .w( " INTENT " , " text/plain " + sharedText)
74+ Log .d( TAG_INTENT , " text/plain $ sharedText" )
7775 mToShare = " data:text/plain;base64," + Base64 .encodeToString(sharedText.toByteArray(), 16 ).trim()
7876 } else if (type.startsWith(" image/" )) {
7977 val imageUri = intent.getParcelableExtra(Intent .EXTRA_STREAM ) as Uri
80- Log .w( " INTENT " , " image/ " + imageUri)
78+ Log .d( TAG_INTENT , " image/ $ imageUri" )
8179 mToShare = " data:text/plain;base64," + Base64 .encodeToString(imageUri.path.toByteArray(), 16 ).trim()
8280 }
8381 }
84- mWebView!! .loadUrl(" file:///android_asset/android.html" )
85-
82+ webView.loadUrl(" file:///android_asset/android.html" )
8683 }
8784
8885 fun beginOAuthFlow () {
89- Config .release().then( fun ( value : Config ): FxaResult < Unit > {
86+ Config .release().then { value ->
9087 mAccount = FirefoxAccount (value, " 20f7931c9054d833" , " https://send.firefox.com/fxa/android-redirect.html" )
91- mAccount?.beginOAuthFlow(arrayOf(" profile" , " https://identity.mozilla.com/apps/send" ), true )?.then(fun (url : String ): FxaResult <Unit > {
92- Log .w(" CONFIG" , " GOT A URL " + url)
93- this @MainActivity.runOnUiThread({
94- mWebView!! .loadUrl(url)
95- })
96- return FxaResult .fromValue(Unit )
97- })
98- Log .w(" CONFIG" , " CREATED FIREFOXACCOUNT" )
99- return FxaResult .fromValue(Unit )
100- })
88+ mAccount?.beginOAuthFlow(arrayOf(" profile" , " https://identity.mozilla.com/apps/send" ), true )
89+ ?.then { url ->
90+ Log .d(TAG_CONFIG , " GOT A URL $url " )
91+ this @MainActivity.runOnUiThread {
92+ webView.loadUrl(url)
93+ }
94+ FxaResult .fromValue(Unit )
95+ }
96+ Log .d(TAG_CONFIG , " CREATED FIREFOXACCOUNT" )
97+ FxaResult .fromValue(Unit )
98+ }
10199 }
102100
103101 fun shareUrl (url : String ) {
104- val shareIntent = Intent ()
105- shareIntent.action = Intent .ACTION_SEND
106- shareIntent.type = " text/plain"
107- shareIntent.putExtra(Intent .EXTRA_TEXT , url)
102+ val shareIntent = Intent ().apply {
103+ action = Intent .ACTION_SEND
104+ type = " text/plain"
105+ putExtra(Intent .EXTRA_TEXT , url)
106+ }
107+
108+ val components = arrayOf(ComponentName (applicationContext, MainActivity ::class .java))
108109 val chooser = Intent .createChooser(shareIntent, " " )
109- chooser.putExtra(Intent .EXTRA_EXCLUDE_COMPONENTS , arrayOf(ComponentName (applicationContext, MainActivity ::class .java)))
110+ .putExtra(Intent .EXTRA_EXCLUDE_COMPONENTS , components)
111+
110112 startActivity(chooser)
111113 }
112114
113- @SuppressLint(" NewApi" )
114115 override fun onResume () {
115116 super .onResume()
116- mWebView!! .onResume()
117- // ...
117+ webView.onResume()
118118 }
119119
120- @SuppressLint(" NewApi" )
121120 override fun onPause () {
122- mWebView!! .onPause()
123- // ...
121+ webView.onPause()
124122 super .onPause()
125123 }
126124
127125 override fun onDestroy () {
128- mWebView!! .onDestroy()
129- // ...
126+ webView.onDestroy()
130127 super .onDestroy()
131128 }
132129
133130 override fun onActivityResult (requestCode : Int , resultCode : Int , intent : Intent ? ) {
134131 super .onActivityResult(requestCode, resultCode, intent)
135- mWebView!! .onActivityResult(requestCode, resultCode, intent)
136- // ...
132+ webView.onActivityResult(requestCode, resultCode, intent)
137133 }
138134
139135 override fun onBackPressed () {
140- if (! mWebView !! .onBackPressed()) {
136+ if (! webView .onBackPressed()) {
141137 return
142138 }
143- // ...
144139 super .onBackPressed()
145140 }
146141
147142 override fun onPageStarted (url : String , favicon : Bitmap ? ) {
148143 if (url.startsWith(" https://send.firefox.com/fxa/android-redirect.html" )) {
149144 // We load this here so the user doesn't see the android-redirect.html page
150- mWebView !! .loadUrl(" file:///android_asset/android.html" )
145+ webView .loadUrl(" file:///android_asset/android.html" )
151146
152- val parsed = Uri .parse(url)
153- val code = parsed.getQueryParameter(" code" )
154- val state = parsed.getQueryParameter(" state" )
155-
156- code?.let { code ->
157- state?.let { state ->
147+ val uri = Uri .parse(url)
148+ uri.getQueryParameter(" code" )?.let { code ->
149+ uri.getQueryParameter(" state" )?.let { state ->
158150 mAccount?.completeOAuthFlow(code, state)?.whenComplete { info ->
159- // displayAndPersistProfile(code, state)
160- val profile = mAccount?.getProfile(false )?.then(fun (profile : Profile ): FxaResult <Unit > {
161- val accessToken = info.accessToken
162- val keys = info.keys
163- val avatar = profile.avatar
164- val displayName = profile.displayName
165- val email = profile.email
166- val uid = profile.uid
167- val toPass = " {\" accessToken\" : \" ${accessToken} \" , \" keys\" : '${keys} ', \" avatar\" : \" ${avatar} \" , \" displayName\" : \" ${displayName} \" , \" email\" : \" ${email} \" , \" uid\" : \" ${uid} \" }"
168- mToCall = " finishLogin(${toPass} )"
169- this @MainActivity.runOnUiThread({
151+ mAccount?.getProfile(false )?.then { profile ->
152+ val profileJsonPayload = JSONObject ()
153+ .put(" accessToken" , info.accessToken)
154+ .put(" keys" , info.keys)
155+ .put(" avatar" , profile.avatar)
156+ .put(" displayName" , profile.displayName)
157+ .put(" email" , profile.email)
158+ .put(" uid" , profile.uid).toString()
159+ mToCall = " finishLogin($profileJsonPayload )"
160+ this @MainActivity.runOnUiThread {
170161 // Clear the history so that the user can't use the back button to see broken pages
171162 // that were inserted into the history by the login process.
172- mWebView !! .clearHistory()
163+ webView .clearHistory()
173164
174165 // We also reload this here because we need to make sure onPageFinished runs after mToCall has been set.
175166 // We can't guarantee that onPageFinished wasn't already called at this point.
176- mWebView!! .loadUrl(" file:///android_asset/android.html" )
177- })
178-
179-
180- return FxaResult .fromValue(Unit )
181- })
167+ webView.loadUrl(" file:///android_asset/android.html" )
168+ }
169+ FxaResult .fromValue(Unit )
170+ }
182171 }
183172 }
184173 }
185174 }
186- Log .w( " MAIN " , " onPageStarted" );
175+ Log .d( TAG_MAIN , " onPageStarted" )
187176 }
188177
189178 override fun onPageFinished (url : String ) {
190- Log .w( " MAIN " , " onPageFinished" )
179+ Log .d( TAG_MAIN , " onPageFinished" )
191180 if (mToShare != null ) {
192- Log .w( " INTENT " , mToShare)
181+ Log .d( TAG_INTENT , mToShare)
193182
194- mWebView? .postWebMessage(WebMessage (mToShare), Uri .EMPTY )
183+ webView .postWebMessage(WebMessage (mToShare), Uri .EMPTY )
195184 mToShare = null
196185 }
197186 if (mToCall != null ) {
198- this @MainActivity.runOnUiThread( {
199- mWebView? .evaluateJavascript(mToCall, fun ( value : String ) {
187+ this @MainActivity.runOnUiThread {
188+ webView .evaluateJavascript(mToCall) {
200189 mToCall = null
201- })
202- })
190+ }
191+ }
203192 }
204193 }
205194
206195 override fun onPageError (errorCode : Int , description : String , failingUrl : String ) {
207- Log .w( " MAIN " , " onPageError " + description)
196+ Log .d( TAG_MAIN , " onPageError( $errorCode , $ description, $failingUrl ) " )
208197 }
209198
210- override fun onDownloadRequested (url : String , suggestedFilename : String , mimeType : String , contentLength : Long , contentDisposition : String , userAgent : String ) {
211- Log .w(" MAIN" , " onDownloadRequested" )
199+ override fun onDownloadRequested (url : String ,
200+ suggestedFilename : String ,
201+ mimeType : String ,
202+ contentLength : Long ,
203+ contentDisposition : String ,
204+ userAgent : String ) {
205+ Log .d(TAG_MAIN , " onDownloadRequested" )
212206 }
213207
214208 override fun onExternalPageRequest (url : String ) {
215- Log .w( " MAIN " , " onExternalPageRequest" )
209+ Log .d( TAG_MAIN , " onExternalPageRequest( $url ) " )
216210 }
217211
212+ companion object {
213+ private const val TAG_MAIN = " MAIN"
214+ private const val TAG_INTENT = " INTENT"
215+ private const val TAG_CONFIG = " CONFIG"
216+ private const val JS_INTERFACE_NAME = " Android"
217+ }
218218}
0 commit comments