From 5d9a3fd7fb8f2f9d0f592c89446824980c9841c6 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Mon, 14 Aug 2017 20:48:39 -0700 Subject: v1.4.5 (#174) * Update/kau (#125) * Update logger * Clean imports and bring back reactive libs * Update dependencies and make billing async * Misc (#128) * Update null * Attempt to improve transparent theme backgrounds * Update menu * Move injections to visible method and reduce offset * Update searchview and logging * Clean temp strings and add network states * Move console blacklist to web state * Change some logs to info * Move glide loader to onCreate (#135) * Remove commit number increments (#139) * Fix/misc (#140) * Add canadian locale to toLowerCase * Add try catch to JsAssets * Disable error throwing for bad search subject * Log more throwables quietly * Check internet connection before fetching username * Remove name check in frost notifications * Add activity lifecycle logger * Add rxjava to lib showcase * Move network checker to io thread (#150) * Update dependency * Blank * Feature/jsoup debugger (#152) * Create debugger * Update debugger content * Create debugging logic * Finalize and test debugger * Add reload listener * Fix/pro crash without play store (#155) * Update changelog * Check if iab service exists * Add checker before launching play store request * Separate strings * Enhancement/message notifications (#157) * Map message notifs to the headless html extractor * Update strings * Bring im notifs out of alpha * Update changelog * Remove confirmation dialog (#159) * Separate message notifications and add click intents (#171) * Separate message notifications and add click intent for group notifications * Add comments and finalize * Feature/scroll down on message thread (#172) * Add hook for scroll * Update changelog * Add custom navdrawer layout (#173) * Add faq for auto play * Update changelog * Fix page banner bg (#163) --- .../pitchedapps/frost/web/HeadlessHtmlExtractor.kt | 88 ++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 app/src/main/kotlin/com/pitchedapps/frost/web/HeadlessHtmlExtractor.kt (limited to 'app/src/main/kotlin/com/pitchedapps/frost/web/HeadlessHtmlExtractor.kt') diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/HeadlessHtmlExtractor.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/HeadlessHtmlExtractor.kt new file mode 100644 index 00000000..50f2f6bc --- /dev/null +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/HeadlessHtmlExtractor.kt @@ -0,0 +1,88 @@ +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) + e.setCancellable { + runOnUiThread { 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 = QuietChromeClient() // basic client that disables logging + 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") + settings.javaScriptEnabled = false + settings.blockNetworkLoads = true + destroy() + } + } + } + + override fun destroy() { + super.destroy() + L.d("HeadlessHtmlExtractor destroyed") + } +} \ No newline at end of file -- cgit v1.2.3