From 5e9ed54c90f994f99deb105d57f4d5b3ca1db8cd Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Sat, 16 Sep 2017 18:18:28 -0400 Subject: Fix/messaging overlay (#291) * Create base switcher * Add intent blacklist * Revert extra overlay * Add user agent enum * Test per link user agents * Test extra overlays once again * Fix up messaging overlays --- .../frost/activities/FrostWebActivity.kt | 20 ------------ .../frost/activities/WebOverlayActivity.kt | 29 ++++++++++++++++- .../kotlin/com/pitchedapps/frost/utils/Utils.kt | 4 +-- .../kotlin/com/pitchedapps/frost/web/FrostJSI.kt | 2 +- .../frost/web/FrostUrlOverlayValidator.kt | 37 +++++++++++++++++++--- .../com/pitchedapps/frost/web/FrostWebView.kt | 2 +- .../pitchedapps/frost/web/FrostWebViewClients.kt | 12 ++++--- .../com/pitchedapps/frost/web/FrostWebViewCore.kt | 16 ++++++++++ 8 files changed, 88 insertions(+), 34 deletions(-) delete mode 100644 app/src/main/kotlin/com/pitchedapps/frost/activities/FrostWebActivity.kt (limited to 'app/src/main/kotlin/com/pitchedapps') diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/FrostWebActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/FrostWebActivity.kt deleted file mode 100644 index 1773471f..00000000 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/FrostWebActivity.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.pitchedapps.frost.activities - -import android.os.Bundle -import com.pitchedapps.frost.utils.Prefs - - -/** - * Created by Allan Wang on 2017-06-19. - * - * Replica of [WebOverlayActivity] with a different base url - * Didn't use activity-alias because it causes issues when only one activity has the singleInstance mode - */ -class FrostWebActivity : WebOverlayActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - Prefs.prevId = Prefs.userId - super.onCreate(savedInstanceState) - } - -} \ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt index 756d5d35..e5452655 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt @@ -21,6 +21,7 @@ import com.pitchedapps.frost.contracts.ActivityWebContract import com.pitchedapps.frost.contracts.FileChooserContract import com.pitchedapps.frost.contracts.FileChooserDelegate import com.pitchedapps.frost.facebook.FbCookie +import com.pitchedapps.frost.facebook.USER_AGENT_BASIC import com.pitchedapps.frost.facebook.formattedFbUrl import com.pitchedapps.frost.utils.* import com.pitchedapps.frost.web.FrostWebView @@ -28,8 +29,31 @@ import com.pitchedapps.frost.web.FrostWebView /** * Created by Allan Wang on 2017-06-01. + * + * Collection of overlay activities for Frost + * + * Each one is largely the same layout, but is separated so they may run is separate single tasks + * All overlays support user switches */ -open class WebOverlayActivity : KauBaseActivity(), + +/** + * Used by notifications. Unlike the other overlays, this runs as a singleInstance + * Going back will bring you back to the previous app + */ +class FrostWebActivity : WebOverlayActivityBase(false) + +/** + * Variant that forces a basic user agent. This is largely internal, + * and is only necessary when we are launching from an existing [WebOverlayActivityBase] + */ +class WebOverlayBasicActivity : WebOverlayActivityBase(true) + +/** + * Internal overlay for the app; this is tied with the main task and is singleTop as opposed to singleInstance + */ +class WebOverlayActivity : WebOverlayActivityBase(false) + +open class WebOverlayActivityBase(val forceBasicAgent: Boolean) : KauBaseActivity(), ActivityWebContract, FileChooserContract by FileChooserDelegate() { val toolbar: Toolbar by bindView(R.id.overlay_toolbar) @@ -64,7 +88,10 @@ open class WebOverlayActivity : KauBaseActivity(), coordinator.setBackgroundColor(Prefs.bgColor.withAlpha(255)) frostWeb.setupWebview(url) + if (forceBasicAgent) + frostWeb.web.userAgentString = USER_AGENT_BASIC frostWeb.web.addTitleListener({ toolbar.title = it }) + Prefs.prevId = Prefs.userId if (userId != Prefs.userId) FbCookie.switchUser(userId) { frostWeb.web.loadBaseUrl() } else frostWeb.web.loadBaseUrl() if (Showcase.firstWebOverlay) { 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 e342394f..bcda6a43 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt @@ -62,14 +62,14 @@ fun Activity.cookies(): ArrayList { * Note that most requests may need to first check if the url can be launched as an overlay * See [requestWebOverlay] to verify the launch */ -fun Context.launchWebOverlay(url: String) { +fun Context.launchWebOverlay(url: String, clazz: Class = WebOverlayActivity::class.java) { val argUrl = url.formattedFbUrl L.v("Launch received", url) L.i("Launch web overlay", argUrl) if (argUrl.isFacebookUrl && argUrl.contains("/logout.php")) FbCookie.logout(this) else if (!(Prefs.linksInDefaultApp && resolveActivityForUri(Uri.parse(argUrl)))) - startActivity(WebOverlayActivity::class.java, false, intentBuilder = { + startActivity(clazz, false, intentBuilder = { putExtra(ARG_URL, argUrl) }) } 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 c7232fe3..93d5c773 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt @@ -33,7 +33,7 @@ class FrostJSI(val webView: FrostWebViewCore) { */ @JavascriptInterface fun loadUrl(url: String?): Boolean - = if (url == null) false else context.requestWebOverlay(url) + = if (url == null) false else webView.requestWebOverlay(url) @JavascriptInterface fun reloadBaseUrl(animate: Boolean) { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostUrlOverlayValidator.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostUrlOverlayValidator.kt index 29d2e991..2d9915be 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostUrlOverlayValidator.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostUrlOverlayValidator.kt @@ -1,7 +1,10 @@ package com.pitchedapps.frost.web -import android.content.Context +import com.pitchedapps.frost.activities.WebOverlayBasicActivity +import com.pitchedapps.frost.activities.WebOverlayActivity +import com.pitchedapps.frost.activities.WebOverlayActivityBase import com.pitchedapps.frost.facebook.FbItem +import com.pitchedapps.frost.facebook.USER_AGENT_BASIC import com.pitchedapps.frost.facebook.formattedFbUrl import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.isFacebookUrl @@ -14,15 +17,36 @@ import com.pitchedapps.frost.utils.launchWebOverlay * cannot be resolved on a new window and must instead * by loaded in the current page * This helper method will collect all known cases and launch the overlay accordingly - * Returns {@code true} (default) if overlay is launcher, {@code false} otherwise + * Returns {@code true} (default) if overlay is launched, {@code false} otherwise + * + * If the request already comes from an instance of [WebOverlayActivity], we will then judge + * whether the user agent string should be changed. All propagated results will return false, + * as we have no need of sending a new intent to the same activity */ -fun Context.requestWebOverlay(url: String): Boolean { +fun FrostWebViewCore.requestWebOverlay(url: String): Boolean { if (url == "#") return false + + if (context is WebOverlayActivityBase) { + L.v("Check web request from overlay", url) + //already overlay; manage user agent + if (userAgentString != USER_AGENT_BASIC && url.formattedFbUrl.shouldUseBasicAgent) { + L.i("Switch to basic agent overlay") + context.launchWebOverlay(url, WebOverlayBasicActivity::class.java) + return true + } + if (context is WebOverlayBasicActivity && !url.formattedFbUrl.shouldUseBasicAgent) { + L.i("Switch from basic agent") + context.launchWebOverlay(url) + return true + } + L.i("return false switch") + return false + } /* * Non facebook urls can be loaded */ if (!url.formattedFbUrl.isFacebookUrl) { - launchWebOverlay(url) + context.launchWebOverlay(url) L.d("Request web overlay is not a facebook url", url) return true } @@ -39,7 +63,7 @@ fun Context.requestWebOverlay(url: String): Boolean { if (!url.contains("?tid=id") && !url.contains("?tid=mid")) return false } L.v("Request web overlay passed", url) - launchWebOverlay(url) + context.launchWebOverlay(url) return true } @@ -48,6 +72,9 @@ fun Context.requestWebOverlay(url: String): Boolean { */ val messageWhitelist = setOf(FbItem.MESSAGES.url, FbItem.CHAT.url) +val String.shouldUseBasicAgent + get() = (messageWhitelist.any { contains(it) }) + /** * The following components should never be launched in a new overlay */ diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebView.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebView.kt index 2cd31a57..7fb7324e 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebView.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebView.kt @@ -59,7 +59,7 @@ class FrostWebView @JvmOverloads constructor( baseEnum = enum with(settings) { javaScriptEnabled = true - if (messageWhitelist.any { url.contains(it) }) + if (url.shouldUseBasicAgent) userAgentString = USER_AGENT_BASIC allowFileAccess = true textZoom = Prefs.webTextScaling 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 253b4a9b..c398469c 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt @@ -10,8 +10,6 @@ import android.webkit.WebViewClient import com.pitchedapps.frost.activities.LoginActivity import com.pitchedapps.frost.activities.MainActivity import com.pitchedapps.frost.activities.SelectorActivity -import com.pitchedapps.frost.activities.WebOverlayActivity -import com.pitchedapps.frost.enums.FeedSort import com.pitchedapps.frost.facebook.FB_URL_BASE import com.pitchedapps.frost.facebook.FbItem import com.pitchedapps.frost.injectors.* @@ -100,7 +98,7 @@ open class FrostWebViewClient(val webCore: FrostWebViewCore) : BaseWebViewClient injectBackgroundColor() webCore.jsInject( JsActions.LOGIN_CHECK, - JsAssets.CLICK_A.maybe(webCore.baseEnum != null && Prefs.overlayEnabled), + JsAssets.CLICK_A.maybe(Prefs.overlayEnabled), JsAssets.TEXTAREA_LISTENER, CssHider.ADS.maybe(!Prefs.showFacebookAds && IS_FROST_PRO), JsAssets.CONTEXT_A, @@ -123,7 +121,7 @@ open class FrostWebViewClient(val webCore: FrostWebViewCore) : BaseWebViewClient */ private fun launchRequest(request: WebResourceRequest): Boolean { L.d("Launching Url", request.url?.toString() ?: "null") - return webCore.context !is WebOverlayActivity && webCore.context.requestWebOverlay(request.url.toString()) + return webCore.requestWebOverlay(request.url.toString()) } private fun launchImage(url: String, text: String? = null): Boolean { @@ -137,6 +135,12 @@ open class FrostWebViewClient(val webCore: FrostWebViewCore) : BaseWebViewClient L.i("Url Loading", request.url?.toString()) val path = request.url?.path ?: return super.shouldOverrideUrlLoading(view, request) L.v("Url Loading Path", path) + request.url?.toString()?.apply { + if (contains("intent") && contains("com.facebook")) { + L.i("Skip facebook intent request") + return true + } + } if (path.startsWith("/composer/")) return launchRequest(request) if (request.url.toString().contains("scontent-sea1-1.xx.fbcdn.net") && (path.endsWith(".jpg") || path.endsWith(".png"))) return launchImage(request.url.toString()) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewCore.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewCore.kt index 6dbc7c8d..15383a50 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewCore.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewCore.kt @@ -44,6 +44,22 @@ class FrostWebViewCore @JvmOverloads constructor( var baseEnum: FbItem? = null //only viewpager items should pass the base enum internal lateinit var frostWebClient: FrostWebViewClient + /** + * Wrapper to the main userAgentString to cache it. + * This decouples it from the UiThread + * + * Note that this defaults to null, but the main purpose is to + * check if we've set our own agent. + * + * A null value may be interpreted as the default value + */ + var userAgentString: String? = null + get() = field + set(value) { + field = value + settings.userAgentString = value + } + init { isNestedScrollingEnabled = true progressObservable = PublishSubject.create() -- cgit v1.2.3