Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android plugin version 6 - UserScripts not executing on new tabs. #1455

Closed
Imdavyking opened this issue Dec 5, 2022 · 12 comments
Closed

Android plugin version 6 - UserScripts not executing on new tabs. #1455

Imdavyking opened this issue Dec 5, 2022 · 12 comments

Comments

@Imdavyking
Copy link

userscript works well, but once a new tab is open by javascript, or a new tab is opened manually, the Userscripts does not execute on that webview.

initialUserScripts: UnmodifiableListView([
UserScript(
source: widget.provider + initJs,
injectionTime: UserScriptInjectionTime.AT_DOCUMENT_START,
)
]),

@pichillilorenzo
Copy link
Owner

What example project are you talking about?

@Imdavyking
Copy link
Author

I am injecting javascript in each webview, as they are opened it only works for the first webview tab...it does not works for the rest.

@Imdavyking
Copy link
Author

InAppWebView(
          windowId: widget.windowId,
          initialUrlRequest:
              URLRequest(url: WebUri(widget.data ?? walletURL)),
          initialSettings: InAppWebViewSettings(
            useShouldOverrideUrlLoading: true,
            forceDark: Theme.of(context).brightness == Brightness.dark
                ? ForceDark.ON
                : ForceDark.OFF,
            javaScriptCanOpenWindowsAutomatically: true,
            supportMultipleWindows: true,
            isFraudulentWebsiteWarningEnabled: true,
            safeBrowsingEnabled: true,
            mediaPlaybackRequiresUserGesture: false,
            allowsInlineMediaPlayback: true,
          ),
          onPermissionRequest: (controller, request) async {
            return PermissionResponse(
              resources: request.resources,
              action: PermissionResponseAction.GRANT,
            );
          },
          shouldOverrideUrlLoading: (
            InAppWebViewController controller,
            NavigationAction shouldOverrideUrl,
          ) async {
            Uri url = shouldOverrideUrl.request.url;

            List<String> allowedAction = [
              "http",
              "https",
              "file",
              "chrome",
              "data",
              "javascript",
              "about"
            ];
            if (!allowedAction.contains(url.scheme)) {
              try {
                await launchUrl(url);
              } catch (_) {}
              return NavigationActionPolicy.CANCEL;
            }
            try {
              final urlResponse =
                  await get(Uri.parse(scamDbUrl + url.host));
              final isResponseError = urlResponse.statusCode ~/ 100 == 4 ||
                  urlResponse.statusCode ~/ 100 == 5;

              if (!isResponseError) {
                final jsonDecoded = jsonDecode(urlResponse.body);

                if (jsonDecoded['success'] &&
                    jsonDecoded['result']['status'] == 'blocked') {
                  PackageInfo packageInfo =
                      await PackageInfo.fromPlatform();

                  bool shouldByPass = false;

                  await slideUpPanel(
                    context,
                    SingleChildScrollView(
                      child: Padding(
                        padding: const EdgeInsets.all(25),
                        child: Column(children: [
                          Text(
                            AppLocalizations.of(context).scamSiteDetected,
                            style: const TextStyle(fontSize: 20),
                          ),
                          const SizedBox(
                            height: 20,
                          ),
                          Text(
                            AppLocalizations.of(context)
                                .scamSiteDetectedDescription(
                              url.host,
                              packageInfo.appName,
                            ),
                            textAlign: TextAlign.center,
                            style: const TextStyle(
                              fontSize: 18,
                            ),
                          ),
                          const SizedBox(
                            height: 20,
                          ),
                          TextButton(
                            style: TextButton.styleFrom(
                              foregroundColor: Colors.white,
                              backgroundColor: Colors.red,
                            ),
                            onPressed: () async {
                              shouldByPass = true;
                              Get.back();
                            },
                            child: Text(
                              AppLocalizations.of(context).ignore,
                              style: const TextStyle(
                                fontSize: 20,
                              ),
                            ),
                          ),
                        ]),
                      ),
                    ),
                  );

                  if (shouldByPass) {
                    return NavigationActionPolicy.ALLOW;
                  }

                  return NavigationActionPolicy.CANCEL;
                }
              }
            } catch (_) {}

            return NavigationActionPolicy.ALLOW;
          },
          onWebViewCreated: (controller) async {
            _controller = controller;

            _controller.addJavaScriptHandler(
              handlerName: 'requestAccounts',
              callback: (args) async {
                final pref = Hive.box(secureStorageKey);
                final mnemonic = pref.get(currentMmenomicKey);

                int chainId = pref.get(dappChainIdKey);
                final blockChainDetails =
                    getEthereumDetailsFromChainId(chainId);
                final web3Response = await getEthereumFromMemnomic(
                  mnemonic,
                  blockChainDetails['coinType'],
                );

                final sendingAddress = web3Response['eth_wallet_address'];
                final id = args[0];
                try {
                  await _controller.evaluateJavascript(
                    source:
                        'AlphaWallet.executeCallback($id, null, ["$sendingAddress"]);',
                  );
                } catch (e) {
                  //  replace all quotes in error
                  final error = e.toString().replaceAll('"', '\'');

                  await _controller.evaluateJavascript(
                    source:
                        'AlphaWallet.executeCallback($id, "$error",null);',
                  );
                }
              },
            );
            _controller.addJavaScriptHandler(
              handlerName: 'walletAddEthereumChain',
              callback: (args) async {
                final pref = Hive.box(secureStorageKey);
                int chainId = pref.get(dappChainIdKey);
                final id = args[0];

                final switchChainId =
                    BigInt.parse(json.decode(args[1])['chainId']).toInt();

                final currentChainIdData =
                    getEthereumDetailsFromChainId(chainId);

                final switchChainIdData =
                    getEthereumDetailsFromChainId(switchChainId);

                if (chainId == switchChainId) {
                  await _controller.evaluateJavascript(
                      source:
                          'AlphaWallet.executeCallback($id, "cancelled", null);');
                  return;
                }

                if (switchChainIdData == null) {
                  await _controller.evaluateJavascript(
                      source:
                          'AlphaWallet.executeCallback($id, "we can not add this block", null);');
                } else {
                  switchEthereumChain(
                    context: context,
                    currentChainIdData: currentChainIdData,
                    switchChainIdData: switchChainIdData,
                    onConfirm: () async {
                      await changeBrowserChainId_(
                        switchChainIdData['chainId'],
                        switchChainIdData['rpc'],
                      );

                      await _controller.evaluateJavascript(
                        source:
                            'AlphaWallet.executeCallback($id, null, null);',
                      );
                      Navigator.pop(context);
                    },
                    onReject: () async {
                      await _controller.evaluateJavascript(
                          source:
                              'AlphaWallet.executeCallback($id, "user rejected switch", null);');
                      Navigator.pop(context);
                    },
                  );
                }
              },
            );
            _controller.addJavaScriptHandler(
              handlerName: 'walletSwitchEthereumChain',
              callback: (args) async {
                final pref = Hive.box(secureStorageKey);
                int chainId = pref.get(dappChainIdKey);
                final id = args[0];

                final switchChainId =
                    BigInt.parse(json.decode(args[1])['chainId']).toInt();

                final currentChainIdData =
                    getEthereumDetailsFromChainId(chainId);

                final switchChainIdData =
                    getEthereumDetailsFromChainId(switchChainId);

                if (chainId == switchChainId) {
                  await _controller.evaluateJavascript(
                    source:
                        'AlphaWallet.executeCallback($id, "cancelled", null);',
                  );
                  return;
                }

                if (switchChainIdData == null) {
                  await _controller.evaluateJavascript(
                    source:
                        'AlphaWallet.executeCallback($id, "we can not add this block", null);',
                  );
                } else {
                  switchEthereumChain(
                    context: context,
                    currentChainIdData: currentChainIdData,
                    switchChainIdData: switchChainIdData,
                    onConfirm: () async {
                      await changeBrowserChainId_(
                        switchChainIdData['chainId'],
                        switchChainIdData['rpc'],
                      );

                      await _controller.evaluateJavascript(
                        source:
                            'AlphaWallet.executeCallback($id, null, null);',
                      );
                      Get.back();
                    },
                    onReject: () async {
                      await _controller.evaluateJavascript(
                        source:
                            'AlphaWallet.executeCallback($id, "user rejected switch", null);',
                      );
                      Get.back();
                    },
                  );
                }
              },
            );
            _controller.addJavaScriptHandler(
              handlerName: 'ethCall',
              callback: (args) async {
                final pref = Hive.box(secureStorageKey);
                int chainId = pref.get(dappChainIdKey);
                final rpc = getEthereumDetailsFromChainId(chainId)['rpc'];
                final id = args[0];
                final tx = json.decode(args[1]) as Map;
                try {
                  final client = Web3Client(
                    rpc,
                    Client(),
                  );

                  final mnemonic = pref.get(currentMmenomicKey);
                  final blockChainDetails =
                      getEthereumDetailsFromChainId(chainId);
                  final web3Response = await getEthereumFromMemnomic(
                    mnemonic,
                    blockChainDetails['coinType'],
                  );

                  final sendingAddress = web3Response['eth_wallet_address'];

                  final response = await client.callRaw(
                    sender: EthereumAddress.fromHex(sendingAddress),
                    contract: EthereumAddress.fromHex(tx['to']),
                    data: txDataToUintList(tx['data']),
                  );
                  await _controller.evaluateJavascript(
                    source:
                        'AlphaWallet.executeCallback($id, null, "$response");',
                  );
                } catch (e) {
                  final error = e.toString().replaceAll('"', '\'');

                  await _controller.evaluateJavascript(
                    source:
                        'AlphaWallet.executeCallback($id, "$error",null);',
                  );
                }
              },
            );
            _controller.addJavaScriptHandler(
              handlerName: 'signTransaction',
              callback: (args) async {
                final pref = Hive.box(secureStorageKey);
                int chainId = pref.get(dappChainIdKey);
                final mnemonic = pref.get(currentMmenomicKey);

                final blockChainDetails =
                    getEthereumDetailsFromChainId(chainId);
                final rpc = blockChainDetails['rpc'];
                final web3Response = await getEthereumFromMemnomic(
                  mnemonic,
                  blockChainDetails['coinType'],
                );

                final privateKey = web3Response['eth_wallet_privateKey'];

                final sendingAddress = web3Response['eth_wallet_address'];
                final client = Web3Client(
                  rpc,
                  Client(),
                );
                final credentials = EthPrivateKey.fromHex(privateKey);

                final id = args[0];
                final to = args[1];
                final value = args[2];
                final nonce = args[3] == -1 ? null : args[3];
                final gasPrice = args[5];
                final data = args[6];

                await signTransaction(
                  gasPriceInWei_: gasPrice,
                  to: to,
                  from: sendingAddress,
                  txData: data,
                  valueInWei_: value,
                  gasInWei_: null,
                  networkIcon: null,
                  context: context,
                  blockChainCurrencySymbol: blockChainDetails['symbol'],
                  name: '',
                  onConfirm: () async {
                    try {
                      final signedTransaction =
                          await client.signTransaction(
                        credentials,
                        Transaction(
                          to: to != null
                              ? EthereumAddress.fromHex(to)
                              : null,
                          value: value != null
                              ? EtherAmount.inWei(
                                  BigInt.parse(value),
                                )
                              : null,
                          nonce: nonce,
                          gasPrice: gasPrice != null
                              ? EtherAmount.inWei(BigInt.parse(gasPrice))
                              : null,
                          data: txDataToUintList(data),
                        ),
                        chainId: chainId,
                      );

                      final response = await client
                          .sendRawTransaction(signedTransaction);

                      await _controller.evaluateJavascript(
                        source:
                            'AlphaWallet.executeCallback($id, null, "$response");',
                      );
                    } catch (e) {
                      final error = e.toString().replaceAll('"', '\'');

                      await _controller.evaluateJavascript(
                        source:
                            'AlphaWallet.executeCallback($id, "$error",null);',
                      );
                    } finally {
                      Get.back();
                    }
                  },
                  onReject: () async {
                    await _controller.evaluateJavascript(
                      source:
                          'AlphaWallet.executeCallback($id, "user rejected transaction",null);',
                    );
                    Get.back();
                  },
                  title: 'Sign Transaction',
                  chainId: chainId,
                );
              },
            );

            _controller.addJavaScriptHandler(
              handlerName: 'signMessage',
              callback: (args) async {
                final pref = Hive.box(secureStorageKey);
                int chainId = pref.get(dappChainIdKey);
                final mnemonic = pref.get(currentMmenomicKey);

                final blockChainDetails =
                    getEthereumDetailsFromChainId(chainId);
                final web3Response = await getEthereumFromMemnomic(
                  mnemonic,
                  blockChainDetails['coinType'],
                );

                final privateKey = web3Response['eth_wallet_privateKey'];

                final credentials = EthPrivateKey.fromHex(privateKey);

                final id = args[0];
                String data = args[1];
                String messageType = args[2];
                if (messageType == typedMessageSignKey) {
                  data = json.decode(data)['data'];
                }

                await signMessage(
                  context: context,
                  messageType: messageType,
                  data: data,
                  networkIcon: null,
                  name: null,
                  onConfirm: () async {
                    try {
                      String signedDataHex;
                      Uint8List signedData;
                      if (messageType == typedMessageSignKey) {
                        signedDataHex = EthSigUtil.signTypedData(
                          privateKey: privateKey,
                          jsonData: data,
                          version: TypedDataVersion.V4,
                        );
                      } else if (messageType == personalSignKey) {
                        signedData = await credentials.signPersonalMessage(
                          txDataToUintList(data),
                        );
                        signedDataHex =
                            bytesToHex(signedData, include0x: true);
                      } else if (messageType == normalSignKey) {
                        try {
                          signedDataHex = EthSigUtil.signMessage(
                            privateKey: privateKey,
                            message: txDataToUintList(data),
                          );
                        } catch (e) {
                          signedData =
                              await credentials.signPersonalMessage(
                            txDataToUintList(data),
                          );
                          signedDataHex =
                              bytesToHex(signedData, include0x: true);
                        }
                      }
                      await _controller.evaluateJavascript(
                        source:
                            'AlphaWallet.executeCallback($id, null, "$signedDataHex");',
                      );
                    } catch (e) {
                      final error = e.toString().replaceAll('"', '\'');

                      await _controller.evaluateJavascript(
                        source:
                            'AlphaWallet.executeCallback($id, "$error",null);',
                      );
                    } finally {
                      Get.back();
                    }
                  },
                  onReject: () {
                    _controller.evaluateJavascript(
                      source:
                          'AlphaWallet.executeCallback($id, "user rejected signature",null);',
                    );
                    Get.back();
                  },
                );
              },
            );
          },
          initialUserScripts: UnmodifiableListView([
            UserScript(
              source: widget.provider + initJs,
              injectionTime: UserScriptInjectionTime.AT_DOCUMENT_START,
            )
          ]),)

