proxy private tabs
This commit is contained in:
+29
-9
@@ -1,8 +1,10 @@
|
||||
import 'package:fast_equatable/fast_equatable.dart';
|
||||
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
||||
import 'package:nullability/nullability.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/domain/providers.dart';
|
||||
import 'package:weblibre/features/tor/domain/services/tor_proxy.dart';
|
||||
import 'package:weblibre/features/user/domain/repositories/general_settings.dart';
|
||||
|
||||
part 'proxy_settings_replication.g.dart';
|
||||
|
||||
@@ -25,21 +27,39 @@ class ProxySettingsReplication extends _$ProxySettingsReplication {
|
||||
ref.listen(
|
||||
fireImmediately: true,
|
||||
containersWithCountProvider.select(
|
||||
(value) => EquatableValue(
|
||||
value.valueOrNull
|
||||
?.where((container) => container.metadata.useProxy)
|
||||
.map((container) => container.metadata.contextualIdentity)
|
||||
.nonNulls
|
||||
.toList(),
|
||||
),
|
||||
(value) => EquatableValue(value.valueOrNull),
|
||||
),
|
||||
(previous, next) async {
|
||||
if (next.value != null) {
|
||||
for (final contextId in next.value!) {
|
||||
await _service.addContainerProxy(contextId);
|
||||
for (final container in next.value!) {
|
||||
if (container.metadata.contextualIdentity.isNotEmpty) {
|
||||
if (container.metadata.useProxy) {
|
||||
await _service.addContainerProxy(
|
||||
container.metadata.contextualIdentity!,
|
||||
);
|
||||
} else {
|
||||
await _service.removeContainerProxy(
|
||||
container.metadata.contextualIdentity!,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
ref.listen(
|
||||
fireImmediately: true,
|
||||
generalSettingsRepositoryProvider.select(
|
||||
(value) => value.proxyPrivateTabsTor,
|
||||
),
|
||||
(previous, next) async {
|
||||
if (next) {
|
||||
await _service.addContainerProxy('private');
|
||||
} else {
|
||||
await _service.removeContainerProxy('private');
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ part of 'proxy_settings_replication.dart';
|
||||
// **************************************************************************
|
||||
|
||||
String _$proxySettingsReplicationHash() =>
|
||||
r'9571d178534f68ad3104f1168665ffb57711c6cc';
|
||||
r'cd3a7573abfa0b32562289c02e77f0b44e88a8ae';
|
||||
|
||||
/// See also [ProxySettingsReplication].
|
||||
@ProviderFor(ProxySettingsReplication)
|
||||
|
||||
@@ -2,7 +2,10 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_material_design_icons/flutter_material_design_icons.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:weblibre/features/settings/presentation/controllers/save_settings.dart';
|
||||
import 'package:weblibre/features/tor/domain/services/tor_proxy.dart';
|
||||
import 'package:weblibre/features/user/data/models/general_settings.dart';
|
||||
import 'package:weblibre/features/user/domain/repositories/general_settings.dart';
|
||||
import 'package:weblibre/presentation/hooks/on_initialization.dart';
|
||||
|
||||
class TorProxyScreen extends HookConsumerWidget {
|
||||
@@ -11,6 +14,11 @@ class TorProxyScreen extends HookConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final torProxyPort = ref.watch(torProxyServiceProvider);
|
||||
final proxyPrivateTabsTor = ref.watch(
|
||||
generalSettingsRepositoryProvider.select(
|
||||
(value) => value.proxyPrivateTabsTor,
|
||||
),
|
||||
);
|
||||
|
||||
useOnInitialization(() async {
|
||||
await ref.read(torProxyServiceProvider.notifier).requestSync();
|
||||
@@ -77,6 +85,55 @@ class TorProxyScreen extends HookConsumerWidget {
|
||||
},
|
||||
),
|
||||
),
|
||||
ListTileTheme(
|
||||
iconColor: Colors.white,
|
||||
textColor: Colors.white,
|
||||
child: SwitchListTile.adaptive(
|
||||
inactiveThumbColor: Colors.white,
|
||||
activeColor: const Color(0xFF68B030),
|
||||
trackColor: WidgetStateProperty.resolveWith<Color?>((
|
||||
Set<WidgetState> states,
|
||||
) {
|
||||
if (states.isEmpty) {
|
||||
return const Color(0xFF333A41);
|
||||
}
|
||||
return null; // Use the default color.
|
||||
}),
|
||||
trackOutlineColor:
|
||||
WidgetStateProperty.resolveWith<Color?>((
|
||||
Set<WidgetState> states,
|
||||
) {
|
||||
if (states.isEmpty) {
|
||||
return Colors.white;
|
||||
}
|
||||
return null; // Use the default color.
|
||||
}),
|
||||
thumbIcon: WidgetStateProperty.resolveWith<Icon?>((
|
||||
Set<WidgetState> states,
|
||||
) {
|
||||
if (states.contains(WidgetState.selected)) {
|
||||
return const Icon(MdiIcons.incognito);
|
||||
}
|
||||
return null; // Use the default color.
|
||||
}),
|
||||
value: proxyPrivateTabsTor,
|
||||
title: const Text('Proxy Private Tabs'),
|
||||
subtitle: const Text(
|
||||
'When enabled, all Private Tabs will be tunneled through Tor',
|
||||
),
|
||||
secondary: const Icon(MdiIcons.arrowDecision),
|
||||
onChanged: (value) async {
|
||||
await ref
|
||||
.read(
|
||||
saveGeneralSettingsControllerProvider.notifier,
|
||||
)
|
||||
.save(
|
||||
(currentSettings) => currentSettings.copyWith
|
||||
.proxyPrivateTabsTor(value),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -87,6 +144,7 @@ class TorProxyScreen extends HookConsumerWidget {
|
||||
const Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(height: 8),
|
||||
LinearProgressIndicator(
|
||||
backgroundColor: Color(0xFF333A41),
|
||||
color: Color(0xFF68B030),
|
||||
|
||||
@@ -28,12 +28,15 @@ class GeneralSettings with FastEquatable {
|
||||
final Set<DeleteBrowsingDataType>? deleteBrowsingDataOnQuit;
|
||||
final String defaultSearchProvider;
|
||||
|
||||
final bool proxyPrivateTabsTor;
|
||||
|
||||
GeneralSettings({
|
||||
required this.themeMode,
|
||||
required this.enableReadability,
|
||||
required this.enforceReadability,
|
||||
required this.deleteBrowsingDataOnQuit,
|
||||
required this.defaultSearchProvider,
|
||||
required this.proxyPrivateTabsTor,
|
||||
});
|
||||
|
||||
GeneralSettings.withDefaults({
|
||||
@@ -42,10 +45,12 @@ class GeneralSettings with FastEquatable {
|
||||
bool? enforceReadability,
|
||||
this.deleteBrowsingDataOnQuit,
|
||||
String? defaultSearchProvider,
|
||||
bool? proxyPrivateTabsTor,
|
||||
}) : themeMode = themeMode ?? ThemeMode.dark,
|
||||
enableReadability = enableReadability ?? true,
|
||||
enforceReadability = enforceReadability ?? false,
|
||||
defaultSearchProvider = defaultSearchProvider ?? 'lais';
|
||||
defaultSearchProvider = defaultSearchProvider ?? 'lais',
|
||||
proxyPrivateTabsTor = proxyPrivateTabsTor ?? false;
|
||||
|
||||
factory GeneralSettings.fromJson(Map<String, dynamic> json) =>
|
||||
_$GeneralSettingsFromJson(json);
|
||||
@@ -59,5 +64,6 @@ class GeneralSettings with FastEquatable {
|
||||
enforceReadability,
|
||||
deleteBrowsingDataOnQuit,
|
||||
defaultSearchProvider,
|
||||
proxyPrivateTabsTor,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ abstract class _$GeneralSettingsCWProxy {
|
||||
|
||||
GeneralSettings defaultSearchProvider(String defaultSearchProvider);
|
||||
|
||||
GeneralSettings proxyPrivateTabsTor(bool proxyPrivateTabsTor);
|
||||
|
||||
/// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `GeneralSettings(...).copyWith.fieldName(...)` to override fields one at a time with nullification support.
|
||||
///
|
||||
/// Usage
|
||||
@@ -31,6 +33,7 @@ abstract class _$GeneralSettingsCWProxy {
|
||||
bool enforceReadability,
|
||||
Set<DeleteBrowsingDataType>? deleteBrowsingDataOnQuit,
|
||||
String defaultSearchProvider,
|
||||
bool proxyPrivateTabsTor,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -60,6 +63,10 @@ class _$GeneralSettingsCWProxyImpl implements _$GeneralSettingsCWProxy {
|
||||
GeneralSettings defaultSearchProvider(String defaultSearchProvider) =>
|
||||
this(defaultSearchProvider: defaultSearchProvider);
|
||||
|
||||
@override
|
||||
GeneralSettings proxyPrivateTabsTor(bool proxyPrivateTabsTor) =>
|
||||
this(proxyPrivateTabsTor: proxyPrivateTabsTor);
|
||||
|
||||
@override
|
||||
/// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `GeneralSettings(...).copyWith.fieldName(...)` to override fields one at a time with nullification support.
|
||||
///
|
||||
@@ -73,6 +80,7 @@ class _$GeneralSettingsCWProxyImpl implements _$GeneralSettingsCWProxy {
|
||||
Object? enforceReadability = const $CopyWithPlaceholder(),
|
||||
Object? deleteBrowsingDataOnQuit = const $CopyWithPlaceholder(),
|
||||
Object? defaultSearchProvider = const $CopyWithPlaceholder(),
|
||||
Object? proxyPrivateTabsTor = const $CopyWithPlaceholder(),
|
||||
}) {
|
||||
return GeneralSettings(
|
||||
themeMode: themeMode == const $CopyWithPlaceholder()
|
||||
@@ -97,6 +105,10 @@ class _$GeneralSettingsCWProxyImpl implements _$GeneralSettingsCWProxy {
|
||||
? _value.defaultSearchProvider
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: defaultSearchProvider as String,
|
||||
proxyPrivateTabsTor: proxyPrivateTabsTor == const $CopyWithPlaceholder()
|
||||
? _value.proxyPrivateTabsTor
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: proxyPrivateTabsTor as bool,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -121,6 +133,7 @@ GeneralSettings _$GeneralSettingsFromJson(Map<String, dynamic> json) =>
|
||||
?.map((e) => $enumDecode(_$DeleteBrowsingDataTypeEnumMap, e))
|
||||
.toSet(),
|
||||
defaultSearchProvider: json['defaultSearchProvider'] as String?,
|
||||
proxyPrivateTabsTor: json['proxyPrivateTabsTor'] as bool?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$GeneralSettingsToJson(GeneralSettings instance) =>
|
||||
@@ -132,6 +145,7 @@ Map<String, dynamic> _$GeneralSettingsToJson(GeneralSettings instance) =>
|
||||
?.map((e) => _$DeleteBrowsingDataTypeEnumMap[e]!)
|
||||
.toList(),
|
||||
'defaultSearchProvider': instance.defaultSearchProvider,
|
||||
'proxyPrivateTabsTor': instance.proxyPrivateTabsTor,
|
||||
};
|
||||
|
||||
const _$ThemeModeEnumMap = {
|
||||
|
||||
@@ -43,6 +43,10 @@ class GeneralSettingsRepository extends _$GeneralSettingsRepository {
|
||||
DriftSqlType.string,
|
||||
db.typeMapping,
|
||||
),
|
||||
'proxyPrivateTabsTor': settings['proxyPrivateTabsTor']?.readAs(
|
||||
DriftSqlType.bool,
|
||||
db.typeMapping,
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ part of 'general_settings.dart';
|
||||
// **************************************************************************
|
||||
|
||||
String _$generalSettingsRepositoryHash() =>
|
||||
r'2dcc600ccfb074fa27fae90acb3d61e10c87e884';
|
||||
r'e16ce010f5feb692bd9f3a394c9502f959ded589';
|
||||
|
||||
/// See also [GeneralSettingsRepository].
|
||||
@ProviderFor(GeneralSettingsRepository)
|
||||
|
||||
+10
-2
@@ -9,6 +9,7 @@ import _OnRequestDetails = browser.proxy._OnRequestDetails
|
||||
const localhosts = new Set(['localhost', '127.0.0.1', '[::1]'])
|
||||
|
||||
const containerIdentifier = 'firefox-container-'
|
||||
const privateIdentifier = 'firefox-private'
|
||||
|
||||
type DoNotProxy = never[]
|
||||
export const doNotProxy: DoNotProxy = []
|
||||
@@ -59,9 +60,16 @@ export default class BackgroundMain {
|
||||
if (requestDetails.tabId > -1) {
|
||||
const tab = (await browser.tabs.get(requestDetails.tabId))
|
||||
|
||||
if (tab.cookieStoreId?.startsWith(containerIdentifier) === true) {
|
||||
if (tab.cookieStoreId?.startsWith(containerIdentifier) === true || tab.cookieStoreId === privateIdentifier) {
|
||||
try {
|
||||
const cookieStoreId = tab.cookieStoreId.substring(containerIdentifier.length)
|
||||
let cookieStoreId: string
|
||||
|
||||
if (tab.cookieStoreId.startsWith(containerIdentifier)) {
|
||||
cookieStoreId = tab.cookieStoreId.substring(containerIdentifier.length)
|
||||
} else {
|
||||
// Handle private tabs - use 'private' as identifier
|
||||
cookieStoreId = 'private'
|
||||
}
|
||||
|
||||
const proxies = await this.store.getProxiesForContainer(cookieStoreId)
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ port.onMessage.addListener((raw: unknown): void => {
|
||||
break
|
||||
case "removeContainerProxy":
|
||||
store.removeContainerProxyRelation(message.args, "tor")
|
||||
console.log('removed container relation ' + message.args)
|
||||
break
|
||||
case "healthcheck":
|
||||
port.postMessage({
|
||||
|
||||
Reference in New Issue
Block a user