add install addon functionality

This commit is contained in:
Fabian Freund
2025-05-05 14:34:47 +02:00
parent 8e0325f6b5
commit 35fcae3ed7
7 changed files with 1526 additions and 170 deletions
@@ -0,0 +1,50 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:lensai/core/logger.dart';
import 'package:lensai/features/geckoview/domain/providers.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'browser_addon.g.dart';
@Riverpod()
class BrowserAddonService extends _$BrowserAddonService {
Future<Uri> getAddonXpiUrl(String guid) async {
final url = 'https://addons.mozilla.org/api/v5/addons/addon/$guid/';
try {
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
final data = jsonDecode(response.body) as Map<String, dynamic>;
// ignore: avoid_dynamic_calls
final xpiUrl = data['current_version']['file']['url'] as String;
return Uri.parse(xpiUrl);
} else {
throw Exception('Failed to load addon data: ${response.statusCode}');
}
} catch (e) {
throw Exception('Error fetching addon data: $e');
}
}
Future<bool> install(String addonGuid) async {
try {
final xpiUrl = await getAddonXpiUrl(addonGuid);
await ref.read(addonServiceProvider).installAddon(xpiUrl);
return true;
} catch (e, s) {
logger.e('Failed installing $addonGuid', error: e, stackTrace: s);
return false;
}
}
@override
void build() {
return;
}
}
@@ -0,0 +1,28 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'browser_addon.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
String _$browserAddonServiceHash() =>
r'1dd73c322e712e1492d74f1af844d5b5cc8f81bb';
/// See also [BrowserAddonService].
@ProviderFor(BrowserAddonService)
final browserAddonServiceProvider =
AutoDisposeNotifierProvider<BrowserAddonService, void>.internal(
BrowserAddonService.new,
name: r'browserAddonServiceProvider',
debugGetCreateSourceHash:
const bool.fromEnvironment('dart.vm.product')
? null
: _$browserAddonServiceHash,
dependencies: null,
allTransitiveDependencies: null,
);
typedef _$BrowserAddonService = AutoDisposeNotifier<void>;
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
@@ -24,4 +24,16 @@ class GeckoAddonsApiImpl(private val context: Context) : GeckoAddonsApi {
WebExtensionActionType.PAGE -> components.features.webExtensionToolbarFeature.invokeAddonPageAction(extensionId)
}
}
override fun installAddon(url: String, callback: (Result<Unit>) -> Unit) {
components.core.addonManager.installAddon(
url = url,
onSuccess = { _ ->
callback(Result.success(Unit))
},
onError = { e ->
callback(Result.failure(e))
}
)
}
}
@@ -39,6 +39,10 @@ class GeckoAddonService extends GeckoAddonEvents {
return _api.invokeAddonAction(extensionId, actionType);
}
Future<void> installAddon(Uri url) {
return _api.installAddon(url.toString());
}
@override
void onRemoveWebExtensionAction(
int timestamp,
File diff suppressed because it is too large Load Diff
@@ -1058,6 +1058,9 @@ abstract class GeckoAddonsApi {
void startAddonManagerActivity();
void invokeAddonAction(String extensionId, WebExtensionActionType actionType);
@async
void installAddon(String url);
}
@FlutterApi()