Skip to content

Commit

Permalink
Merge pull request #768 from anthonycr/dev
Browse files Browse the repository at this point in the history
Release 5.1.0
  • Loading branch information
anthonycr committed Oct 1, 2019
2 parents 1433e98 + 079e90b commit aebda85
Show file tree
Hide file tree
Showing 52 changed files with 508 additions and 268 deletions.
3 changes: 0 additions & 3 deletions .gitmodules

This file was deleted.

8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
Change Log
==========

Version 5.1.0 *(2019-10-01)*
----------------------------
- Made copy link action available in incognito mode.
- Fixed bug with bookmark and tab drawer transparency.
- Added feature to freeze old tabs until they are accessed if the app restarts.
- Added button to search suggestions layout that inserts the suggestion rather than searching for it.
- Added support for full sandboxed incognito mode on Android Pie (API 28) and up.

Version 5.0.2 *(2019-09-07)*
----------------------------
- Target Android 10 API 29
Expand Down
13 changes: 5 additions & 8 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ android {
defaultConfig {
minSdkVersion project.minSdkVersion
targetSdkVersion project.targetSdkVersion
versionName "5.0.2"
versionName "5.1.0"
vectorDrawables.useSupportLibrary = true
}

Expand Down Expand Up @@ -60,14 +60,14 @@ android {
dimension "capabilities"
buildConfigField "boolean", "FULL_VERSION", "Boolean.parseBoolean(\"true\")"
applicationId "acr.browser.lightning"
versionCode 100
versionCode 101
}

lightningLite {
dimension "capabilities"
buildConfigField "boolean", "FULL_VERSION", "Boolean.parseBoolean(\"false\")"
applicationId "acr.browser.barebones"
versionCode 101
versionCode 102
}
}

Expand Down Expand Up @@ -144,11 +144,8 @@ dependencies {
implementation 'com.anthonycr.grant:permissions:1.1.2'

// proxy support
// TODO: Replace I2P submodule with version 0.9.41 when it is available on maven
// implementation 'net.i2p.android:client:0.9.40'
// implementation 'net.i2p.android:helper:0.9.5'
implementation project(':client')
implementation project(':helper')
implementation 'net.i2p.android:client:0.9.42'
implementation 'net.i2p.android:helper:0.9.5'

implementation 'com.squareup.okhttp3:okhttp:3.12.3'

Expand Down
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@
android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize|keyboardHidden|keyboard"
android:label="@string/app_name"
android:launchMode="singleInstance"
android:process=":incognito"
android:parentActivityName=".MainActivity"
android:theme="@style/Theme.DarkTheme"
android:windowSoftInputMode="stateHidden|adjustResize">
Expand Down
15 changes: 8 additions & 7 deletions app/src/main/java/acr/browser/lightning/BrowserApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class BrowserApp : Application() {
@Inject internal lateinit var logger: Logger
@Inject internal lateinit var buildInfo: BuildInfo

val applicationComponent: AppComponent by lazy { appComponent }
lateinit var applicationComponent: AppComponent

override fun attachBaseContext(base: Context) {
super.attachBaseContext(base)
Expand All @@ -57,6 +57,12 @@ class BrowserApp : Application() {
.build())
}

if (Build.VERSION.SDK_INT >= 28) {
if (getProcessName() == "$packageName:incognito") {
WebView.setDataDirectorySuffix("incognito")
}
}

val defaultHandler = Thread.getDefaultUncaughtExceptionHandler()

Thread.setDefaultUncaughtExceptionHandler { thread, ex ->
Expand All @@ -78,7 +84,7 @@ class BrowserApp : Application() {
}
}

appComponent = DaggerAppComponent.builder()
applicationComponent = DaggerAppComponent.builder()
.application(this)
.buildInfo(createBuildInfo())
.build()
Expand Down Expand Up @@ -117,16 +123,11 @@ class BrowserApp : Application() {
})

companion object {

private const val TAG = "BrowserApp"

init {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT)
}

@JvmStatic
lateinit var appComponent: AppComponent

}

}
22 changes: 22 additions & 0 deletions app/src/main/java/acr/browser/lightning/Capabilities.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package acr.browser.lightning

import android.os.Build

/**
* Capabilities that are specific to certain API levels.
*/
enum class Capabilities {
FULL_INCOGNITO,
WEB_RTC,
THIRD_PARTY_COOKIE_BLOCKING
}

/**
* Returns true if the capability is supported, false otherwise.
*/
val Capabilities.isSupported: Boolean
get() = when (this) {
Capabilities.FULL_INCOGNITO -> Build.VERSION.SDK_INT >= 28
Capabilities.WEB_RTC -> Build.VERSION.SDK_INT >= 21
Capabilities.THIRD_PARTY_COOKIE_BLOCKING -> Build.VERSION.SDK_INT >= 21
}
8 changes: 6 additions & 2 deletions app/src/main/java/acr/browser/lightning/IncognitoActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ class IncognitoActivity : BrowserActivity() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
CookieSyncManager.createInstance(this@IncognitoActivity)
}
cookieManager.setAcceptCookie(userPreferences.incognitoCookiesEnabled)
if (Capabilities.FULL_INCOGNITO.isSupported) {
cookieManager.setAcceptCookie(userPreferences.cookiesEnabled)
} else {
cookieManager.setAcceptCookie(userPreferences.incognitoCookiesEnabled)
}
}

override fun onCreateOptionsMenu(menu: Menu): Boolean {
Expand All @@ -41,7 +45,7 @@ class IncognitoActivity : BrowserActivity() {

override fun isIncognito() = true

override fun closeActivity() = closeDrawers(this::closeBrowser)
override fun closeActivity() = closeDrawers(::closeBrowser)

companion object {
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,51 +130,34 @@ class BloomFilterAdBlocker @Inject constructor(
}

override fun isAd(url: String): Boolean {
val domain = try {
getDomainName(url)
} catch (exception: URISyntaxException) {
logger.log(TAG, "URL '$url' is invalid", exception)
return false
}
val domain = url.host() ?: return false

val mightBeOnBlockList = bloomFilter.mightContain(domain)

return if (mightBeOnBlockList) {
val isOnBlockList = hostsRepository.containsHost(domain)
if (isOnBlockList) {
logger.log(TAG, "URL '$url' is an ad")
} else {
logger.log(TAG, "False positive for $url")
}
return when {
mightBeOnBlockList -> {
val isOnBlockList = hostsRepository.containsHost(domain)
if (isOnBlockList) {
logger.log(TAG, "URL '$url' is an ad")
} else {
logger.log(TAG, "False positive for $url")
}

isOnBlockList
} else {
false
isOnBlockList
}
domain.name.startsWith("www.") -> isAd(domain.name.substring(4))
else -> false
}
}

/**
* Returns the probable domain name for a given URL
*
* @param url the url to parse
* @return returns the domain
* @throws URISyntaxException throws an exception if the string cannot form a URI
* Extract the [Host] from a [String] representing a URL. Returns null if no host was extracted.
*/
@Throws(URISyntaxException::class)
private fun getDomainName(url: String): Host {
val host = url.indexOf('/', 8)
.takeIf { it != -1 }
?.let(url::take)
?: url

val uri = URI(host)
val domain = uri.host ?: return Host(host)

return Host(if (domain.startsWith("www.")) {
domain.substring(4)
} else {
domain
})
private fun String.host(): Host? = try {
URI(this).host?.let(::Host)
} catch (exception: URISyntaxException) {
logger.log(TAG, "Invalid URL: $this", exception)
null
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,6 @@ class SearchBoxModel @Inject constructor(
}
}

private fun safeDomain(url: String) = Utils.getDomainName(url)
private fun safeDomain(url: String) = Utils.getDisplayDomainName(url)

}
35 changes: 26 additions & 9 deletions app/src/main/java/acr/browser/lightning/browser/TabsManager.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package acr.browser.lightning.browser

import acr.browser.lightning.R
import acr.browser.lightning.di.DatabaseScheduler
import acr.browser.lightning.di.DiskScheduler
import acr.browser.lightning.di.MainScheduler
Expand Down Expand Up @@ -101,7 +102,7 @@ class TabsManager @Inject constructor(
.subscribeOn(mainScheduler)
.observeOn(databaseScheduler)
.flatMapObservable {
return@flatMapObservable if (incognito) {
if (incognito) {
initializeIncognitoMode(it.value())
} else {
initializeRegularMode(it.value(), activity)
Expand All @@ -116,9 +117,7 @@ class TabsManager @Inject constructor(
* Returns an [Observable] that emits the [TabInitializer] for incognito mode.
*/
private fun initializeIncognitoMode(initialUrl: String?): Observable<TabInitializer> =
Observable.fromCallable {
return@fromCallable initialUrl?.let(::UrlInitializer) ?: homePageInitializer
}
Observable.fromCallable { initialUrl?.let(::UrlInitializer) ?: homePageInitializer }

/**
* Returns an [Observable] that emits the [TabInitializer] for normal operation mode.
Expand Down Expand Up @@ -156,7 +155,7 @@ class TabsManager @Inject constructor(
* saved on disk. Can potentially be empty.
*/
private fun restorePreviousTabs(): Observable<TabInitializer> = readSavedStateFromDisk()
.map { bundle ->
.map { (bundle, title) ->
return@map bundle.getString(URL_KEY)?.let { url ->
when {
url.isBookmarkUrl() -> bookmarkPageInitializer
Expand All @@ -165,7 +164,8 @@ class TabsManager @Inject constructor(
url.isHistoryUrl() -> historyPageInitializer
else -> homePageInitializer
}
} ?: BundleInitializer(bundle)
} ?: FreezableBundleInitializer(bundle, title
?: application.getString(R.string.tab_frozen))
}


Expand Down Expand Up @@ -327,11 +327,11 @@ class TabsManager @Inject constructor(
val outState = Bundle(ClassLoader.getSystemClassLoader())
logger.log(TAG, "Saving tab state")
tabList
.filter { it.url.isNotBlank() }
.withIndex()
.forEach { (index, tab) ->
if (!tab.url.isSpecialUrl()) {
outState.putBundle(BUNDLE_KEY + index, tab.saveState())
outState.putString(TAB_TITLE_KEY + index, tab.title)
} else {
outState.putBundle(BUNDLE_KEY + index, Bundle().apply {
putString(URL_KEY, tab.url)
Expand All @@ -354,15 +354,31 @@ class TabsManager @Inject constructor(
* on disk. After the list of bundle [Bundle] is read off disk, the old state will be deleted.
* Can potentially be empty.
*/
private fun readSavedStateFromDisk(): Observable<Bundle> = Maybe
private fun readSavedStateFromDisk(): Observable<Pair<Bundle, String?>> = Maybe
.fromCallable { FileUtils.readBundleFromStorage(application, BUNDLE_STORAGE) }
.flattenAsObservable { bundle ->
bundle.keySet()
.filter { it.startsWith(BUNDLE_KEY) }
.mapNotNull(bundle::getBundle)
.mapNotNull { bundleKey ->
bundle.getBundle(bundleKey)?.let {
Pair(
it,
bundle.getString(TAB_TITLE_KEY + bundleKey.extractNumberFromEnd())
)
}
}
}
.doOnNext { logger.log(TAG, "Restoring previous WebView state now") }

private fun String.extractNumberFromEnd(): String {
val underScore = lastIndexOf('_')
return if (underScore in 0 until length) {
substring(underScore + 1)
} else {
""
}
}

/**
* Returns the index of the current tab.
*
Expand Down Expand Up @@ -409,6 +425,7 @@ class TabsManager @Inject constructor(
private const val TAG = "TabsManager"

private const val BUNDLE_KEY = "WEBVIEW_"
private const val TAB_TITLE_KEY = "TITLE_"
private const val URL_KEY = "URL_KEY"
private const val BUNDLE_STORAGE = "SAVED_TABS.parcel"
}
Expand Down
Loading

0 comments on commit aebda85

Please sign in to comment.