getFavicons method

  1. @override
Future<List<Favicon>> getFavicons()

Gets the list of all favicons for the current page.

Officially Supported Platforms/Implementations:

  • Android WebView
  • iOS WKWebView
  • macOS WKWebView
  • Web <iframe> but requires same origin
  • Windows WebView2
  • Linux WPE WebKit

Use the PlatformInAppWebViewController.isMethodSupported method to check if this method is supported at runtime.

Implementation

@override
Future<List<Favicon>> getFavicons() async {
  List<Favicon> favicons = [];

  var webviewUrl = await getUrl();

  if (webviewUrl == null) {
    return favicons;
  }

  String? manifestUrl;

  var html = await getHtml();
  if (html == null || html.isEmpty) {
    return favicons;
  }
  var assetPathBase;

  if (webviewUrl.isScheme("file")) {
    var assetPathSplit = webviewUrl.toString().split("/flutter_assets/");
    assetPathBase = assetPathSplit[0] + "/flutter_assets/";
  }

  InAppWebViewSettings? settings = await getSettings();
  if (settings != null && settings.javaScriptEnabled == true) {
    List<Map<dynamic, dynamic>> links =
        (await evaluateJavascript(
          source: """
(function() {
var linkNodes = document.head.getElementsByTagName("link");
var links = [];
for (var i = 0; i < linkNodes.length; i++) {
  var linkNode = linkNodes[i];
  if (linkNode.rel === 'manifest') {
    links.push(
      {
        rel: linkNode.rel,
        href: linkNode.href,
        sizes: null
      }
    );
  } else if (linkNode.rel != null && linkNode.rel.indexOf('icon') >= 0) {
    links.push(
      {
        rel: linkNode.rel,
        href: linkNode.href,
        sizes: linkNode.sizes != null && linkNode.sizes.value != "" ? linkNode.sizes.value : null
      }
    );
  }
}
return links;
})();
""",
        ))?.cast<Map<dynamic, dynamic>>() ??
        [];
    for (var link in links) {
      if (link["rel"] == "manifest") {
        manifestUrl = link["href"];
        if (!_isUrlAbsolute(manifestUrl!)) {
          if (manifestUrl.startsWith("/")) {
            manifestUrl = manifestUrl.substring(1);
          }
          manifestUrl =
              ((assetPathBase == null)
                  ? webviewUrl.scheme + "://" + webviewUrl.host + "/"
                  : assetPathBase) +
              manifestUrl;
        }
        continue;
      }
      favicons.addAll(
        _createFavicons(
          webviewUrl,
          assetPathBase,
          link["href"],
          link["rel"],
          link["sizes"],
          false,
        ),
      );
    }
  }

  // try to get /favicon.ico
  try {
    HttpClient client = HttpClient();
    var faviconUrl =
        webviewUrl.scheme + "://" + webviewUrl.host + "/favicon.ico";
    var faviconUri = WebUri(faviconUrl);
    var headRequest = await client.headUrl(faviconUri);
    var headResponse = await headRequest.close();
    if (headResponse.statusCode == 200) {
      favicons.add(Favicon(url: faviconUri, rel: "shortcut icon"));
    }
  } catch (e) {
    developer.log(
      "/favicon.ico file not found: " + e.toString(),
      name: runtimeType.toString(),
    );
  }

  // try to get the manifest file
  HttpClientRequest? manifestRequest;
  HttpClientResponse? manifestResponse;
  bool manifestFound = false;
  if (manifestUrl == null) {
    manifestUrl =
        webviewUrl.scheme + "://" + webviewUrl.host + "/manifest.json";
  }
  try {
    HttpClient client = HttpClient();
    manifestRequest = await client.getUrl(Uri.parse(manifestUrl));
    manifestResponse = await manifestRequest.close();
    manifestFound =
        manifestResponse.statusCode == 200 &&
        manifestResponse.headers.contentType?.mimeType == "application/json";
  } catch (e) {
    developer.log(
      "Manifest file not found: " + e.toString(),
      name: this.runtimeType.toString(),
    );
  }

  if (manifestFound) {
    try {
      Map<String, dynamic> manifest = json.decode(
        await manifestResponse!.transform(Utf8Decoder()).join(),
      );
      if (manifest.containsKey("icons")) {
        for (Map<String, dynamic> icon in manifest["icons"]) {
          favicons.addAll(
            _createFavicons(
              webviewUrl,
              assetPathBase,
              icon["src"],
              icon["rel"],
              icon["sizes"],
              true,
            ),
          );
        }
      }
    } catch (e) {
      developer.log(
        "Cannot get favicons from Manifest file. It might not have a valid format: " +
            e.toString(),
        error: e,
        name: runtimeType.toString(),
      );
    }
  }

  return favicons;
}