From 725d6a99a07f91f940a07e6b49dd6224a6aa32d1 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Sun, 31 Dec 2017 02:44:46 -0500 Subject: Enhancement/proguard (#589) * Add error log * Rewrite logger --- .../pitchedapps/frost/web/FrostChromeClients.kt | 30 +------ .../kotlin/com/pitchedapps/frost/web/FrostJSI.kt | 4 +- .../frost/web/FrostRequestInterceptor.kt | 2 +- .../frost/web/FrostUrlOverlayValidator.kt | 15 ++-- .../pitchedapps/frost/web/FrostWebViewClients.kt | 49 +++--------- .../pitchedapps/frost/web/HeadlessHtmlExtractor.kt | 91 ---------------------- .../com/pitchedapps/frost/web/LoginWebView.kt | 8 +- 7 files changed, 30 insertions(+), 169 deletions(-) delete mode 100644 app/src/main/kotlin/com/pitchedapps/frost/web/HeadlessHtmlExtractor.kt (limited to 'app/src/main/kotlin/com/pitchedapps/frost/web') diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClients.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClients.kt index 960fe4c2..8c016e5c 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClients.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClients.kt @@ -19,30 +19,6 @@ import io.reactivex.subjects.Subject * Collection of chrome clients */ -/** - * Fully quiet client that disables any prompts relating to the UI - * (as nothing is attached) - */ -class HeadlessChromeClient : WebChromeClient() { - - override fun onConsoleMessage(consoleMessage: ConsoleMessage) = true - - override fun onJsAlert(view: WebView, url: String?, message: String?, result: JsResult): Boolean { - result.cancel() - return true - } - - override fun onJsConfirm(view: WebView, url: String?, message: String?, result: JsResult): Boolean { - result.cancel() - return true - } - - override fun onJsPrompt(view: WebView, url: String?, message: String?, defaultValue: String?, result: JsPromptResult): Boolean { - result.cancel() - return true - } -} - /** * The default chrome client */ @@ -55,7 +31,7 @@ class FrostChromeClient(web: FrostWebView) : WebChromeClient() { override fun onConsoleMessage(consoleMessage: ConsoleMessage): Boolean { if (consoleBlacklist.any { consoleMessage.message().contains(it) }) return true - L.v("Chrome Console ${consoleMessage.lineNumber()}: ${consoleMessage.message()}") + L.v { "Chrome Console ${consoleMessage.lineNumber()}: ${consoleMessage.message()}" } return true } @@ -76,9 +52,9 @@ class FrostChromeClient(web: FrostWebView) : WebChromeClient() { } override fun onGeolocationPermissionsShowPrompt(origin: String, callback: GeolocationPermissions.Callback) { - L.i("Requesting geolocation") + L.i { "Requesting geolocation" } context.kauRequestPermissions(PERMISSION_ACCESS_FINE_LOCATION) { granted, _ -> - L.i("Geolocation response received; ${if (granted) "granted" else "denied"}") + L.i { "Geolocation response received; ${if (granted) "granted" else "denied"}" } callback(origin, granted, true) } } 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 b567801b..9264ea52 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt @@ -33,13 +33,13 @@ class FrostJSI(val web: FrostWebView) { if (url != null) web.post { (context as? VideoViewHolder)?.showVideo(url, isGif) - ?: L.d("Could not load video; contract not implemented") + ?: L.d { "Could not load video; contract not implemented" } } } @JavascriptInterface fun reloadBaseUrl(animate: Boolean) { - L.d("FrostJSI reload") + L.d { "FrostJSI reload" } web.post { web.stopLoading() web.reloadBase(animate) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostRequestInterceptor.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostRequestInterceptor.kt index f7f5666d..454e2a4b 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostRequestInterceptor.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostRequestInterceptor.kt @@ -47,7 +47,7 @@ fun WebView.shouldFrostInterceptRequest(request: WebResourceRequest): WebResourc if (whitelistHost.contains(host)) return null if (!adWhitelistHost.contains(host) && FrostPglAdBlock.isAdHost(host)) return blankResource // if (!shouldLoadImages && !Prefs.loadMediaOnMeteredNetwork && request.isMedia) return blankResource - L.v("Intercept Request", "$host $url") + L.v { "Intercept Request: $host $url" } return null } 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 253d4801..8eec3402 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostUrlOverlayValidator.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostUrlOverlayValidator.kt @@ -29,34 +29,35 @@ import org.jetbrains.anko.runOnUiThread * as we have no need of sending a new intent to the same activity */ fun FrostWebView.requestWebOverlay(url: String): Boolean { + L.v { "Request web overlay: $url" } val context = context // finalize reference if (url.isVideoUrl && context is VideoViewHolder) { - L.i("Found video", url) + L.d { "Found video" } context.runOnUiThread { context.showVideo(url) } return true } if (!url.isIndependent) { - L.i("Forbid overlay switch", url) + L.d { "Forbid overlay switch" } return false } if (!Prefs.overlayEnabled) return false if (context is WebOverlayActivityBase) { - L.v("Check web request from overlay", url) + L.v { "Check web request from overlay" } //already overlay; manage user agent if (userAgentString != USER_AGENT_BASIC && url.formattedFbUrl.shouldUseBasicAgent) { - L.i("Switch to basic agent overlay") + 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") + L.i { "Switch from basic agent" } context.launchWebOverlay(url) return true } - L.i("return false switch") + L.i { "return false switch" } return false } - L.v("Request web overlay passed", url) + L.v { "Request web overlay passed" } context.launchWebOverlay(url) return true } 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 71c71b66..a826066d 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt @@ -44,10 +44,12 @@ open class FrostWebViewClient(val web: FrostWebView) : BaseWebViewClient() { private val refresh: Subject = web.parent.refreshObservable private val isMain = web.parent.baseEnum != null + protected inline fun v(crossinline message: () -> Any?) = L.v { "web client: ${message()}" } + override fun onPageStarted(view: WebView, url: String?, favicon: Bitmap?) { super.onPageStarted(view, url, favicon) if (url == null) return - L.d("FWV Loading", url) + v { "loading $url" } refresh.onNext(true) } @@ -87,7 +89,7 @@ open class FrostWebViewClient(val web: FrostWebView) : BaseWebViewClient() { override fun onPageFinished(view: WebView, url: String?) { url ?: return - L.d("Page finished", url) + v { "finished $url" } if (!url.isFacebookUrl) { refresh.onNext(false) return @@ -102,7 +104,7 @@ open class FrostWebViewClient(val web: FrostWebView) : BaseWebViewClient() { } internal fun injectAndFinish() { - L.d("Page finished reveal") + v { "page finished reveal" } refresh.onNext(false) injectBackgroundColor() web.jsInject( @@ -117,11 +119,11 @@ open class FrostWebViewClient(val web: FrostWebView) : BaseWebViewClient() { } open fun handleHtml(html: String?) { - L.d("Handle Html") + L.d { "Handle Html" } } open fun emit(flag: Int) { - L.d("Emit $flag") + L.d { "Emit $flag" } } /** @@ -130,21 +132,21 @@ open class FrostWebViewClient(val web: FrostWebView) : BaseWebViewClient() { * returns false if we are already in an overlaying activity */ private fun launchRequest(request: WebResourceRequest): Boolean { - L.d("Launching Url", request.url?.toString() ?: "null") + v { "Launching url: ${request.url}" } return web.requestWebOverlay(request.url.toString()) } private fun launchImage(url: String, text: String? = null): Boolean { - L.d("Launching Image", url) + v { "Launching image: $url" } web.context.launchImageActivity(url, text) if (web.canGoBack()) web.goBack() return true } override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean { - L.i("Url Loading", request.url?.toString()) + v { "Url loading: ${request.url}" } val path = request.url?.path ?: return super.shouldOverrideUrlLoading(view, request) - L.v("Url Loading Path", path) + v { "Url path $path" } val url = request.url.toString() if (url.isExplicitIntent) { view.context.resolveActivityForUri(request.url) @@ -184,34 +186,7 @@ class FrostWebViewClientMenu(web: FrostWebView) : FrostWebViewClient(web) { } override fun onPageFinishedActions(url: String) { - L.d("Should inject ${url.shouldInjectMenu}") + v { "Should inject ${url.shouldInjectMenu}" } if (!url.shouldInjectMenu) injectAndFinish() } -} - -/** - * Headless client that injects content after a page load - * The JSI is meant to handle everything else - */ -class HeadlessWebViewClient(val tag: String, val postInjection: InjectorContract) : BaseWebViewClient() { - - override fun onPageStarted(view: WebView, url: String?, favicon: Bitmap?) { - super.onPageStarted(view, url, favicon) - if (url == null) return - L.d("Headless Page $tag Started", url) - } - - override fun onPageFinished(view: WebView, url: String?) { - super.onPageFinished(view, url) - if (url == null) return - L.d("Headless Page $tag Finished", url) - postInjection.inject(view) - } - - /** - * In addition to general filtration, we will also strip away css and images - */ - override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? - = super.shouldInterceptRequest(view, request).filterCss(request).filterImage(request) - } \ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/HeadlessHtmlExtractor.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/HeadlessHtmlExtractor.kt deleted file mode 100644 index 2c7735a4..00000000 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/HeadlessHtmlExtractor.kt +++ /dev/null @@ -1,91 +0,0 @@ -package com.pitchedapps.frost.web - -import android.annotation.SuppressLint -import android.content.Context -import android.webkit.JavascriptInterface -import android.webkit.WebView -import ca.allanwang.kau.utils.gone -import com.pitchedapps.frost.R -import com.pitchedapps.frost.facebook.USER_AGENT_BASIC -import com.pitchedapps.frost.injectors.InjectorContract -import com.pitchedapps.frost.utils.L -import io.reactivex.Single -import io.reactivex.SingleEmitter -import io.reactivex.android.schedulers.AndroidSchedulers -import io.reactivex.schedulers.Schedulers -import org.jetbrains.anko.runOnUiThread -import java.util.concurrent.TimeUnit - -/** - * Created by Allan Wang on 2017-08-12. - * - * Launches a headless html request and returns a result pair - * When successful, the pair will contain the html content and -1 - * When unsuccessful, the pair will contain an empty string and a StringRes for the given error - * - * All errors are rerouted to success calls, so no exceptions should occur. - * The headless extractor will also destroy itself on cancellation or when the request is finished - */ -fun Context.launchHeadlessHtmlExtractor(url: String, injector: InjectorContract, action: (Single>) -> Unit) { - val single = Single.create> { e: SingleEmitter> -> - val extractor = HeadlessHtmlExtractor(this, url, injector, e) - extractor.resumeTimers() - e.setCancellable { - runOnUiThread { - extractor.pauseTimers() - extractor.destroy() - } - e.onSuccess("" to R.string.html_extraction_cancelled) - } - }.subscribeOn(AndroidSchedulers.mainThread()) - .timeout(20, TimeUnit.SECONDS, Schedulers.io(), { it.onSuccess("" to R.string.html_extraction_timeout) }) - .onErrorReturn { "" to R.string.html_extraction_error } - action(single) -} - -/** - * Given a link and some javascript, will load the link and load the JS on completion - * The JS is expected to call [HeadlessHtmlExtractor.HtmlJSI.handleHtml], which will be sent - * to the [emitter] - */ -@SuppressLint("ViewConstructor") -private class HeadlessHtmlExtractor( - context: Context, url: String, val injector: InjectorContract, val emitter: SingleEmitter> -) : WebView(context) { - - val startTime = System.currentTimeMillis() - - init { - L.v("Created HeadlessHtmlExtractor for $url") - gone() - setupWebview(url) - } - - @SuppressLint("SetJavaScriptEnabled") - private fun setupWebview(url: String) { - settings.javaScriptEnabled = true - settings.userAgentString = USER_AGENT_BASIC - webViewClient = HeadlessWebViewClient(url, injector) // basic client that loads our JS once the page has loaded - webChromeClient = HeadlessChromeClient() - addJavascriptInterface(HtmlJSI(), "Frost") - loadUrl(url) - } - - inner class HtmlJSI { - @JavascriptInterface - fun handleHtml(html: String?) { - val time = System.currentTimeMillis() - startTime - emitter.onSuccess((html ?: "") to -1) - post { - L.d("HeadlessHtmlExtractor fetched $url in $time ms") - destroy() - } - } - } - - override fun destroy() { - pauseTimers() - super.destroy() - L.d("HeadlessHtmlExtractor destroyed") - } -} \ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt index 9855040d..a2f341ef 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt @@ -46,7 +46,7 @@ class LoginWebView @JvmOverloads constructor( fun loadLogin(progressCallback: (Int) -> Unit, loginCallback: (CookieModel) -> Unit) { this.progressCallback = progressCallback this.loginCallback = loginCallback - L.d("Begin loading login") + L.d { "Begin loading login" } loadUrl(FB_LOGIN_URL) } @@ -62,7 +62,7 @@ class LoginWebView @JvmOverloads constructor( doAsync { if (!url.isFacebookUrl) return@doAsync val cookie = CookieManager.getInstance().getCookie(url) ?: return@doAsync - L.d("Checking cookie for login", cookie) + L.d { "Checking cookie for login" } val id = FB_USER_MATCHER.find(cookie)[1]?.toLong() ?: return@doAsync uiThread { onFound(id, cookie) } } @@ -70,7 +70,7 @@ class LoginWebView @JvmOverloads constructor( override fun onPageCommitVisible(view: WebView, url: String?) { super.onPageCommitVisible(view, url) - L.d("Login page commit visible") + L.d { "Login page commit visible" } view.setBackgroundColor(Color.TRANSPARENT) if (url.isFacebookUrl) view.jsInject(CssHider.HEADER, @@ -88,7 +88,7 @@ class LoginWebView @JvmOverloads constructor( inner class LoginChromeClient : WebChromeClient() { override fun onConsoleMessage(consoleMessage: ConsoleMessage): Boolean { - L.d("Login Console ${consoleMessage.lineNumber()}: ${consoleMessage.message()}") + L.v { "Login Console ${consoleMessage.lineNumber()}: ${consoleMessage.message()}" } return true } -- cgit v1.2.3