/* Ċ Ġ* ĠCopyright Ġ( c ) Ġ 2 0 2 0 ĠD uck Duck Go Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠĠ Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ Ċ package Ġcom . duck duck go . app . browser . login detection Ċ Ċ import Ġandroid . content . Context Ċ import Ġandroid . webkit . Web Resource Request Ċ import Ġandroid . webkit . WebView Ċ import Ġandroidx . annotation . Ui Thread Ċ import Ġcom . duck duck go . app . browser . R Ċ import Ġcom . duck duck go . app . browser . login detection . Login Detection Javascript Interface . Companion . J AV AS CRIPT _ INTERFACE _ NAME Ċ import Ġcom . duck duck go . app . global . get Valid Url Ċ import Ġcom . duck duck go . app . settings . db . Settings DataStore Ċ import Ġtim ber . log . Tim ber Ċ import Ġjavax . inject . Inject Ċ Ċ interface ĠDOM Login Detector Ġ{ ĊĠĠĠ Ġfun Ġadd Login Detection ( ĊĠĠĠĠĠĠĠ ĠwebView : ĠWebView , ĊĠĠĠĠĠĠĠ Ġon Login Detected : Ġ() Ġ-> ĠUnit ĊĠĠĠ Ġ) ĊĊĠĠĠ Ġfun Ġon Event ( event : ĠWeb Navigation Event ) Ċ } Ċ Ċ sealed Ġclass ĠWeb Navigation Event Ġ{ ĊĠĠĠ Ġdata Ġclass ĠOn Page Started ( val ĠwebView : ĠWebView ) Ġ: ĠWeb Navigation Event () ĊĠĠĠ Ġdata Ġclass ĠShould Intercept Request ( ĊĠĠĠĠĠĠĠ Ġval ĠwebView : ĠWebView , ĊĠĠĠĠĠĠĠ Ġval Ġrequest : ĠWeb Resource Request ĊĠĠĠ Ġ) Ġ: ĠWeb Navigation Event () Ċ } Ċ Ċ class ĠJs Login Detector Ġ@ Inject Ġconstructor ( private Ġval Ġsettings DataStore : ĠSettings DataStore ) Ġ: ĊĠĠĠ ĠDOM Login Detector Ġ{ ĊĠĠĠ Ġprivate Ġval Ġjava Script Detector Ġ= ĠJavaScript Detector () ĊĠĠĠ Ġprivate Ġval Ġlogin Path Regex Ġ= ĠRegex (" login | sign - in | signin | session ") ĊĊĠĠĠ Ġoverride Ġfun Ġadd Login Detection ( ĊĠĠĠĠĠĠĠ ĠwebView : ĠWebView , ĊĠĠĠĠĠĠĠ Ġon Login Detected : Ġ() Ġ-> ĠUnit ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ ĠwebView . add Javascript Interface ( Login Detection Javascript Interface Ġ{ Ġon Login Detected () Ġ}, ĠJ AV AS CRIPT _ INTERFACE _ NAME ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Ui Thread ĊĠĠĠ Ġoverride Ġfun Ġon Event ( event : ĠWeb Navigation Event ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( settings DataStore . app Login Detection ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( event ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠWeb Navigation Event . On Page Started Ġ-> Ġinject Login Form Detection JS ( event . web View ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠWeb Navigation Event . Should Intercept Request Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( evaluate If Login Post Request ( event . request )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġscan For Password Fields ( event . web View ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġevaluate If Login Post Request ( request : ĠWeb Resource Request ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( request . method Ġ== ĠHTTP _ POST ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . i (" Login Detector : Ġevaluate Ġ${ request . url }") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġvalid Url Ġ= Ġrequest . url . get Valid Url () Ġ?: Ġreturn Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( valid Url . path ?. contains ( login Path Regex ) Ġ== Ġtrue Ġ|| Ġvalid Url . is OAuth Url ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . v (" Login Detector : Ġpost Ġlogin ĠDET ECT ED ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Ui Thread ĊĠĠĠ Ġprivate Ġfun Ġscan For Password Fields ( web View : ĠWebView ) Ġ{ ĊĠĠĠĠĠĠĠ ĠwebView . evaluate Javascript (" javascript :${ java Script Detector . login Form Detector ( web View . context )} ", Ġnull ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Ui Thread ĊĠĠĠ Ġprivate Ġfun Ġinject Login Form Detection JS ( web View : ĠWebView ) Ġ{ ĊĠĠĠĠĠĠĠ ĠwebView . evaluate Javascript (" javascript :${ java Script Detector . login Form Events Detector ( web View . context )} ", Ġnull ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġclass ĠJavaScript Detector Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġlateinit Ġvar Ġfunctions : ĠString ĊĠĠĠĠĠĠĠ Ġprivate Ġlateinit Ġvar Ġhandlers : ĠString ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġget Functions JS ( context : ĠContext ): ĠString Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! this :: functions . isInitialized ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfunctions Ġ= Ġcontext . resources . open Raw Resource ( R . raw . login _ form _ detection _ functions ). buffered Reader (). use Ġ{ Ġit . read Text () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfunctions ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġget Handlers JS ( context : ĠContext ): ĠString Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! this :: handlers . isInitialized ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhandlers Ġ= Ġcontext . resources . open Raw Resource ( R . raw . login _ form _ detection _ handlers ). buffered Reader (). use Ġ{ Ġit . read Text () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġhandlers ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġlogin Form Events Detector ( context : ĠContext ): ĠString Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġwrap Into Anonymous Function ( get Functions JS ( context ) Ġ+ Ġget Handlers JS ( context )) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġlogin Form Detector ( context : ĠContext ): ĠString Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġwrap Into Anonymous Function ( get Functions JS ( context ) Ġ+ Ġ" scan For Password Field (); ") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġwrap Into Anonymous Function ( raw JavaScript : ĠString ): ĠString Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġ"( function () Ġ{ Ġ$ raw JavaScript Ġ})(); " ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠHTTP _ POST Ġ= Ġ" POST " ĊĠĠĠ Ġ} Ċ } Ċ