@Imdavyking
Copy link
Author

multi_webview_tab_manager

@Imdavyking
Copy link
Author

discovery...i found out this only happens when the tab is opened with javascript.

@pichillilorenzo
Copy link
Owner

I tested a simple User Script and it works with both JavaScript window.open() and target _blank links:

initialUserScripts: UnmodifiableListView([
  UserScript(
      source:
          "window.addEventListener('load', function(event) { console.log('window load'); });",
      injectionTime: UserScriptInjectionTime.AT_DOCUMENT_START)
]),
onConsoleMessage: (controller, consoleMessage) {
  print(consoleMessage);
},

I get every time the console message as expected, on both Android and iOS.

There must be something in your Dart code or Js user script code that doesn't work.

These flutter_inappwebview example projects are just examples that you can use as a starting point for your use case and customize by yourself.

@Imdavyking
Copy link
Author

Please try it for uniswap.io
uniswap uses reactJs

@Imdavyking
Copy link
Author

open uniswap
it worked
click on connect it directs to new page....it doesnt work

@Imdavyking
Copy link
Author

Screen Shot 2022-12-05 at 8 47 23 PM

so i think opening webview with target="_blank" is the problem

@pichillilorenzo
Copy link
Owner

Ok, I found that there is a problem injecting script at document start on Android for on WebViews opened from onCreateWindow using the windowId. It should be fixed with the next version 6 release!

@pichillilorenzo pichillilorenzo transferred this issue from pichillilorenzo/flutter_inappwebview_examples Dec 6, 2022
@pichillilorenzo pichillilorenzo changed the title UserScripts not executing on new tabs. Android plugin version 6 - UserScripts not executing on new tabs. Dec 6, 2022
Repository owner deleted a comment from github-actions bot Dec 6, 2022
@pichillilorenzo
Copy link
Owner

Released new version 6.0.0-beta.21 with the fix

@Imdavyking
Copy link
Author

Thank you so much,I appreciate

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants