html %3c% page,javascript - flutter: webview does not allow jumping to anchors in the same html page...

曾景龙
2023-12-01

I've bumped into an annoying flutter issue where HTML anchors don't work in the WebView.

Steps to Reproduce

I'm using webview to show localized html files. In each HTML file there are href links to redirect to corresponding language files. I'm using this little class below to show the HTML as a page.

with this little class

class LocalLoader {

Future loadLocal(String filename) async {

return await rootBundle.loadString('assets/$filename');

}

}

class HtmlPage extends StatelessWidget {

final Completer controller;

final String htmlFile;

HtmlPage({

@required this.htmlFile,

@required this.controller,

});

@override

Widget build(BuildContext context) {

return Container(

child: FutureBuilder(

future: LocalLoader().loadLocal(htmlFile),

builder: (context, snapshot) {

if (snapshot.hasData) {

return WebView(

debuggingEnabled: true,

initialUrl: Uri.dataFromString(snapshot.data,

mimeType: 'text/html',

// CAUTION

// - required for non-ascii chars

encoding: Encoding.getByName("UTF-8")

).toString(),

javascriptMode: JavascriptMode.unrestricted,

onWebViewCreated: (WebViewController webViewController) {

// CAUTION

// - avoid exception "Bad state: Future already completed"

if(!controller.isCompleted) {

controller.complete(webViewController);

}

},

);

} else if (snapshot.hasError) {

return Text("${snapshot.error}");

} else {

print('undefined behaviour');

}

return CircularProgressIndicator();

},

),);

}

}

class HelpPage extends HtmlPage {

HelpPage(ctrl) : super(htmlFile: 'help_en.html', controller: ctrl);

}

class AboutPage extends HtmlPage {

AboutPage(ctrl) : super(htmlFile: 'about_en.html', controller: ctrl);

}

And the relevant html code looks like this in each language files

English      Français

Repro 1

Open my app

Place help_en.html and help_fr.html in assets folder, and add the corresponding yaml section.

Load the initial page "help_en.html" and it shows correctly

Click the Français link on the page

Expected results:

We should see the help_fr.html upon clicking its redirection link.

Actual results:

We see a blank page

Repro 2

I suspected it may have been a relative path error. So I modified the HTML page so that the href looks like

English      Français

But the result is the same as in Repro 1.

Logs

E/InputMethodManager(24228): b/117267690: Failed to get fallback IMM with expected displayId=215 actual IMM#displayId=0 view=io.flutter.plugins.webviewflutter.InputAwareWebView{f259a5f VFEDHVC.. .F...... 0,0-2075,706}

E/InputMethodManager(24228): b/117267690: Failed to get fallback IMM with expected displayId=215 actual IMM#displayId=0 view=io.flutter.plugins.webviewflutter.InputAwareWebView{f259a5f VFEDHVC.. .F...... 0,0-2075,706}

No flutter analyze errors

$ flutter doctor -v

[✓] Flutter (Channel dev, 1.22.0-9.0.pre, on Mac OS X 10.15.6 19G2021, locale en-CN)

• Flutter version 1.22.0-9.0.pre at /Applications/flutter

• Framework revision 7a43175198 (10 days ago), 2020-08-28 23:18:04 -0400

• Engine revision 07e2520d5d

• Dart version 2.10.0 (build 2.10.0-73.0.dev)

• Pub download mirror https://pub.flutter-io.cn

• Flutter download mirror https://storage.flutter-io.cn

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.0)

• Android SDK at /Applications/Android/sdk

• Platform android-30, build-tools 30.0.0

• ANDROID_HOME = /Applications/Android/sdk

• ANDROID_SDK_ROOT = /Applications/Android/sdk

• Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java

• Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)

• All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 11.7)

• Xcode at /Applications/Xcode.app/Contents/Developer

• Xcode 11.7, Build version 11E801a

• CocoaPods version 1.9.1

[✓] Android Studio (version 4.0)

• Android Studio at /Applications/Android Studio.app/Contents

• Flutter plugin version 49.0.2

