diff --git a/lib/main.dart b/lib/main.dart index a8cfa716..c04c8e0a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -11,6 +11,8 @@ import 'package:package_info_plus/package_info_plus.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:theme_mode_handler/theme_mode_handler.dart'; +import 'package:chrome_extension/runtime.dart'; +import 'dart:js_interop'; import 'models/hive/app_options.dart'; import 'models/hive/pending_notifications.dart'; @@ -34,6 +36,7 @@ import 'tools/app_localizations.dart'; import 'tools/app_routes.dart'; import 'tools/app_themes.dart'; import 'tools/session_checker.dart'; +import 'tools/browser_extension_detector.dart'; import 'widgets/spinning_peercoin_icon.dart'; late bool setupFinished; @@ -178,6 +181,14 @@ void main() async { ); } + if (kIsWeb && getChromeRuntimeId() != null) { + // Test: + print(getChromeRuntimeId()); + chrome.runtime.onMessage.listen((e) { + e.sendResponse.callAsFunction(null, {'the_response': 1}.jsify()); + }); + } + //run runApp(const PeercoinApp()); } diff --git a/lib/screens/wallet/wallet_home.dart b/lib/screens/wallet/wallet_home.dart index 6d069fc6..d1bcb48f 100644 --- a/lib/screens/wallet/wallet_home.dart +++ b/lib/screens/wallet/wallet_home.dart @@ -13,6 +13,7 @@ import 'package:peercoin/widgets/wallet/wallet_home/wallet_hide_bottom_sheet.dar import 'package:peercoin/widgets/wallet/wallet_home/wallet_reset_bottom_sheet.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import '../../tools/browser_extension_detector.dart'; import '../../models/available_coins.dart'; import '../../models/hive/coin_wallet.dart'; @@ -208,6 +209,11 @@ class _WalletHomeState extends State } } + if (kIsWeb && isBrowserExtension()) { + // TODO move the listener here + print("Setting up Chrome message listener!"); + } + checkPendingNotifications(); if (mounted) { context.loaderOverlay.hide(); diff --git a/lib/tools/browser_extension_detector.dart b/lib/tools/browser_extension_detector.dart new file mode 100644 index 00000000..e69b9aa1 --- /dev/null +++ b/lib/tools/browser_extension_detector.dart @@ -0,0 +1,18 @@ +import 'dart:js_interop'; + +@JS('chrome.runtime.id') +external JSString? get chromeRuntimeId; + +String? getChromeRuntimeId() { + try { + final id = chromeRuntimeId; + return id?.toDart; + } catch (e) { + return null; + } +} + +bool isBrowserExtension() { + // Wrapper around both Chrome and Firefox detection (TODO) + return getChromeRuntimeId() != null; +} diff --git a/web/background.js b/web/background.js new file mode 100644 index 00000000..f3c5ae10 --- /dev/null +++ b/web/background.js @@ -0,0 +1,20 @@ +chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { + console.log('Message from website:', message); + + // Check if the message type matches "PEERCOIN_BROWSER_EXTENSION" + if (message.type === "PEERCOIN_BROWSER_EXTENSION") { + // Forward the message to Flutter and handle the response + chrome.runtime.sendMessage(message, (response) => { + console.log('Response from Flutter:', response); + + // Send the response back to the website + sendResponse(response); + }); + + // Indicate sendResponse will be handled asynchronously + return true; + } + + // Ignore messages that do not match the type + return false; +}); diff --git a/web/content_script.js b/web/content_script.js new file mode 100644 index 00000000..726a609f --- /dev/null +++ b/web/content_script.js @@ -0,0 +1,31 @@ +function injectPageScript() { + const script = document.createElement('script'); + script.src = chrome.runtime.getURL('page_script.js'); + script.onload = () => { + console.log('Peercoin extension page script injected successfully.'); + script.remove(); // Optional: remove script after injection + }; + (document.head || document.documentElement).appendChild(script); +} + +// Inject the script when content script loads +injectPageScript(); + +// Listener for messages from the web page +window.addEventListener('message', (event) => { + // Validate the event source and ensure it's a Peercoin-specific message + if (event.source !== window || !event.data || event.data.type !== 'PEERCOIN_BROWSER_EXTENSION') return; + + console.log('Content script received Peercoin extension event:', event.data); + + // Relay the Peercoin event to the background script + chrome.runtime.sendMessage(event.data, (response) => { + if (chrome.runtime.lastError) { + console.error('Error sending Peercoin extension message to background:', chrome.runtime.lastError.message); + } else { + console.log('Received response from extension background script:', response); + } + }); +}); + +console.log('Peercoin extension content script initialized.'); \ No newline at end of file diff --git a/web/manifest.json b/web/manifest.json index 68db2efa..b96c923c 100644 --- a/web/manifest.json +++ b/web/manifest.json @@ -19,13 +19,21 @@ } }, "permissions": [ - "storage", - "activeTab" + "activeTab", + "scripting" ], "host_permissions": [ "*://*.peercoin.net/*" ], "web_accessible_resources": [ + { + "resources": [ + "page_script.js" + ], + "matches": [ + "" + ] + }, { "resources": [ "*.html", @@ -42,5 +50,19 @@ "optional_permissions": [ "clipboardWrite", "clipboardRead" + ], + "background": { + "service_worker": "background.js" + }, + "content_scripts": [ + { + "matches": [ + "" + ], + "js": [ + "content_script.js" + ], + "run_at": "document_start" + } ] } \ No newline at end of file diff --git a/web/page_script.js b/web/page_script.js new file mode 100644 index 00000000..986e41e1 --- /dev/null +++ b/web/page_script.js @@ -0,0 +1,10 @@ +window.sendPeercoinExtensionMessage = function (message) { + const extensionMessage = { + type: '$PEERCOIN_BROWSER_EXTENSION', + payload: message, + timestamp: Date.now() + }; + window.postMessage(extensionMessage, '*'); +}; + +console.log('Peercoin extension page script loaded'); \ No newline at end of file