mirror of
https://github.com/AllanWang/Frost-for-Facebook.git
synced 2024-11-09 20:42:34 +01:00
implement cache db and start js injections
This commit is contained in:
parent
c53e343f03
commit
9a41937a33
@ -1,6 +1,7 @@
|
||||
package com.pitchedapps.frost
|
||||
|
||||
import android.app.Application
|
||||
import com.pitchedapps.frost.facebook.FbCookie
|
||||
import com.pitchedapps.frost.facebook.retro.FrostApi
|
||||
import com.pitchedapps.frost.utils.CrashReportingTree
|
||||
import com.pitchedapps.frost.utils.Prefs
|
||||
@ -21,6 +22,7 @@ class FrostApp : Application() {
|
||||
FlowManager.init(FlowConfig.Builder(this).build())
|
||||
Prefs(this)
|
||||
FrostApi(this)
|
||||
FbCookie.init()
|
||||
super.onCreate()
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,14 @@
|
||||
package com.pitchedapps.frost.dbflow
|
||||
|
||||
import com.pitchedapps.frost.facebook.FbCookie
|
||||
import com.pitchedapps.frost.utils.L
|
||||
import com.pitchedapps.frost.utils.Prefs
|
||||
import com.raizlabs.android.dbflow.annotation.ConflictAction
|
||||
import com.raizlabs.android.dbflow.annotation.Database
|
||||
import com.raizlabs.android.dbflow.annotation.ForeignKey
|
||||
import com.raizlabs.android.dbflow.annotation.PrimaryKey
|
||||
import com.raizlabs.android.dbflow.annotation.Table
|
||||
import com.raizlabs.android.dbflow.kotlinextensions.*
|
||||
import com.raizlabs.android.dbflow.structure.BaseModel
|
||||
import okhttp3.Cookie
|
||||
import java.io.Serializable
|
||||
|
||||
/**
|
||||
* Created by Allan Wang on 2017-05-30.
|
||||
@ -18,43 +20,13 @@ object CookiesDb {
|
||||
const val VERSION = 1
|
||||
}
|
||||
|
||||
//@Database(name = CookieDb.NAME, version = CookieDb.VERSION)
|
||||
//object CookieDb {
|
||||
// const val NAME = "Cookie"
|
||||
// const val VERSION = 1
|
||||
//}
|
||||
@Table(database = CookiesDb::class, allFields = true, primaryKeyConflict = ConflictAction.REPLACE)
|
||||
data class CookieModel(@PrimaryKey var id: Long = Prefs.userIdDefault, var cookie: String? = null) : BaseModel()
|
||||
|
||||
@Table(database = CookiesDb::class, allFields = true)
|
||||
data class CookieModel(@PrimaryKey var name: String,
|
||||
var value: String,
|
||||
var expiresAt: Long,
|
||||
var domain: String,
|
||||
var path: String,
|
||||
var secure: Boolean,
|
||||
var httpOnly: Boolean) {
|
||||
fun loadFbCookie(): CookieModel? = (select from CookieModel::class where (CookieModel_Table.id eq Prefs.userId)).querySingle()
|
||||
|
||||
constructor(cookie: Cookie) : this(cookie.name(), cookie.value(), cookie.expiresAt(), cookie.domain(), cookie.path(), cookie.secure(), cookie.httpOnly())
|
||||
constructor() : this("", "", 0L, "", "", false, false)
|
||||
|
||||
fun toCookie(): Cookie {
|
||||
val builder = Cookie.Builder().name(name).value(value).expiresAt(expiresAt).domain(domain).path(path)
|
||||
if (secure) builder.secure()
|
||||
if (httpOnly) builder.httpOnly()
|
||||
return builder.build()
|
||||
fun saveFbCookie() {
|
||||
CookieModel(FbCookie.userId, FbCookie.webCookie).async save {
|
||||
L.d("Fb cookie saved")
|
||||
}
|
||||
|
||||
fun isSecure() = secure
|
||||
fun isHttpOnly() = httpOnly
|
||||
}
|
||||
|
||||
//class CookieList(val cookies: List<Cookie>)
|
||||
//class CookieDbList(val cookies: List<CookieDb>)
|
||||
|
||||
//@com.raizlabs.android.dbflow.annotation.TypeConverter
|
||||
//class CookieTypeConverter() : TypeConverter<CookieDbList, CookieList>() {
|
||||
// override fun getModelValue(data: CookieDbList): CookieList = CookieList(data.cookies.map { it.toCookie() })
|
||||
// override fun getDBValue(model: CookieList): CookieDbList = CookieDbList(model.cookies.map { CookieDb(it) })
|
||||
//}
|
||||
|
||||
@Table(database = CookiesDb::class)
|
||||
data class Cookies(@PrimaryKey var url: String = "", @ForeignKey var cookie: CookieModel = CookieModel())
|
||||
}
|
@ -16,6 +16,7 @@ import com.raizlabs.android.dbflow.annotation.PrimaryKey
|
||||
import com.raizlabs.android.dbflow.annotation.Table
|
||||
import com.raizlabs.android.dbflow.kotlinextensions.from
|
||||
import com.raizlabs.android.dbflow.sql.language.SQLite
|
||||
import com.raizlabs.android.dbflow.structure.BaseModel
|
||||
|
||||
/**
|
||||
* Created by Allan Wang on 2017-05-30.
|
||||
@ -33,7 +34,7 @@ data class FbTab(val title: String, val icon: IIcon, val url: String)
|
||||
data class FbTabModel(
|
||||
var title: String = "",
|
||||
@ForeignKey(saveForeignKeyModel = true, deleteForeignKeyModel = false) var icon: IIconModel = IIconModel(),
|
||||
@PrimaryKey var url: String = "") {
|
||||
@PrimaryKey var url: String = "") : BaseModel() {
|
||||
constructor(fbTab: FbTab) : this(fbTab.title, IIconModel(fbTab.icon), fbTab.url)
|
||||
|
||||
fun toFbTab() = FbTab(title, icon.toIIcon(), url)
|
||||
@ -56,15 +57,19 @@ data class IIconModel(var type: Int = -1, @PrimaryKey var name: String = "") {
|
||||
}
|
||||
}
|
||||
|
||||
enum class FbUrl(@StringRes val titleId: Int, val icon: IIcon, val url: String) {
|
||||
LOGIN(R.string.feed, CommunityMaterial.Icon.cmd_newspaper, "https://www.facebook.com/v2.9/dialog/oauth?client_id=${FB_KEY}&redirect_uri=https://touch.facebook.com/&response_type=token,granted_scopes"),
|
||||
FEED(R.string.feed, CommunityMaterial.Icon.cmd_newspaper, "https://touch.facebook.com/"),
|
||||
PROFILE(R.string.profile, CommunityMaterial.Icon.cmd_account, "https://touch.facebook.com/me/"),
|
||||
EVENTS(R.string.events, GoogleMaterial.Icon.gmd_event, "https://touch.facebook.com/events/upcoming"),
|
||||
FRIENDS(R.string.friends, GoogleMaterial.Icon.gmd_people, "https://touch.facebook.com/friends/center/requests/"),
|
||||
MESSAGES(R.string.messages, MaterialDesignIconic.Icon.gmi_comments, "https://touch.facebook.com/messages"),
|
||||
NOTIFICATIONS(R.string.notifications, MaterialDesignIconic.Icon.gmi_globe, "https://touch.facebook.com/notifications");
|
||||
const val FB_URL_BASE = "https://m.facebook.com/"
|
||||
//const val FB_URL_BASE = "https://touch.facebook.com/"
|
||||
|
||||
enum class FbUrl(@StringRes val titleId: Int, val icon: IIcon, relativeUrl: String) {
|
||||
// LOGIN(R.string.feed, CommunityMaterial.Icon.cmd_newspaper, "https://www.facebook.com/v2.9/dialog/oauth?client_id=${FB_KEY}&redirect_uri=https://touch.facebook.com/&response_type=token,granted_scopes"),
|
||||
FEED(R.string.feed, CommunityMaterial.Icon.cmd_newspaper, ""),
|
||||
PROFILE(R.string.profile, CommunityMaterial.Icon.cmd_account, "me"),
|
||||
EVENTS(R.string.events, GoogleMaterial.Icon.gmd_event, "events/upcoming"),
|
||||
FRIENDS(R.string.friends, GoogleMaterial.Icon.gmd_people, "friends/center/requests"),
|
||||
MESSAGES(R.string.messages, MaterialDesignIconic.Icon.gmi_comments, "messages"),
|
||||
NOTIFICATIONS(R.string.notifications, MaterialDesignIconic.Icon.gmi_globe, "notifications");
|
||||
|
||||
val url = "$FB_URL_BASE$relativeUrl"
|
||||
fun tabInfo(c: Context) = FbTab(c.getString(titleId), icon, url)
|
||||
}
|
||||
|
||||
@ -79,7 +84,5 @@ fun loadFbTabs(c: Context): List<FbTab> {
|
||||
}
|
||||
|
||||
fun List<FbTab>.saveAsync(c: Context) {
|
||||
map { FbTabModel(it) }.replace(c, FbTabsDb.NAME, {
|
||||
L.e("Saved successfully")
|
||||
})
|
||||
map { FbTabModel(it) }.replace(c, FbTabsDb.NAME)
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package com.pitchedapps.frost.facebook
|
||||
|
||||
import android.webkit.CookieManager
|
||||
import com.pitchedapps.frost.utils.Prefs
|
||||
|
||||
/**
|
||||
* Created by Allan Wang on 2017-05-30.
|
||||
*/
|
||||
object CookieMap {
|
||||
|
||||
var userId: Int = -1
|
||||
private val userMatcher = "c_user=([0-9]*);"
|
||||
private val map = HashMap<String, String>()
|
||||
|
||||
operator fun get(key: String) = map[key]
|
||||
|
||||
operator fun set(key: String, value: String) {
|
||||
map[key] = value
|
||||
}
|
||||
|
||||
fun put(url: String, cookie: String) {
|
||||
map.put(url, cookie)
|
||||
checkUserId(url, cookie)
|
||||
}
|
||||
|
||||
fun checkUserId(url: String, cookie: String) {
|
||||
if (userId != -1) return
|
||||
if (!url.contains("facebook") || !cookie.contains(userMatcher)) return
|
||||
val id = Regex(userMatcher).find(cookie)?.value
|
||||
if (id != null) {
|
||||
userId = id.toInt()
|
||||
save()
|
||||
}
|
||||
}
|
||||
|
||||
fun save() {
|
||||
Prefs.userId = userId
|
||||
CookieManager.getInstance().flush()
|
||||
|
||||
}
|
||||
|
||||
fun reset() {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package com.pitchedapps.frost.facebook
|
||||
|
||||
import android.webkit.CookieManager
|
||||
import com.pitchedapps.frost.dbflow.FB_URL_BASE
|
||||
import com.pitchedapps.frost.dbflow.loadFbCookie
|
||||
import com.pitchedapps.frost.dbflow.saveFbCookie
|
||||
import com.pitchedapps.frost.utils.L
|
||||
import com.pitchedapps.frost.utils.Prefs
|
||||
|
||||
/**
|
||||
* Created by Allan Wang on 2017-05-30.
|
||||
*/
|
||||
object FbCookie {
|
||||
|
||||
var userId: Long = Prefs.userIdDefault
|
||||
var dbCookie: String? = null
|
||||
var webCookie: String?
|
||||
get() = CookieManager.getInstance().getCookie(FB_URL_BASE)
|
||||
set(value) = CookieManager.getInstance().setCookie(FB_URL_BASE, value)
|
||||
|
||||
fun init() {
|
||||
userId = Prefs.userId
|
||||
dbCookie = loadFbCookie()?.cookie
|
||||
if (dbCookie != null && webCookie == null) {
|
||||
L.d("DbCookie found & WebCookie is null; setting webcookie")
|
||||
webCookie = dbCookie
|
||||
}
|
||||
}
|
||||
|
||||
private val userMatcher: Regex by lazy { Regex("c_user=([0-9]*);") }
|
||||
|
||||
fun checkUserId(url: String, cookie: String?) {
|
||||
if (userId != Prefs.userIdDefault || cookie == null) return
|
||||
L.d("Checking cookie for $url\n\t$cookie")
|
||||
if (!url.contains("facebook") || !cookie.contains(userMatcher)) return
|
||||
val id = userMatcher.find(cookie)?.groups?.get(1)?.value
|
||||
if (id != null) {
|
||||
try {
|
||||
userId = id.toLong()
|
||||
save()
|
||||
} catch (e: NumberFormatException) {
|
||||
//todo send report that id has changed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun save() {
|
||||
L.d("New cookie found for $userId")
|
||||
Prefs.userId = userId
|
||||
CookieManager.getInstance().flush()
|
||||
saveFbCookie()
|
||||
}
|
||||
|
||||
//TODO reset when new account is added; reset and clear when account is logged out
|
||||
fun reset() {
|
||||
Prefs.userId = Prefs.userIdDefault
|
||||
userId = Prefs.userIdDefault
|
||||
with(CookieManager.getInstance()) {
|
||||
removeAllCookies(null)
|
||||
flush()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package com.pitchedapps.frost.injectors
|
||||
|
||||
import android.webkit.WebView
|
||||
|
||||
/**
|
||||
* Created by Allan Wang on 2017-05-31.
|
||||
*/
|
||||
class JsInjector {
|
||||
private val builder = StringBuilder()
|
||||
|
||||
init {
|
||||
builder.append("javascript:(function(){")
|
||||
}
|
||||
|
||||
private fun getElementById(id: String) = "document.getElementById(\"$id\")"
|
||||
|
||||
private fun hideElementById(id: String) {
|
||||
builder.append(getElementById(id)).append(".style.display=\"none\";")
|
||||
}
|
||||
|
||||
fun hideElementById(vararg ids: String) {
|
||||
ids.forEach { hideElementById(it) }
|
||||
}
|
||||
|
||||
fun build() = builder.toString() + "})()"
|
||||
|
||||
fun inject(webView: WebView) {
|
||||
webView.loadUrl(build())
|
||||
}
|
||||
|
||||
override fun toString() = build()
|
||||
}
|
@ -2,8 +2,8 @@ package com.pitchedapps.frost.utils
|
||||
|
||||
import android.content.Context
|
||||
import com.raizlabs.android.dbflow.config.FlowManager
|
||||
import com.raizlabs.android.dbflow.kotlinextensions.processInTransactionAsync
|
||||
import com.raizlabs.android.dbflow.kotlinextensions.save
|
||||
import com.raizlabs.android.dbflow.kotlinextensions.*
|
||||
import com.raizlabs.android.dbflow.structure.database.transaction.FastStoreModelTransaction
|
||||
import com.raizlabs.android.dbflow.structure.database.transaction.Transaction
|
||||
|
||||
/**
|
||||
@ -18,19 +18,8 @@ object DbUtils {
|
||||
|
||||
}
|
||||
|
||||
inline fun <reified T : Any> List<T>.replace(context: Context, dbName: String,
|
||||
crossinline callback: ((successful: Boolean) -> Unit)) {
|
||||
inline fun <reified T : Any> List<T>.replace(context: Context, dbName: String) {
|
||||
L.d("Replacing $dbName.db")
|
||||
DbUtils.db(dbName).reset(context)
|
||||
this.processInTransactionAsync({
|
||||
t, databaseWrapper ->
|
||||
t.save(databaseWrapper)
|
||||
},
|
||||
Transaction.Success {
|
||||
callback.invoke(true)
|
||||
},
|
||||
Transaction.Error { _, error ->
|
||||
L.e(error.message ?: "DbReplace error")
|
||||
callback.invoke(false)
|
||||
})
|
||||
FastStoreModelTransaction.saveBuilder(FlowManager.getModelAdapter(T::class.java)).addAll(this).build()
|
||||
}
|
@ -25,8 +25,9 @@ object Prefs {
|
||||
get() = sp.getLong(LAST_ACTIVE, -1)
|
||||
set(value) = set(LAST_ACTIVE, System.currentTimeMillis())
|
||||
|
||||
var userId: Int
|
||||
get() = sp.getInt(USER_ID, -1)
|
||||
const val userIdDefault = -1L
|
||||
var userId: Long
|
||||
get() = sp.getLong(USER_ID, userIdDefault)
|
||||
set(value) = set(USER_ID, value)
|
||||
|
||||
private fun set(key: String, value: Boolean) = sp.edit().putBoolean(key, value).apply()
|
||||
|
@ -11,6 +11,7 @@ import android.util.AttributeSet
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.webkit.*
|
||||
import com.pitchedapps.frost.facebook.FbCookie
|
||||
import com.pitchedapps.frost.utils.L
|
||||
import com.pitchedapps.frost.utils.ObservableContainer
|
||||
import io.reactivex.subjects.BehaviorSubject
|
||||
@ -52,22 +53,19 @@ class FrostWebView @JvmOverloads constructor(
|
||||
override fun onReceivedError(view: WebView?, request: WebResourceRequest?, error: WebResourceError?) {
|
||||
super.onReceivedError(view, request, error)
|
||||
observable.onNext(WebStatus.ERROR)
|
||||
L.e("Error ${request}")
|
||||
L.e("FWV Error ${request}")
|
||||
}
|
||||
|
||||
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
|
||||
override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) {
|
||||
super.onPageStarted(view, url, favicon)
|
||||
observable.onNext(WebStatus.LOADING)
|
||||
L.d("Loading $url")
|
||||
L.d("FWV Loading $url")
|
||||
}
|
||||
|
||||
override fun onPageFinished(view: WebView?, url: String?) {
|
||||
override fun onPageFinished(view: WebView, url: String) {
|
||||
super.onPageFinished(view, url)
|
||||
observable.onNext(WebStatus.LOADED)
|
||||
val cookie = CookieManager.getInstance().getCookie(url)
|
||||
L.d("Loaded $url")
|
||||
L.d("Cookie $cookie")
|
||||
CookieManager.getInstance().flush()
|
||||
FbCookie.checkUserId(url, CookieManager.getInstance().getCookie(url))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user