• Dart plugin version 193.7547

• Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)

[✓] VS Code (version 1.48.2)

• VS Code at /Applications/Visual Studio Code.app/Contents

• Flutter extension version 3.13.2

[✓] Connected device (2 available)

• ONEPLUS A6000 (mobile) • • android-arm64 • Android 10 (API 29)

• MyiPhone (mobile) • • ios • iOS 13.6.1

! Device emulator-5554 is offline.

• No issues found!

UPDATE

I dug further and thought this might be related to #27086, but it turned out to be even worse, see below:

Attempt

To work around this issue, I thought about merging help_en.html and help_fr.html into a single html file and turn the href's into anchors so that I can bypass the local assets reference issue by jumping within the same html file.

In theory, this would work.

Trouble

However, to my surprise, this didn't work either! I still see blank pages when trying to go to the anchors. The same anchors work fine in an Electron test app and in the browsers.

This time I got an error in Android Studio's console

E/InputMethodManager(28987): b/117267690: Failed to get fallback IMM with expected displayId=259 actual IMM#displayId=0 view=io.flutter.plugins.webviewflutter.InputAwareWebView{b193667 VFEDHVC.. .F...... 0,0-2075,706}

I/chromium(28987): [INFO:CONSOLE(0)] "Not allowed to navigate top frame to data URL: data:text/html;charset=utf-8,%3C!DOCTYPE%20html%3E%0A%3Chtml%20xmlns=%22http://www.w3.org/1999/xhtml%22%20lang=%22%22%20xml:lang=%22%22%3E%0A%3Chead%3E%0A%20%20%3Cmeta%20charset=%22utf-8%22%20/%3E%0A%20%20%3Cmeta%20name=%22generator%22%20content=%22pandoc%22%20/%3E%0A%20%20%3Cmeta%20name=%22viewport%22%20content=%22width=device-width,%20initial-scale=1.0,%20user-scalable=yes%22%20/%3E%0A%20%20%3Ctitle%3E%20%3C/title%3E%0A%20%20%3Cstyle%3E%0A%20%20%20%20code%7Bwhite-space:%20pre-wrap;%7D%0A%20%20%20%20span....E4%BA%8E%3C/h1%3E%0A%3Ch3%20id=%22section%22%3E%3C/h3%3E%0A%3Ch2%20id=%22%E5%8A%A8%E5%90%AC-version-1.0%22%3E%E5%8A%A8%E5%90%AC%20version%201.0%3C/h2%3E%0A%3Cp%3ECopyright%C2%A9%202020%20NExT%20%E5%B7%A5%E4%BD%9C%E5%AE%A4%E7%BE%A4%3C/p%3E%0A%3Cp%3E%E7%89%88%E6%9D%83%E6%89%80%E6%9C%89%3C/p%3E%0A%3Cp%3E%E9%9A%90%E7%A7%81%E6%94%BF%E7%AD%96%3Cspan%20class=%22math%20inline%22%3E%C2%A0%C2%A0%C2%A0%C2%A0%3C/span%3E%E7%94%A8%E6%88%B7%E6%9C%8D%E5%8A%A1%E5%8D%8F%E8%AE%AE%3C/p%3E%0A%3C/body%3E%0A%3C/html%3E%0A#helpen", source: data:text/html;charset=utf-8,%3C!DOCTYPE%20html%3E%0A%3Chtml%20xmlns=%22http://www.w3.org/1999/xhtml%22%20lang=%22%22%20xml:lang=%22%22%3E%0A%3Chead%3E%0A%20%20%3Cmeta%20charset=%22utf-8%22%20/%3E%0A%20%20%3Cmeta%20name=%22generator%22%20content=%22pandoc%22%20/%3E%0A%20%20%3Cmeta%20name=%22viewport%22%20content=%22width=device-width,%20initial-scale=1.0,%20user-scalable=yes%22%20/%3E%0A%20%20%3Ctitle%3E%20%3C/title%3E%0A%20%20%3Cstyle%3E%0A%20%20%20%20code%7Bwhite-space:%20pre-wrap;%7D%0A%20%20%20%20span.smallcaps%7Bfont-variant:%20small-caps;%7D%0A%20%20%20%20span.underline%7Btext-decoration:%20underline;%7D%0A%20%20%20%20div.column%7Bdisplay:%20inline-block;%20vertical-align:%20top;%20width:%2050%25;%7D%0A%20%20%20%20div.hanging-indent%7Bmargin-left:%201.5em;%20text-indent:%20-1.5em;%7D%0A%20%20%3C/style%3E%0A%20%20%3C!--%5Bif%20lt%20IE%209%5D%3E%0A%20%20%20%20%3Cscript%20src=%22//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js%22%3E%3C/script%3E%0A%20%20%3C!%5Bendif%5D--%3E%0A%20%20%3Cscript%20type=%22text/javascript%22%20src=%22help_lang.js%22%20type=%22module%22%3E%3C/script%3E%0A%20%20%3Cstyle%3E%0A%20%20/*%0A%20%20%20%20CAUTION:%20must%20use%20embedded%20style%20for%20standalone%20html%20with%20-s%0A%20%20*/%0A%20%20/***************%0A%20%20Global%0A%20%20***************/%0A%20%20/*%0A%20%20%20*%20I%20add%20this%20to%20html%20files%20generated%20with%20pandoc.%0A%20%20%20*/%0A%20%20html%20%7B%0A%20%20font-size:%20100%25;%0A%20%20overflow-y:%20scroll;%0A%20%20-webkit-text-size-adjust:%20100%25;%0A%20%20-ms-text-size-adjust:%20100%25;%0A%0A%20%20/*--scrollbarBG:%20%23CFD8DC;*/%0A%20%20--scrollbarBG:%20%232a2f39;%0A%20%20--thumbBG:%20%2390a4ae;%0A%20%20/*CAUTION:%20required%20for%20background%20parallax%20*/%0A%20%20height:%20100%25;%0A%20%20/*CAUTION%20end:%20required%20for%20background%20parallax%20*/%0A%20%20%7D%0A%20%20body%20%7B%0A%20%20color:%20%23e5e5e5;%0A%20%20font-family:%20Arial,%20Helvetica,%20sans-serif;%0A%20%20font-size:%2012px;%0A%20%20line-height:%201.7;%0A%20%20padding:%201em;%0A%20%20margin:%20auto;%0A%20%20max-width:%2042em;%0A%20%20/*CAUTION:%20required%20for%20background%20parallax%20*/%0A%20%20background:%20url('images/bg-logo.png')%20no-repeat%20top%20right,%20%232a2f39;%0A%20%20height:%20100%25;%0A%20%20background-attachment:%20fixed;%0A%20%20background-position:%20center;%0A%20%20background-repeat:%20no-repeat;%0A%20%20background-size:%20cover;%0A%20%20/*CAUTION%20end:%20required%20for%20background%20parallax*/%0A%20%20%7D%0A%20%20a%20%7B%0A%20%20color:%20%237c8694;%0A%20%20text-decoration:%20none;%0A%20%20%7D%0A%20%20a:visited%20%7B%0A%20%20color:%20%230072ae;%0A%20%20%7D%0A%20%20a:hover%20%7B%0A%20%20color:%20%2306e;%0A%20%20%7D%0A%20%20a:active%20%7B%0A%20%20color:%20%23faa700;%0A%20%20%7D%0A%20%20a:focus%20%7B%0A%20%20outline:%20thin%20dotted;%0A%20%20%7D%0A%20%20*::-moz-selection%20%7B%0A%20%20background:%20rgba(255,%20255,%200,%200.3);%

E/InputMethodManager(28987): b/117267690: Failed to get fallback IMM with expected displayId=259 actual IMM#displayId=0 view=io.flutter.plugins.webviewflutter.InputAwareWebView{b193667 VFEDHVC.. .F...... 0,0-2075,706}

Verdict

So to me this is beyond the fuss of running an http server to work around a very simple webpage doc. It is actually a much more serious bug to me.

 类似资料: