Skip to content

Commit

Permalink
sensitive logging flag
Browse files Browse the repository at this point in the history
  • Loading branch information
crc-32 committed Jul 4, 2024
1 parent 87033db commit 1df8984
Show file tree
Hide file tree
Showing 10 changed files with 216 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,42 @@ package io.rebble.cobble.bridges.ui

import android.content.Context
import io.rebble.cobble.bridges.FlutterBridge
import io.rebble.cobble.errors.GlobalExceptionHandler
import io.rebble.cobble.log.collectAndShareLogs
import io.rebble.cobble.pigeons.Pigeons
import io.rebble.cobble.shared.datastore.KMPPrefs
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import javax.inject.Inject

class DebugFlutterBridge @Inject constructor(
private val context: Context,
private val prefs: KMPPrefs,
private val globalExceptionHandler: GlobalExceptionHandler,
bridgeLifecycleController: BridgeLifecycleController
) : FlutterBridge, Pigeons.DebugControl {
private val scope = CoroutineScope(Dispatchers.Main + globalExceptionHandler)
init {
bridgeLifecycleController.setupControl(Pigeons.DebugControl::setup, this)
}

override fun collectLogs(rwsId: String) {
collectAndShareLogs(context, rwsId)
}

override fun getSensitiveLoggingEnabled(result: Pigeons.Result<Boolean>) {
scope.launch {
result.success(prefs.sensitiveDataLoggingEnabled.first())
}
}

override fun setSensitiveLoggingEnabled(enabled: Boolean, result: Pigeons.Result<Void>) {
scope.launch {
prefs.setSensitiveDataLoggingEnabled(enabled)
result.success(null)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import io.rebble.cobble.datasources.PairedStorage
import io.rebble.cobble.datasources.WatchMetadataStore
import io.rebble.cobble.errors.GlobalExceptionHandler
import io.rebble.cobble.service.ServiceLifecycleControl
import io.rebble.cobble.shared.datastore.KMPPrefs
import io.rebble.cobble.shared.domain.calendar.CalendarSync
import io.rebble.libpebblecommon.ProtocolHandler
import io.rebble.libpebblecommon.services.PhoneControlService
Expand Down Expand Up @@ -51,6 +52,7 @@ interface AppComponent {

//TODO: Unify DI under Koin
fun createKMPCalendarSync(): CalendarSync
fun createKMPPrefs(): KMPPrefs

@Component.Factory
interface Factory {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,13 @@ import io.rebble.cobble.bridges.background.NotificationsFlutterBridge
import io.rebble.cobble.data.NotificationAction
import io.rebble.cobble.data.NotificationMessage
import io.rebble.cobble.datasources.FlutterPreferences
import io.rebble.cobble.shared.datastore.KMPPrefs
import io.rebble.cobble.shared.domain.state.ConnectionState
import io.rebble.libpebblecommon.packets.blobdb.BlobResponse
import io.rebble.libpebblecommon.packets.blobdb.TimelineItem
import io.rebble.libpebblecommon.services.notification.NotificationService
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.*
import timber.log.Timber

class NotificationListener : NotificationListenerService() {
Expand All @@ -37,6 +35,7 @@ class NotificationListener : NotificationListenerService() {

private lateinit var notificationService: NotificationService
private lateinit var notificationBridge: NotificationsFlutterBridge
private lateinit var prefs: KMPPrefs

override fun onCreate() {
val injectionComponent = (applicationContext as CobbleApplication).component
Expand All @@ -49,6 +48,7 @@ class NotificationListener : NotificationListenerService() {
notificationService = injectionComponent.createNotificationService()
notificationBridge = injectionComponent.createNotificationsFlutterBridge()
flutterPreferences = injectionComponent.createFlutterPreferences()
prefs = injectionComponent.createKMPPrefs()

super.onCreate()
_isActive.value = true
Expand Down Expand Up @@ -101,6 +101,14 @@ class NotificationListener : NotificationListenerService() {
//if (sbn.notification.group != null && !NotificationCompat.isGroupSummary(sbn.notification)) return
if (mutedPackages.contains(sbn.packageName)) return // ignore muted packages


coroutineScope.launch {
if (prefs.sensitiveDataLoggingEnabled.firstOrNull() == true) {
Timber.d("Notification posted: ${sbn.packageName}")
Timber.d("Notification: ${sbn.notification}\n${sbn.notification.extras}")
}
}

var tagId: String? = null
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
tagId = sbn.notification.channelId
Expand Down
60 changes: 60 additions & 0 deletions android/app/src/main/kotlin/io/rebble/cobble/pigeons/Pigeons.java
Original file line number Diff line number Diff line change
Expand Up @@ -4216,6 +4216,10 @@ public interface DebugControl {

void collectLogs(@NonNull String rwsId);

void getSensitiveLoggingEnabled(@NonNull Result<Boolean> result);

void setSensitiveLoggingEnabled(@NonNull Boolean enabled, @NonNull Result<Void> result);

/** The codec used by DebugControl. */
static @NonNull MessageCodec<Object> getCodec() {
return new StandardMessageCodec();
Expand Down Expand Up @@ -4246,6 +4250,62 @@ static void setup(@NonNull BinaryMessenger binaryMessenger, @Nullable DebugContr
channel.setMessageHandler(null);
}
}
{
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger, "dev.flutter.pigeon.DebugControl.getSensitiveLoggingEnabled", getCodec());
if (api != null) {
channel.setMessageHandler(
(message, reply) -> {
ArrayList<Object> wrapped = new ArrayList<Object>();
Result<Boolean> resultCallback =
new Result<Boolean>() {
public void success(Boolean result) {
wrapped.add(0, result);
reply.reply(wrapped);
}

public void error(Throwable error) {
ArrayList<Object> wrappedError = wrapError(error);
reply.reply(wrappedError);
}
};

api.getSensitiveLoggingEnabled(resultCallback);
});
} else {
channel.setMessageHandler(null);
}
}
{
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger, "dev.flutter.pigeon.DebugControl.setSensitiveLoggingEnabled", getCodec());
if (api != null) {
channel.setMessageHandler(
(message, reply) -> {
ArrayList<Object> wrapped = new ArrayList<Object>();
ArrayList<Object> args = (ArrayList<Object>) message;
Boolean enabledArg = (Boolean) args.get(0);
Result<Void> resultCallback =
new Result<Void>() {
public void success(Void result) {
wrapped.add(0, null);
reply.reply(wrapped);
}

public void error(Throwable error) {
ArrayList<Object> wrappedError = wrapError(error);
reply.reply(wrappedError);
}
};

api.setSensitiveLoggingEnabled(enabledArg, resultCallback);
});
} else {
channel.setMessageHandler(null);
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ class KMPPrefs: KoinComponent {
preferences[ENABLE_CALENDAR_KEY] = enabled
}
}

val sensitiveDataLoggingEnabled = dataStore.data.map { preferences ->
preferences[SENSITIVE_DATA_LOGGING_KEY] ?: false
}
suspend fun setSensitiveDataLoggingEnabled(enabled: Boolean) {
dataStore.edit { preferences ->
preferences[SENSITIVE_DATA_LOGGING_KEY] = enabled
}
}
}

private val ENABLE_CALENDAR_KEY = booleanPreferencesKey("enable_calendar_sync")
private val ENABLE_CALENDAR_KEY = booleanPreferencesKey("enable_calendar_sync")
private val SENSITIVE_DATA_LOGGING_KEY = booleanPreferencesKey("sensitive_data_logging")
2 changes: 2 additions & 0 deletions ios/Runner/Pigeon/Pigeons.h
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,8 @@ NSObject<FlutterMessageCodec> *DebugControlGetCodec(void);

@protocol DebugControl
- (void)collectLogsRwsId:(NSString *)rwsId error:(FlutterError *_Nullable *_Nonnull)error;
- (void)getSensitiveLoggingEnabledWithCompletion:(void (^)(NSNumber *_Nullable, FlutterError *_Nullable))completion;
- (void)setSensitiveLoggingEnabledEnabled:(NSNumber *)enabled completion:(void (^)(FlutterError *_Nullable))completion;
@end

extern void DebugControlSetup(id<FlutterBinaryMessenger> binaryMessenger, NSObject<DebugControl> *_Nullable api);
Expand Down
36 changes: 36 additions & 0 deletions ios/Runner/Pigeon/Pigeons.m
Original file line number Diff line number Diff line change
Expand Up @@ -2471,6 +2471,42 @@ void DebugControlSetup(id<FlutterBinaryMessenger> binaryMessenger, NSObject<Debu
[channel setMessageHandler:nil];
}
}
{
FlutterBasicMessageChannel *channel =
[[FlutterBasicMessageChannel alloc]
initWithName:@"dev.flutter.pigeon.DebugControl.getSensitiveLoggingEnabled"
binaryMessenger:binaryMessenger
codec:DebugControlGetCodec()];
if (api) {
NSCAssert([api respondsToSelector:@selector(getSensitiveLoggingEnabledWithCompletion:)], @"DebugControl api (%@) doesn't respond to @selector(getSensitiveLoggingEnabledWithCompletion:)", api);
[channel setMessageHandler:^(id _Nullable message, FlutterReply callback) {
[api getSensitiveLoggingEnabledWithCompletion:^(NSNumber *_Nullable output, FlutterError *_Nullable error) {
callback(wrapResult(output, error));
}];
}];
} else {
[channel setMessageHandler:nil];
}
}
{
FlutterBasicMessageChannel *channel =
[[FlutterBasicMessageChannel alloc]
initWithName:@"dev.flutter.pigeon.DebugControl.setSensitiveLoggingEnabled"
binaryMessenger:binaryMessenger
codec:DebugControlGetCodec()];
if (api) {
NSCAssert([api respondsToSelector:@selector(setSensitiveLoggingEnabledEnabled:completion:)], @"DebugControl api (%@) doesn't respond to @selector(setSensitiveLoggingEnabledEnabled:completion:)", api);
[channel setMessageHandler:^(id _Nullable message, FlutterReply callback) {
NSArray *args = message;
NSNumber *arg_enabled = GetNullableObjectAtIndex(args, 0);
[api setSensitiveLoggingEnabledEnabled:arg_enabled completion:^(FlutterError *_Nullable error) {
callback(wrapResult(nil, error));
}];
}];
} else {
[channel setMessageHandler:nil];
}
}
}
@interface TimelineControlCodecReader : FlutterStandardReader
@end
Expand Down
49 changes: 49 additions & 0 deletions lib/infrastructure/pigeons/pigeons.g.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2304,6 +2304,55 @@ class DebugControl {
return;
}
}

Future<bool> getSensitiveLoggingEnabled() async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.DebugControl.getSensitiveLoggingEnabled', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(null) as List<Object?>?;
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else if (replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (replyList[0] as bool?)!;
}
}

Future<void> setSensitiveLoggingEnabled(bool arg_enabled) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.DebugControl.setSensitiveLoggingEnabled', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_enabled]) as List<Object?>?;
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else {
return;
}
}
}

class _TimelineControlCodec extends StandardMessageCodec {
Expand Down
17 changes: 17 additions & 0 deletions lib/ui/devoptions/debug_options_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ class DebugOptionsPage extends HookConsumerWidget implements CobbleScreen {
final bootOverrideUrlController = useTextEditingController();

final DebugControl debug = DebugControl();
final sensitiveLoggingEnabled = useState(false);
useEffect(() {
debug.getSensitiveLoggingEnabled().then((value) {
sensitiveLoggingEnabled.value = value;
});
return null;
}, []);

useEffect(() {
bootUrlController.text = bootUrl;
Expand Down Expand Up @@ -88,6 +95,16 @@ class DebugOptionsPage extends HookConsumerWidget implements CobbleScreen {
],
),
),
SwitchListTile(
contentPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15),
value: sensitiveLoggingEnabled.value,
onChanged: (value) {
debug.setSensitiveLoggingEnabled(value);
sensitiveLoggingEnabled.value = value;
},
title: const Text("Enable sensitive data logging"),
subtitle: const Text("Enables more in-depth logging at the cost of privacy (e.g. notification contents)"),
),
CobbleButton(
onPressed: () async {
try {
Expand Down
4 changes: 4 additions & 0 deletions pigeons/pigeons.dart
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,10 @@ abstract class IntentControl {
@HostApi()
abstract class DebugControl {
void collectLogs(String rwsId);
@async
bool getSensitiveLoggingEnabled();
@async
void setSensitiveLoggingEnabled(bool enabled);
}

@HostApi()
Expand Down

0 comments on commit 1df8984

Please sign in to comment.