aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAllan Wang <me@allanwang.ca>2021-01-24 19:10:09 -0800
committerAllan Wang <me@allanwang.ca>2021-01-24 19:10:09 -0800
commit58068ce55e9e203a77c67dfee78fb2658e3bb6aa (patch)
treeaed233a587838d42caccdd771a52a1f4471d8092
parentbe88f69e7863b8df2923ab456481e419de29b33b (diff)
downloadfrost-58068ce55e9e203a77c67dfee78fb2658e3bb6aa.tar.gz
frost-58068ce55e9e203a77c67dfee78fb2658e3bb6aa.tar.bz2
frost-58068ce55e9e203a77c67dfee78fb2658e3bb6aa.zip
Create messenger client with cookie checking
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/db/CookiesDb.kt3
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/FbConst.kt1
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt4
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragments.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt20
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoViewer.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/views/FrostWebView.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt55
-rw-r--r--app/src/test/kotlin/com/pitchedapps/frost/facebook/FbConstTest.kt37
10 files changed, 101 insertions, 27 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/db/CookiesDb.kt b/app/src/main/kotlin/com/pitchedapps/frost/db/CookiesDb.kt
index 163d151b..8c2e32a7 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/db/CookiesDb.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/db/CookiesDb.kt
@@ -44,7 +44,8 @@ data class CookieEntity(
) : Parcelable {
override fun toString(): String = "CookieEntity(${hashCode()})"
- fun toSensitiveString(): String = "CookieEntity(id=$id, name=$name, cookie=$cookie)"
+ fun toSensitiveString(): String =
+ "CookieEntity(id=$id, name=$name, cookie=$cookie cookieMessenger=$cookieMessenger)"
}
@Dao
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbConst.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbConst.kt
index fc4e3fae..b0846864 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbConst.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbConst.kt
@@ -34,6 +34,7 @@ const val FB_URL_MBASIC_BASE = "https://$FACEBOOK_MBASIC_COM/"
fun profilePictureUrl(id: Long) = "https://graph.facebook.com/$id/picture?type=large"
const val FB_LOGIN_URL = "${FB_URL_BASE}login"
const val FB_HOME_URL = "${FB_URL_BASE}home.php"
+const val MESSENGER_THREAD_PREFIX = "$HTTPS_MESSENGER_COM/t/"
/*
* User agent candidates.
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt
index b02ec941..4e932d09 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt
@@ -24,7 +24,6 @@ import com.pitchedapps.frost.db.CookieEntity
import com.pitchedapps.frost.db.deleteById
import com.pitchedapps.frost.db.save
import com.pitchedapps.frost.db.selectById
-import com.pitchedapps.frost.db.updateMessengerCookie
import com.pitchedapps.frost.prefs.Prefs
import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.utils.cookies
@@ -121,11 +120,8 @@ class FbCookie(private val prefs: Prefs, private val cookieDao: CookieDao) {
L.d { "Switching User; null cookie" }
return
}
- val currentId = prefs.userId
withContext(Dispatchers.Main + NonCancellable) {
L.d { "Switching User" }
- // Save current messenger cookie state.
- cookieDao.updateMessengerCookie(currentId, messengerCookie)
prefs.userId = cookie.id
CookieManager.getInstance().apply {
removeAllCookies()
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragments.kt b/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragments.kt
index 502c37fb..3cac92af 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragments.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragments.kt
@@ -26,6 +26,7 @@ import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.views.FrostWebView
import com.pitchedapps.frost.web.FrostWebViewClient
import com.pitchedapps.frost.web.FrostWebViewClientMenu
+import com.pitchedapps.frost.web.FrostWebViewClientMessenger
/**
* Created by Allan Wang on 27/12/17.
@@ -41,6 +42,7 @@ class WebFragment : BaseFragment() {
* Given a webview, output a client
*/
fun client(web: FrostWebView) = when (baseEnum) {
+ FbItem.MESSENGER -> FrostWebViewClientMessenger(web)
FbItem.MENU -> FrostWebViewClientMenu(web)
else -> FrostWebViewClient(web)
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt
index 2d3a10c8..13ce2920 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt
@@ -35,6 +35,7 @@ import ca.allanwang.kau.email.sendEmail
import ca.allanwang.kau.mediapicker.createMediaFile
import ca.allanwang.kau.mediapicker.createPrivateMediaFile
import ca.allanwang.kau.utils.colorToForeground
+import ca.allanwang.kau.utils.ctxCoroutine
import ca.allanwang.kau.utils.darken
import ca.allanwang.kau.utils.isColorDark
import ca.allanwang.kau.utils.navigationBarColor
@@ -77,8 +78,6 @@ import java.net.URLEncoder
import java.nio.charset.StandardCharsets
import java.util.ArrayList
import java.util.Locale
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import org.apache.commons.text.StringEscapeUtils
@@ -98,14 +97,6 @@ const val ARG_IMAGE_URL = "arg_image_url"
const val ARG_TEXT = "arg_text"
const val ARG_COOKIE = "arg_cookie"
-/**
- * Most context items implement [CoroutineScope] by default.
- * We will add a fallback just in case.
- * It is expected that the scope returned always has the Android main dispatcher as part of the context.
- */
-internal inline val Context.ctxCoroutine: CoroutineScope
- get() = this as? CoroutineScope ?: GlobalScope
-
inline fun <reified T : Activity> Context.launchNewTask(
cookieList: ArrayList<CookieEntity> = arrayListOf(),
clearStack: Boolean = false
@@ -186,7 +177,9 @@ fun WebOverlayActivity.url(): String {
fun Activity.setFrostTheme(themeProvider: ThemeProvider, forceTransparent: Boolean = false) {
val isTransparent =
- forceTransparent || (Color.alpha(themeProvider.bgColor) != 255) || (Color.alpha(themeProvider.headerColor) != 255)
+ forceTransparent || (Color.alpha(themeProvider.bgColor) != 255) || (Color.alpha(
+ themeProvider.headerColor
+ ) != 255)
if (themeProvider.bgColor.isColorDark) {
setTheme(if (isTransparent) R.style.FrostTheme_Transparent else R.style.FrostTheme)
} else {
@@ -313,7 +306,10 @@ inline val String?.isFacebookUrl
get() = this != null && (contains(FACEBOOK_COM) || contains(FBCDN_NET))
inline val String?.isMessengerUrl
-get() = this != null && contains(MESSENGER_COM)
+ get() = this != null && contains(MESSENGER_COM)
+
+inline val String?.isFbCookie
+ get() = this != null && contains("c_user")
/**
* [true] if url is a video and can be accepted by VideoViewer
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoViewer.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoViewer.kt
index 169e7f73..a76aeea0 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoViewer.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoViewer.kt
@@ -25,6 +25,7 @@ import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.ViewTreeObserver
import android.widget.FrameLayout
+import ca.allanwang.kau.utils.ctxCoroutine
import ca.allanwang.kau.utils.fadeIn
import ca.allanwang.kau.utils.fadeOut
import ca.allanwang.kau.utils.gone
@@ -46,7 +47,6 @@ import com.pitchedapps.frost.db.currentCookie
import com.pitchedapps.frost.injectors.ThemeProvider
import com.pitchedapps.frost.prefs.Prefs
import com.pitchedapps.frost.utils.L
-import com.pitchedapps.frost.utils.ctxCoroutine
import com.pitchedapps.frost.utils.frostDownload
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostWebView.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostWebView.kt
index e4752d1b..ecd8c093 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostWebView.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostWebView.kt
@@ -24,6 +24,7 @@ import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import ca.allanwang.kau.utils.AnimHolder
+import ca.allanwang.kau.utils.ctxCoroutine
import ca.allanwang.kau.utils.launchMain
import com.pitchedapps.frost.contracts.FrostContentContainer
import com.pitchedapps.frost.contracts.FrostContentCore
@@ -37,7 +38,6 @@ import com.pitchedapps.frost.fragments.WebFragment
import com.pitchedapps.frost.injectors.ThemeProvider
import com.pitchedapps.frost.prefs.Prefs
import com.pitchedapps.frost.utils.L
-import com.pitchedapps.frost.utils.ctxCoroutine
import com.pitchedapps.frost.utils.frostDownload
import com.pitchedapps.frost.web.FrostChromeClient
import com.pitchedapps.frost.web.FrostJSI
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt
index 4e8e8cee..12e10e10 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt
@@ -18,6 +18,7 @@ package com.pitchedapps.frost.web
import android.content.Context
import android.webkit.JavascriptInterface
+import ca.allanwang.kau.utils.ctxCoroutine
import com.pitchedapps.frost.activities.MainActivity
import com.pitchedapps.frost.activities.WebOverlayActivityBase
import com.pitchedapps.frost.contracts.MainActivityContract
@@ -28,7 +29,6 @@ import com.pitchedapps.frost.prefs.Prefs
import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.utils.WebContext
import com.pitchedapps.frost.utils.cookies
-import com.pitchedapps.frost.utils.ctxCoroutine
import com.pitchedapps.frost.utils.isIndependent
import com.pitchedapps.frost.utils.launchImageActivity
import com.pitchedapps.frost.utils.showWebContextMenu
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt
index 8ec5f975..1495b2e0 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt
@@ -22,11 +22,17 @@ import android.webkit.WebResourceRequest
import android.webkit.WebResourceResponse
import android.webkit.WebView
import android.webkit.WebViewClient
+import ca.allanwang.kau.utils.ctxCoroutine
import ca.allanwang.kau.utils.withAlpha
+import com.pitchedapps.frost.db.CookieDao
+import com.pitchedapps.frost.db.currentCookie
+import com.pitchedapps.frost.db.updateMessengerCookie
import com.pitchedapps.frost.enums.ThemeCategory
import com.pitchedapps.frost.facebook.FACEBOOK_BASE_COM
import com.pitchedapps.frost.facebook.FbCookie
import com.pitchedapps.frost.facebook.FbItem
+import com.pitchedapps.frost.facebook.HTTPS_MESSENGER_COM
+import com.pitchedapps.frost.facebook.MESSENGER_THREAD_PREFIX
import com.pitchedapps.frost.facebook.WWW_FACEBOOK_COM
import com.pitchedapps.frost.facebook.formattedFbUrl
import com.pitchedapps.frost.injectors.CssAsset
@@ -39,6 +45,7 @@ import com.pitchedapps.frost.prefs.Prefs
import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.utils.isExplicitIntent
import com.pitchedapps.frost.utils.isFacebookUrl
+import com.pitchedapps.frost.utils.isFbCookie
import com.pitchedapps.frost.utils.isImageUrl
import com.pitchedapps.frost.utils.isIndirectImageUrl
import com.pitchedapps.frost.utils.isMessengerUrl
@@ -46,6 +53,7 @@ import com.pitchedapps.frost.utils.launchImageActivity
import com.pitchedapps.frost.utils.resolveActivityForUri
import com.pitchedapps.frost.views.FrostWebView
import kotlinx.coroutines.channels.SendChannel
+import kotlinx.coroutines.launch
/**
* Created by Allan Wang on 2017-05-31.
@@ -71,11 +79,11 @@ open class BaseWebViewClient : WebViewClient() {
*/
open class FrostWebViewClient(val web: FrostWebView) : BaseWebViewClient() {
- private val fbCookie: FbCookie get() = web.fbCookie
- private val prefs: Prefs get() = web.prefs
- private val themeProvider: ThemeProvider get() = web.themeProvider
- private val refresh: SendChannel<Boolean> = web.parent.refreshChannel
- private val isMain = web.parent.baseEnum != null
+ protected val fbCookie: FbCookie get() = web.fbCookie
+ protected val prefs: Prefs get() = web.prefs
+ protected val themeProvider: ThemeProvider get() = web.themeProvider
+ protected val refresh: SendChannel<Boolean> = web.parent.refreshChannel
+ protected val isMain = web.parent.baseEnum != null
/**
* True if current url supports refresh. See [doUpdateVisitedHistory] for updates
@@ -279,8 +287,6 @@ private const val EMIT_FINISH = 0
*/
class FrostWebViewClientMenu(web: FrostWebView) : FrostWebViewClient(web) {
- private val prefs: Prefs get() = web.prefs
-
override fun onPageFinished(view: WebView, url: String?) {
super.onPageFinished(view, url)
if (url == null) {
@@ -302,3 +308,38 @@ class FrostWebViewClientMenu(web: FrostWebView) : FrostWebViewClient(web) {
// Skip
}
}
+
+class FrostWebViewClientMessenger(web: FrostWebView) : FrostWebViewClient(web) {
+
+ override fun onPageFinished(view: WebView, url: String?) {
+ super.onPageFinished(view, url)
+ messengerCookieCheck(url!!)
+ }
+
+ private val cookieDao: CookieDao get() = web.cookieDao
+ private var hasCookie = fbCookie.messengerCookie.isFbCookie
+
+ /**
+ * Check cookie changes. Unlike fb checks, we will continuously poll for cookie changes during loading.
+ * There is no lifecycle association between messenger login and facebook login,
+ * so we'll try to be smart about when to check for state changes.
+ *
+ * From testing, it looks like this is called after redirects.
+ * We can therefore classify no login as pointing to messenger.com,
+ * and login as pointing to messenger.com/t/[thread id]
+ */
+ private fun messengerCookieCheck(url: String?) {
+ if (url?.startsWith(HTTPS_MESSENGER_COM) != true) return
+ val shouldHaveCookie = url.startsWith(MESSENGER_THREAD_PREFIX)
+ L._d { "Messenger client: $url $shouldHaveCookie" }
+ if (shouldHaveCookie == hasCookie) return
+ hasCookie = shouldHaveCookie
+ web.context.ctxCoroutine.launch {
+ cookieDao.updateMessengerCookie(
+ prefs.userId,
+ if (shouldHaveCookie) fbCookie.messengerCookie else null
+ )
+ L._d { "New cookie ${cookieDao.currentCookie(prefs)?.toSensitiveString()}" }
+ }
+ }
+}
diff --git a/app/src/test/kotlin/com/pitchedapps/frost/facebook/FbConstTest.kt b/app/src/test/kotlin/com/pitchedapps/frost/facebook/FbConstTest.kt
new file mode 100644
index 00000000..8a8c42d6
--- /dev/null
+++ b/app/src/test/kotlin/com/pitchedapps/frost/facebook/FbConstTest.kt
@@ -0,0 +1,37 @@
+package com.pitchedapps.frost.facebook
+
+import kotlin.test.Test
+import kotlin.test.assertFalse
+
+class FbConstTest {
+
+ private val constants = listOf(
+ FACEBOOK_COM,
+ MESSENGER_COM,
+ FBCDN_NET,
+ WWW_FACEBOOK_COM,
+ WWW_MESSENGER_COM,
+ HTTPS_FACEBOOK_COM,
+ HTTPS_MESSENGER_COM,
+ FACEBOOK_BASE_COM,
+ FB_URL_BASE,
+ FACEBOOK_MBASIC_COM,
+ FB_URL_MBASIC_BASE,
+ FB_LOGIN_URL,
+ FB_HOME_URL,
+ MESSENGER_THREAD_PREFIX
+ )
+
+ /**
+ * Make sure we don't have accidental double forward slashes after appending
+ */
+ @Test
+ fun doubleForwardSlashTest() {
+ constants.forEach {
+ assertFalse(
+ it.replace("https://", "").contains("//"),
+ "Accidental forward slash for $it"
+ )
+ }
+ }
+} \ No newline at end of file