Skip to content

Commit

Permalink
bug(SharedPreference): prevent SharedPreference causing potential app…
Browse files Browse the repository at this point in the history
… crash (#1860)
  • Loading branch information
SmartbearYing committed Jul 4, 2023
1 parent 2888547 commit e673f4a
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 9 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## TBD

### Bug fixes

* Prevent rare app crash while migrating old `SharedPreferences` data from older versions of `bugsnag-android`
[#1860](https://github.com/bugsnag/bugsnag-android/pull/1860)

## 5.30.0 (2023-05-11)

### Enhancements
Expand Down
1 change: 1 addition & 0 deletions bugsnag-android-core/detekt-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
<ID>SwallowedException:DeviceIdFilePersistence.kt$DeviceIdFilePersistence$catch (exc: OverlappingFileLockException) { Thread.sleep(FILE_LOCK_WAIT_MS) }</ID>
<ID>SwallowedException:JsonHelperTest.kt$JsonHelperTest$catch (e: IllegalArgumentException) { didThrow = true }</ID>
<ID>SwallowedException:PluginClient.kt$PluginClient$catch (exc: ClassNotFoundException) { if (isWarningEnabled) { logger.d("Plugin '$clz' is not on the classpath - functionality will not be enabled.") } null }</ID>
<ID>SwallowedException:SharedPrefMigrator.kt$SharedPrefMigrator$catch (e: RuntimeException) { null }</ID>
<ID>ThrowsCount:JsonHelper.kt$JsonHelper$ fun jsonToLong(value: Any?): Long?</ID>
<ID>TooManyFunctions:ConfigInternal.kt$ConfigInternal : CallbackAwareMetadataAwareUserAwareFeatureFlagAware</ID>
<ID>TooManyFunctions:DeviceDataCollector.kt$DeviceDataCollector</ID>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,38 @@ package com.bugsnag.android

import android.annotation.SuppressLint
import android.content.Context
import android.content.SharedPreferences

/**
* Reads legacy information left in SharedPreferences and migrates it to the new location.
*/
internal class SharedPrefMigrator(context: Context) : DeviceIdPersistence {

private val prefs = context
.getSharedPreferences("com.bugsnag.android", Context.MODE_PRIVATE)
private val prefs: SharedPreferences? =
try {
context.getSharedPreferences("com.bugsnag.android", Context.MODE_PRIVATE)
} catch (e: RuntimeException) {
null
}

/**
* This implementation will never create an ID; it will only fetch one if present.
*/
override fun loadDeviceId(requestCreateIfDoesNotExist: Boolean) = prefs.getString(INSTALL_ID_KEY, null)
override fun loadDeviceId(requestCreateIfDoesNotExist: Boolean) =
prefs?.getString(INSTALL_ID_KEY, null)

fun loadUser(deviceId: String?) = User(
prefs.getString(USER_ID_KEY, deviceId),
prefs.getString(USER_EMAIL_KEY, null),
prefs.getString(USER_NAME_KEY, null)
prefs?.getString(USER_ID_KEY, deviceId),
prefs?.getString(USER_EMAIL_KEY, null),
prefs?.getString(USER_NAME_KEY, null)
)

fun hasPrefs() = prefs.contains(INSTALL_ID_KEY)
fun hasPrefs() = prefs?.contains(INSTALL_ID_KEY) == true

@SuppressLint("ApplySharedPref")
fun deleteLegacyPrefs() {
if (hasPrefs()) {
prefs.edit().clear().commit()
prefs?.edit()?.clear()?.commit()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
import org.mockito.Mockito.times
Expand All @@ -32,10 +33,24 @@ internal class SharedPrefMigratorTest {

@Before
fun setUp() {
`when`(context.getSharedPreferences(eq("com.bugsnag.android"), eq(0))).thenReturn(prefs)
`when`(context.getSharedPreferences(eq("com.bugsnag.android"), anyInt())).thenReturn(prefs)
prefMigrator = SharedPrefMigrator(context)
}

@Test
fun nullSharedPreferences() {
`when`(context.getSharedPreferences(eq("com.bugsnag.android"), anyInt())).thenReturn(null)
prefMigrator = SharedPrefMigrator(context)
assertFalse(prefMigrator.hasPrefs())
}

@Test
fun gettingSharedPreferencesWithException() {
`when`(context.getSharedPreferences(eq("com.bugsnag.android"), anyInt())).thenThrow(RuntimeException())
prefMigrator = SharedPrefMigrator(context)
assertFalse(prefMigrator.hasPrefs())
}

@Test
fun nullDeviceId() {
`when`(prefs.getString("install.iud", null)).thenReturn(null)
Expand Down

0 comments on commit e673f4a

Please sign in to comment.