diff --git a/.all-contributorsrc b/.all-contributorsrc
index da88e3369..33a5556f6 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -493,7 +493,8 @@
"avatar_url": "https://avatars.githubusercontent.com/u/1270149?v=4",
"profile": "https://uekoetter.dev/",
"contributions": [
- "doc"
+ "doc",
+ "code"
]
},
{
@@ -747,6 +748,123 @@
"contributions": [
"code"
]
+ },
+ {
+ "login": "gmackall",
+ "name": "Gray Mackall",
+ "avatar_url": "https://avatars.githubusercontent.com/u/34871572?v=4",
+ "profile": "https://github.com/gmackall",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "p-mazhnik",
+ "name": "Pavel Mazhnik",
+ "avatar_url": "https://avatars.githubusercontent.com/u/25964451?v=4",
+ "profile": "https://github.com/p-mazhnik",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "nnnlog",
+ "name": "nlog (solrin)",
+ "avatar_url": "https://avatars.githubusercontent.com/u/20399222?v=4",
+ "profile": "https://nlog.dev",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "Murmurl912",
+ "name": "Murmurl912",
+ "avatar_url": "https://avatars.githubusercontent.com/u/36264246?v=4",
+ "profile": "https://github.com/Murmurl912",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "bschulz87",
+ "name": "Benjamin Schulz",
+ "avatar_url": "https://avatars.githubusercontent.com/u/30199362?v=4",
+ "profile": "https://github.com/bschulz87",
+ "contributions": [
+ "ideas"
+ ]
+ },
+ {
+ "login": "ShuheiSuzuki-07",
+ "name": "seal-app",
+ "avatar_url": "https://avatars.githubusercontent.com/u/118415919?v=4",
+ "profile": "https://github.com/ShuheiSuzuki-07",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "takuyaaaaaaahaaaaaa",
+ "name": "Takuya Tominaga",
+ "avatar_url": "https://avatars.githubusercontent.com/u/31458194?v=4",
+ "profile": "https://github.com/takuyaaaaaaahaaaaaa",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "yamaha252",
+ "name": "Sergey",
+ "avatar_url": "https://avatars.githubusercontent.com/u/4444068?v=4",
+ "profile": "https://github.com/yamaha252",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "lyb5834",
+ "name": "yuanbo li",
+ "avatar_url": "https://avatars.githubusercontent.com/u/16265810?v=4",
+ "profile": "https://github.com/lyb5834",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "Mecharyry",
+ "name": "Ryan Feline",
+ "avatar_url": "https://avatars.githubusercontent.com/u/3380092?v=4",
+ "profile": "https://github.com/Mecharyry",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "fuzzybinary",
+ "name": "Jeff Ward",
+ "avatar_url": "https://avatars.githubusercontent.com/u/249982?v=4",
+ "profile": "https://fuzzybinary.com",
+ "contributions": [
+ "test"
+ ]
+ },
+ {
+ "login": "yerkejs",
+ "name": "Yelzhan Yerkebulan",
+ "avatar_url": "https://avatars.githubusercontent.com/u/33483071?v=4",
+ "profile": "https://hero.io",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "GooRingX",
+ "name": "GooRingX",
+ "avatar_url": "https://avatars.githubusercontent.com/u/167741400?v=4",
+ "profile": "https://github.com/GooRingX",
+ "contributions": [
+ "code"
+ ]
}
],
"contributorsPerLine": 7,
diff --git a/.github/ISSUE_TEMPLATE/APP_SHOWCASE.md b/.github/ISSUE_TEMPLATE/APP_SHOWCASE.md
deleted file mode 100755
index 169f5961d..000000000
--- a/.github/ISSUE_TEMPLATE/APP_SHOWCASE.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-name: App Showcase
-about: Add your App on the Official Showcase Page
-
----
-
-Check the [Showcase](https://inappwebview.dev/showcase/) page to see an open list of Apps built with **Flutter** and **Flutter InAppWebView**.
-
-If you are using the **Flutter InAppWebView** plugin and would like to add your App there,
-follow the instruction on the [Submit App](https://inappwebview.dev/submit-app/) page!
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.md b/.github/ISSUE_TEMPLATE/BUG_REPORT.md
deleted file mode 100755
index 62863a346..000000000
--- a/.github/ISSUE_TEMPLATE/BUG_REPORT.md
+++ /dev/null
@@ -1,54 +0,0 @@
----
-name: Bug report
-about: Something is crashing or not working as intended
-labels: bug
----
-
-
-
-- [x] I have read the [Getting Started](https://inappwebview.dev/docs/intro/) section
-- [x] I have already searched for the same problem
-
-## Environment
-
-| Technology | Version |
-|-----------------------| ------------- |
-| Flutter version | |
-| Plugin version | |
-| Android version | |
-| iOS version | |
-| macOS version | |
-| Xcode version | |
-| Google Chrome version | |
-
-Device information:
-
-## Description
-
-**Expected behavior:**
-
-**Current behavior:**
-
-## Steps to reproduce
-
-
-
-1. This
-2. Than that
-3. Then
-
-## Images
-
-## Stacktrace/Logcat
diff --git a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md
deleted file mode 100755
index 97a1f1708..000000000
--- a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md
+++ /dev/null
@@ -1,22 +0,0 @@
----
-name: Feature request
-about: Suggest an idea for this project
-
----
-
-## Environment
-
-**Flutter version:**
-**Plugin version:**
-**Android version:**
-**iOS version:**
-**Xcode version:**
-**Device information:**
-
-## Description
-
-**What you'd like to happen:**
-
-**Alternatives you've considered:**
-
-**Images:**
diff --git a/.github/ISSUE_TEMPLATE/app_showcase.yml b/.github/ISSUE_TEMPLATE/app_showcase.yml
new file mode 100644
index 000000000..5cd6f9e3f
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/app_showcase.yml
@@ -0,0 +1,93 @@
+name: 📱 App Showcase
+description: Add your App on the Official Showcase plugin website page
+title: "Write your App name here"
+labels:
+ - showcase
+
+body:
+ - type: markdown
+ attributes:
+ value: |
+ **Request to submit your application to the official [Showcase](https://inappwebview.dev/showcase) plugin website page.**
+
+ **Please fill out the following information:**
+ - type: textarea
+ attributes:
+ label: App Icon
+ description: |
+ Add your App Icon here. You can drag and drop the image directly inside this textarea.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: What is the reason of using flutter_inappwebview in your app?
+ description: |
+ Explain why you are using the flutter_inappwebview plugin in your app.
+ placeholder: |
+ I'm using the flutter_inappwebview plugin in my app to create a custom Browser, to use WebRTC feature, to display local HTML content, etc.
+ validations:
+ required: true
+ - type: checkboxes
+ attributes:
+ label: Platforms
+ description: |
+ Your App is available on which platforms?
+ options:
+ - label: Mobile
+ - label: Desktop
+ - label: Web
+ - type: input
+ attributes:
+ label: Short Description
+ description: |
+ A short description of your app. Max 250 characters.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Long Description
+ description: |
+ A long description of your app.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: App Screenshots
+ description: |
+ Add some screenshots of your app. You can drag and drop images directly inside this textarea. Max 8 images.
+ validations:
+ required: true
+ - type: input
+ attributes:
+ label: App Website URL
+ description: |
+ Your App's official website URL, if available.
+ validations:
+ required: false
+ - type: input
+ attributes:
+ label: App Source Code Repository URL
+ description: |
+ Your App's source code repository URL, if available.
+ validations:
+ required: false
+ - type: input
+ attributes:
+ label: Google Play Store URL
+ description: |
+ Your App's Google Play Store URL, if available.
+ validations:
+ required: false
+ - type: input
+ attributes:
+ label: Apple App Store URL
+ description: |
+ Your App's Apple App Store URL, if available.
+ validations:
+ required: false
+ - type: textarea
+ attributes:
+ label: Additional information
+ description: Anything else you'd like to include?
+ validations:
+ required: false
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 000000000..112af4088
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -0,0 +1,107 @@
+name: 🐛 Bug
+description: Something is crashing or not working as intended
+title: "Write the title here"
+labels:
+ - bug
+
+body:
+ - type: markdown
+ attributes:
+ value: |
+ **Before you submit this issue, please make sure you have read the the [Getting Started](https://inappwebview.dev/docs/intro/) page.**
+
+ **Please fill out the following information:**
+ - type: checkboxes
+ attributes:
+ label: Is there an existing issue for this?
+ description: |
+ PLEASE! Make sure to check if this issue is a duplicate.
+
+ Search for it using the GitHub issue search box (check the closed issues too) or on the official [inappwebview.dev](https://inappwebview.dev/) website, or using Google, StackOverflow, etc. before posting a new one.
+
+ You may already find an answer to your problem!
+ options:
+ - label: I have searched the existing issues
+ required: true
+ - type: textarea
+ attributes:
+ label: Current Behavior
+ description: Write what you are experiencing currently.
+ placeholder: |
+ The plugin isn't working as expected. It crashes when I do this...
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Expected Behavior
+ description: Write what you expected to happen.
+ placeholder: |
+ The plugin should do this when I do that...
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Steps with code example to reproduce
+ description: Steps with code example to reproduce the issue. A not well written description might lead to the delay in fixing the issue.
+ value: |
+
+ Steps with code example to reproduce
+
+ ```dart
+ // Paste your code here
+ ```
+
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Stacktrace/Logs
+ description: |
+ If you have any stacktrace or logs, paste them here. Make sure to remove any sensitive information.
+ value: |
+
+ Stacktrace/Logs
+
+ ```
+
+ ```
+
+ validations:
+ required: true
+ - type: input
+ attributes:
+ label: Flutter version
+ description: The Flutter version in which you used the plugin to face the issue.
+ placeholder: v3.22.0, v3.24.3, etc.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Operating System, Device-specific and/or Tool
+ description: |
+ The Operating System, Device-specific and/or Tool in which you used the plugin to face the issue.
+ For example: All platforms, Android, iOS, XCode, macOS, Windows, Web, Chrome, etc.
+ Make sure to include the version too.
+ placeholder: Android 34+, iOS 17.0+, macOS, Windows, etc.
+ validations:
+ required: true
+ - type: input
+ attributes:
+ label: Plugin version
+ description: In which version of flutter_inappwebview did you encounter this bug?
+ placeholder: v6.1.0, v6.0.0, etc.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Additional information
+ description: Anything else you'd like to include? Like screenshots or a video recording of the issue.
+ validations:
+ required: false
+ - type: checkboxes
+ attributes:
+ label: Self grab
+ description: If you are a developer and want to work on this issue yourself, you can check this box and wait for maintainer response. We welcome contributions!
+ options:
+ - label: I'm ready to work on this issue!
+ required: false
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 000000000..5b7de1e17
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,5 @@
+blank_issues_enabled: false
+contact_links:
+ - name: Ask a question
+ url: https://github.com/pichillilorenzo/flutter_inappwebview/discussions/new?category=q-a
+ about: The place for questions and support
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
new file mode 100644
index 000000000..914aa71ad
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -0,0 +1,54 @@
+name: ✨ Feature Request
+description: Suggest an idea for this project
+title: "Write the title here"
+labels:
+ - enhancement
+
+body:
+ - type: checkboxes
+ attributes:
+ label: Is there an existing feature request for this?
+ description: Make sure to check if this feature request is a duplicate.
+ options:
+ - label: I have searched the existing feature request
+ required: true
+ - type: input
+ attributes:
+ label: Operating System
+ description: |
+ The Operating System in which you want to have this feature.
+ For example: All platforms if possible, Android, iOS, macOS, Windows, Web, Chrome, etc.
+ placeholder: All platforms if possible, Android, iOS, macOS, Windows, etc.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Pain
+ description: Explain your feature request.
+ placeholder: I'd like to have that / I don't like that I've to do this
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Suggested solution
+ description: Tell about a solution you can think of
+ placeholder: You could add that / change this / use that
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Useful resources
+ description: Provide some useful resource which could help implement your suggestion.
+ - type: textarea
+ attributes:
+ label: Additional information
+ description: Anything else you'd like to include? Like screenshots or a video recording of the issue.
+ validations:
+ required: false
+ - type: checkboxes
+ attributes:
+ label: Self grab
+ description: If you are a developer and want to work on this feature request yourself, you can check this box and wait for maintainer response. We welcome contributions!
+ options:
+ - label: I'm ready to work on this issue!
+ required: false
\ No newline at end of file
diff --git a/.github/autolabeler.yml b/.github/autolabeler.yml
index bcd2f4b82..b591d96a3 100644
--- a/.github/autolabeler.yml
+++ b/.github/autolabeler.yml
@@ -1,8 +1,13 @@
# Configuration for probot-auto-labeler - https://github.com/probot/autolabeler
# label: file | path
-android: ["/android", "*.kt", "*.java", "*gradle*", "AndroidManifest.xml"]
-iOS: ["/ios", "*.swift", "*.h", "*.m", "*.xcodeproj", "*.xcworkspace", "*.plist", "*.storyboard", "*.xcconfig", Podfile*"]
-flutter/dart: ["/lib", "*.dart"]
+android: ["/flutter_inappwebview_android", "*.dart", "*.kt", "*.java", "*gradle*", "AndroidManifest.xml"]
+iOS: ["/flutter_inappwebview_ios", "*.dart", "*.swift", "*.h", "*.m", "*.plist", "*.storyboard", "*.xcconfig", Podfile*"]
+macOS: ["/flutter_inappwebview_macos", "*.dart", "*.swift", "*.h", "*.m", "*.plist", "*.storyboard", "*.xcconfig", Podfile*"]
+windows: ["/flutter_inappwebview_windows", "*.dart", "*.cs", "*.c", "*.cpp", "*.h", "CMakeLists.txt"]
+linux: ["/flutter_inappwebview_linux", "*.dart", "*.c", "*.h", "*.cpp", "*.cmake", "*.makefile", "CMakeLists.txt"]
+web: ["/flutter_inappwebview_web", "*.dart", "*.html", "*.js", "*.css"]
+platform_interface: ["/flutter_inappwebview_platform_interface", "*.dart"]
+plugin: ["/flutter_inappwebview", "*.dart"]
documentation: ["*.md"]
legal: ["LICENSE*", "NOTICES*"]
diff --git a/.github/workflows/android-integration-test.yml b/.github/workflows/android-integration-test.yml
deleted file mode 100644
index 1dd606ffb..000000000
--- a/.github/workflows/android-integration-test.yml
+++ /dev/null
@@ -1,70 +0,0 @@
-# Name of your workflow.
-name: Android Integration Tests
-on:
- # Trigger the workflow on push or pull request,
- # but only for the main branch
- push:
- branches:
- - master
- pull_request:
- branches:
- - master
-# A workflow run is made up of one or more jobs.
-jobs:
- # id of job, a string that is unique to the "jobs" node above.
- android_integration_tests:
- # Creates a build matrix for your jobs. You can define different
- # variations of an environment to run each job in.
- strategy:
- # A set of different configurations of the virtual
- # environment.
- # matrix:
- # When set to true, GitHub cancels all in-progress jobs if any
- # matrix job fails.
- fail-fast: false
- # The type of machine to run the job on.
- runs-on: macOS-latest
- timeout-minutes: 60
- # Contains a sequence of tasks.
- steps:
- # The branch or tag ref that triggered the workflow will be
- # checked out.
- # https://github.com/actions/checkout
- - uses: actions/checkout@v2
- # Sets up cache
- - name: Cache multiple paths
- uses: actions/cache@v2
- with:
- path: |
- ~/.pub-cache
- ~/.npm
- key: ${{ runner.os }}-pub-and-npm-cache
- # Sets up a flutter environment.
- # https://github.com/marketplace/actions/flutter-action
- - name: "Install Flutter"
- uses: subosito/flutter-action@v1.4.0
- with:
- channel: 'dev' # 'stable' or 'dev' or 'beta'
- - name: "Change Flutter channel to master"
- run: |
- flutter channel master
- flutter upgrade
- - uses: actions/setup-node@v2
- with:
- node-version: '14'
- - name: "Install npm dependencies"
- run: |
- cd ./nodejs_server_test_auth_basic_and_ssl
- npm install
- cd ..
- - name: "Install flutter dependencies"
- run: |
- flutter pub get
- # Sets up android emulator
- - name: "Run Android Flutter Integration Test"
- uses: ReactiveCircus/android-emulator-runner@v2.14.3
- with:
- api-level: 29
- target: default
- avd-name: Flutter-Android
- script: ./scripts/test.sh $(ipconfig getifaddr en0)
\ No newline at end of file
diff --git a/.github/workflows/auto-comment.yml b/.github/workflows/auto-comment.yml
deleted file mode 100644
index 47f0a8953..000000000
--- a/.github/workflows/auto-comment.yml
+++ /dev/null
@@ -1,35 +0,0 @@
-name: Auto Comment
-on: [issues, pull_request]
-jobs:
- run:
- runs-on: ubuntu-latest
- steps:
- - uses: bubkoo/auto-comment@v1
- with:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- issuesOpened: >
- 👋 @{{ author }}
-
-
- **NOTE**: This comment is auto-generated.
-
-
- Are you sure you have already searched for the same problem?
-
-
- Some people open new issues but they didn't search for something similar or for the same issue.
- Please, search for it using the GitHub issue search box or on the official [inappwebview.dev](https://inappwebview.dev/) website,
- or, also, using Google, StackOverflow, etc. before posting a new one.
- You may already find an answer to your problem!
-
-
- If this is really a new issue, then thank you for raising it. I will investigate it and get back to you as soon as possible.
- Please, make sure you have given me as much context as possible!
- Also, if you didn't already, post a code example that can replicate this issue.
-
-
- In the meantime, you can already search for some possible solutions online!
- Because this plugin uses native WebView, you can search online for the same issue adding `android WebView [MY ERROR HERE]` or `ios WKWebView [MY ERROR HERE]` keywords.
-
-
- Following these steps can save you, me, and other people a lot of time, thanks!
\ No newline at end of file
diff --git a/.github/workflows/ios-integration-test.yml b/.github/workflows/ios-integration-test.yml
deleted file mode 100644
index cb790158b..000000000
--- a/.github/workflows/ios-integration-test.yml
+++ /dev/null
@@ -1,69 +0,0 @@
-# Name of your workflow.
-name: iOS Integration Tests
-on:
- # Trigger the workflow on push or pull request,
- # but only for the main branch
- push:
- branches:
- - master
- pull_request:
- branches:
- - master
-# A workflow run is made up of one or more jobs.
-jobs:
- # id of job, a string that is unique to the "jobs" node above.
- ios_integration_tests:
- # Creates a build matrix for your jobs. You can define different
- # variations of an environment to run each job in.
- strategy:
- # A set of different configurations of the virtual
- # environment.
- # matrix:
- # When set to true, GitHub cancels all in-progress jobs if any
- # matrix job fails.
- fail-fast: false
- # The type of machine to run the job on.
- runs-on: macOS-latest
- timeout-minutes: 60
- # Contains a sequence of tasks.
- steps:
- # A name for your step to display on GitHub.
- - name: "Start Simulator"
- run: |
- xcrun simctl list
- xcrun simctl create Flutter-iPhone com.apple.CoreSimulator.SimDeviceType.iPhone-12 com.apple.CoreSimulator.SimRuntime.iOS-14-3 | xargs xcrun simctl boot
- # The branch or tag ref that triggered the workflow will be
- # checked out.
- # https://github.com/actions/checkout
- - uses: actions/checkout@v2
- # Sets up cache
- - name: Cache multiple paths
- uses: actions/cache@v2
- with:
- path: |
- ~/.pub-cache
- ~/.npm
- key: ${{ runner.os }}-pub-and-npm-cache
- # Sets up a flutter environment.
- # https://github.com/marketplace/actions/flutter-action
- - name: "Install Flutter"
- uses: subosito/flutter-action@v1.4.0
- with:
- channel: 'dev' # 'stable' or 'dev' or 'beta'
- - name: "Change Flutter channel to master"
- run: |
- flutter channel master
- flutter upgrade
- - uses: actions/setup-node@v2
- with:
- node-version: '14'
- - name: "Install npm dependencies"
- run: |
- cd ./nodejs_server_test_auth_basic_and_ssl
- npm install
- cd ..
- - name: "Run iOS Flutter Integration Test"
- run: |
- flutter pub get
- flutter devices
- ./scripts/test.sh $(ipconfig getifaddr en0)
\ No newline at end of file
diff --git a/.github/workflows/lock.yaml b/.github/workflows/lock.yaml
new file mode 100644
index 000000000..e4f6f4126
--- /dev/null
+++ b/.github/workflows/lock.yaml
@@ -0,0 +1,29 @@
+# Configuration for Lock Threads - https://github.com/dessant/lock-threads
+
+name: 'Lock Threads'
+
+# By specifying the access of one of the scopes, all of those that are not
+# specified are set to 'none'.
+permissions:
+ issues: write
+
+on:
+ schedule:
+ - cron: '0 0 * * *' # Run every day at midnight
+
+jobs:
+ lock:
+ permissions:
+ issues: write
+ runs-on: ubuntu-latest
+ steps:
+ - uses: dessant/lock-threads@v5.0.1
+ with:
+ process-only: 'issues'
+ github-token: ${{ github.token }}
+ # Number of days of inactivity before a closed issue is locked.
+ issue-inactive-days: 14
+ issue-comment: >
+ This thread has been automatically locked since there has not been
+ any recent activity after it was closed. If you are still experiencing a
+ similar issue, please open a new bug and a minimal reproduction of the issue.
\ No newline at end of file
diff --git a/.github/workflows/no-response.yml b/.github/workflows/no-response.yaml
similarity index 78%
rename from .github/workflows/no-response.yml
rename to .github/workflows/no-response.yaml
index cad68e988..b353a9728 100644
--- a/.github/workflows/no-response.yml
+++ b/.github/workflows/no-response.yaml
@@ -1,3 +1,4 @@
+
name: No Response
# Both `issue_comment` and `scheduled` event types are required for this Action
@@ -6,8 +7,7 @@ on:
issue_comment:
types: [created]
schedule:
- # Schedule for five minutes after the hour, every hour
- - cron: '5 * * * *'
+ - cron: '0 0 * * *' # Run every day at midnight
# By specifying the access of one of the scopes, all of those that are not
# specified are set to 'none'.
@@ -17,7 +17,6 @@ permissions:
jobs:
noResponse:
runs-on: ubuntu-latest
- if: ${{ github.repository == 'flutter/flutter' }}
steps:
- uses: godofredoc/no-response@0ce2dc0e63e1c7d2b87752ceed091f6d32c9df09
with:
@@ -29,12 +28,11 @@ jobs:
bug for now.
If you find this problem please file a new issue with the same description,
- what happens, logs and the output of 'flutter doctor -v'. All system setups
- can be slightly different so it's always better to open new issues and reference
+ what happens and logs. It's always better to open new issues and reference
the related ones.
Thanks for your contribution.
# Number of days of inactivity before an issue is closed for lack of response.
daysUntilClose: 21
# Label requiring a response.
- responseRequiredLabel: "waiting for customer response"
\ No newline at end of file
+ responseRequiredLabel: "waiting for customer response"
diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml
new file mode 100644
index 000000000..13ffa0832
--- /dev/null
+++ b/.github/workflows/stale.yaml
@@ -0,0 +1,22 @@
+name: Close Stale Issues
+
+on:
+ schedule:
+ - cron: '0 0 * * *' # Run every day at midnight
+
+jobs:
+ close-issues:
+ runs-on: ubuntu-latest
+ permissions:
+ issues: write
+ steps:
+ - name: Close stale issues
+ uses: actions/stale@v9.0.0
+ with:
+ days-before-issue-stale: 365
+ days-before-issue-close: 0
+ stale-issue-label: "stale"
+ stale-issue-message: "This issue is stale and has been automatically closed because it has been open for more than 365 days with no activity. Please reopen a new issue if you still have it."
+ days-before-pr-stale: -1
+ days-before-pr-close: -1
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index cac255942..7710a3b56 100755
--- a/.gitignore
+++ b/.gitignore
@@ -23,7 +23,7 @@
# Flutter/Dart/Pub related
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
/pubspec.lock
-**/doc/api/
+doc/api/
.dart_tool/
.packages
build/
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 000000000..70f8824fc
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,75 @@
+{
+ "cmake.configureOnOpen": false,
+ "files.associations": {
+ "algorithm": "cpp",
+ "any": "cpp",
+ "array": "cpp",
+ "atomic": "cpp",
+ "bit": "cpp",
+ "cctype": "cpp",
+ "charconv": "cpp",
+ "chrono": "cpp",
+ "clocale": "cpp",
+ "cmath": "cpp",
+ "compare": "cpp",
+ "concepts": "cpp",
+ "coroutine": "cpp",
+ "cstddef": "cpp",
+ "cstdint": "cpp",
+ "cstdio": "cpp",
+ "cstdlib": "cpp",
+ "cstring": "cpp",
+ "ctime": "cpp",
+ "cwchar": "cpp",
+ "exception": "cpp",
+ "format": "cpp",
+ "forward_list": "cpp",
+ "functional": "cpp",
+ "initializer_list": "cpp",
+ "iomanip": "cpp",
+ "ios": "cpp",
+ "iosfwd": "cpp",
+ "iostream": "cpp",
+ "istream": "cpp",
+ "iterator": "cpp",
+ "limits": "cpp",
+ "list": "cpp",
+ "locale": "cpp",
+ "map": "cpp",
+ "memory": "cpp",
+ "new": "cpp",
+ "optional": "cpp",
+ "ostream": "cpp",
+ "ratio": "cpp",
+ "set": "cpp",
+ "sstream": "cpp",
+ "stdexcept": "cpp",
+ "stop_token": "cpp",
+ "streambuf": "cpp",
+ "string": "cpp",
+ "system_error": "cpp",
+ "thread": "cpp",
+ "tuple": "cpp",
+ "type_traits": "cpp",
+ "typeinfo": "cpp",
+ "unordered_map": "cpp",
+ "utility": "cpp",
+ "variant": "cpp",
+ "vector": "cpp",
+ "xfacet": "cpp",
+ "xhash": "cpp",
+ "xiosbase": "cpp",
+ "xlocale": "cpp",
+ "xlocbuf": "cpp",
+ "xlocinfo": "cpp",
+ "xlocmes": "cpp",
+ "xlocmon": "cpp",
+ "xlocnum": "cpp",
+ "xloctime": "cpp",
+ "xmemory": "cpp",
+ "xstring": "cpp",
+ "xtr1common": "cpp",
+ "xtree": "cpp",
+ "xutility": "cpp"
+ }
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index 1780a4557..6d63860ad 100755
--- a/README.md
+++ b/README.md
@@ -5,10 +5,10 @@

-[](#contributors-)
+[](#contributors-)
-[](https://pub.dartlang.org/packages/flutter_inappwebview)
+[](https://pub.dartlang.org/packages/flutter_inappwebview)
[](https://pub.dev/packages/flutter_inappwebview/score)
[](https://pub.dev/packages/flutter_inappwebview/score)
[](https://pub.dev/packages/flutter_inappwebview/score)
@@ -19,13 +19,18 @@
[](https://github.com/pichillilorenzo/flutter_inappwebview)
[](https://github.com/pichillilorenzo/flutter_inappwebview)
-A Flutter plugin that allows you to add an inline webview, to use an headless webview, and to open an in-app browser window.
+###### Supported Platforms
-
+[](https://pub.dartlang.org/packages/flutter_inappwebview_platform_interface)
+[](https://pub.dartlang.org/packages/flutter_inappwebview_android)
+[](https://pub.dartlang.org/packages/flutter_inappwebview_ios)
+[](https://pub.dartlang.org/packages/flutter_inappwebview_macos)
+[](https://pub.dartlang.org/packages/flutter_inappwebview_windows)
+[](https://pub.dartlang.org/packages/flutter_inappwebview_web)
-## New Version 6.x.x is OUT NOW!
+A Flutter plugin that allows you to add an inline webview, to use an headless webview, and to open an in-app browser window.
-Migrating from version `5.x.x` is easy! Follow the online [Migration guide](https://inappwebview.dev/docs/migration-guide).
+
## Articles/Resources
@@ -47,27 +52,23 @@ Send a submission request to the [Submit App](https://inappwebview.dev/submit-ap
## Requirements
-- Dart sdk: ">=2.17.0 <4.0.0"
-- Flutter: ">=3.0.0"
+- Dart sdk: "^3.5.0"
+- Flutter: ">=3.24.0"
- Android: `minSdkVersion >= 19`, `compileSdk >= 34`, [AGP](https://developer.android.com/build/releases/gradle-plugin) version `>= 7.3.0` (use [Android Studio - Android Gradle plugin Upgrade Assistant](https://developer.android.com/build/agp-upgrade-assistant) for help), support for `androidx` (see [AndroidX Migration](https://flutter.dev/docs/development/androidx-migration) to migrate an existing app)
-- iOS 9.0+: `--ios-language swift`, Xcode version `>= 14.3`
-- MacOS 10.11+: Xcode version `>= 14.3`
+- iOS 12.0+: `--ios-language swift`, Xcode version `>= 15.0`
+- MacOS 10.14+: Xcode version `>= 15.0`
+- Windows: [NuGet CLI](https://learn.microsoft.com/en-us/nuget/install-nuget-client-tools?tabs=windows#nugetexe-cli) available on your PATH environment variable
## Installation
Add `flutter_inappwebview` as a [dependency in your pubspec.yaml file](https://flutter.io/using-packages/).
-### Installation - Web support
-
-To make it work properly on the Web platform, you need to add the `web_support.js` file inside the `
` of your `web/index.html` file:
-
-```html
-
-
-
-
-
-```
+### Platform Installation Setup:
+- [Android](https://inappwebview.dev/docs/intro/#setup-android)
+- [iOS](https://inappwebview.dev/docs/intro/#setup-ios)
+- [macOS](https://inappwebview.dev/docs/intro/#setup-macos)
+- [Windows](https://inappwebview.dev/docs/intro/#setup-windows)
+- [Web](https://inappwebview.dev/docs/intro/#setup-web)
## Support
@@ -150,7 +151,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
 Rex Raphael 💻 |
 Jan Henrik Høiland 💻 |
 Iguchi Tomokatsu 💻 |
-  Jonas Uekötter 📖 |
+  Jonas Uekötter 📖 💻 |
 emakar 💻 |
 liasica 💻 |
@@ -187,6 +188,23 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
 lrorpilla 💻 |
 Michal Šrůtek 💻 |
 daisukeueta 💻 |
+  Gray Mackall 💻 |
+  Pavel Mazhnik 💻 |
+
+
+  nlog (solrin) 💻 |
+  Murmurl912 💻 |
+  Benjamin Schulz 🤔 |
+  seal-app 💻 |
+  Takuya Tominaga 💻 |
+  Sergey 💻 |
+  yuanbo li 💻 |
+
+
+  Ryan Feline 💻 |
+  Jeff Ward ⚠️ |
+  Yelzhan Yerkebulan 💻 |
+  GooRingX 💻 |
diff --git a/dev_packages/flutter_inappwebview_internal_annotations/CHANGELOG.md b/dev_packages/flutter_inappwebview_internal_annotations/CHANGELOG.md
index b7586c319..81ce60287 100755
--- a/dev_packages/flutter_inappwebview_internal_annotations/CHANGELOG.md
+++ b/dev_packages/flutter_inappwebview_internal_annotations/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.2.0
+
+- Updated `ExchangeableEnum` and `ExchangeableObjectProperty`.
+
## 1.1.1
- Added `ExchangeableObject.fromMapForceAllInline`.
diff --git a/dev_packages/flutter_inappwebview_internal_annotations/lib/src/exchangeable_enum.dart b/dev_packages/flutter_inappwebview_internal_annotations/lib/src/exchangeable_enum.dart
index b69902497..ea66483b4 100644
--- a/dev_packages/flutter_inappwebview_internal_annotations/lib/src/exchangeable_enum.dart
+++ b/dev_packages/flutter_inappwebview_internal_annotations/lib/src/exchangeable_enum.dart
@@ -4,6 +4,10 @@ class ExchangeableEnum {
final bool fromValueMethod;
final bool toNativeValueMethod;
final bool fromNativeValueMethod;
+ final bool nameMethod;
+ final bool toNameMethod;
+ final bool byNameMethod;
+ final bool asNameMapMethod;
final bool toStringMethod;
final bool hashCodeMethod;
final bool equalsOperator;
@@ -15,6 +19,10 @@ class ExchangeableEnum {
this.fromValueMethod = true,
this.toNativeValueMethod = true,
this.fromNativeValueMethod = true,
+ this.nameMethod = true,
+ this.toNameMethod = true,
+ this.byNameMethod = true,
+ this.asNameMapMethod = true,
this.toStringMethod = true,
this.hashCodeMethod = true,
this.equalsOperator = true,
diff --git a/dev_packages/flutter_inappwebview_internal_annotations/lib/src/exchangeable_object_property.dart b/dev_packages/flutter_inappwebview_internal_annotations/lib/src/exchangeable_object_property.dart
index 14fa2eae5..9ffd83955 100644
--- a/dev_packages/flutter_inappwebview_internal_annotations/lib/src/exchangeable_object_property.dart
+++ b/dev_packages/flutter_inappwebview_internal_annotations/lib/src/exchangeable_object_property.dart
@@ -1,9 +1,17 @@
class ExchangeableObjectProperty {
final Function? serializer;
final Function? deserializer;
+ final bool deprecatedUseNewFieldNameInConstructor;
+ final bool deprecatedUseNewFieldNameInFromMapMethod;
+ final bool leaveDeprecatedInFromMapMethod;
+ final bool leaveDeprecatedInToMapMethod;
const ExchangeableObjectProperty({
this.serializer,
- this.deserializer
+ this.deserializer,
+ this.deprecatedUseNewFieldNameInConstructor = true,
+ this.deprecatedUseNewFieldNameInFromMapMethod = true,
+ this.leaveDeprecatedInFromMapMethod = false,
+ this.leaveDeprecatedInToMapMethod = false,
});
}
diff --git a/dev_packages/flutter_inappwebview_internal_annotations/pubspec.yaml b/dev_packages/flutter_inappwebview_internal_annotations/pubspec.yaml
index 215aca267..64e918ec7 100755
--- a/dev_packages/flutter_inappwebview_internal_annotations/pubspec.yaml
+++ b/dev_packages/flutter_inappwebview_internal_annotations/pubspec.yaml
@@ -1,6 +1,6 @@
name: flutter_inappwebview_internal_annotations
description: Internal annotations used by the generator of flutter_inappwebview plugin
-version: 1.1.1
+version: 1.2.0
homepage: https://github.com/pichillilorenzo/flutter_inappwebview
environment:
diff --git a/dev_packages/generators/lib/src/exchangeable_enum_generator.dart b/dev_packages/generators/lib/src/exchangeable_enum_generator.dart
index c362e6812..2d602bba7 100644
--- a/dev_packages/generators/lib/src/exchangeable_enum_generator.dart
+++ b/dev_packages/generators/lib/src/exchangeable_enum_generator.dart
@@ -140,6 +140,7 @@ class ExchangeableEnumGenerator
[];
var hasWebSupport = false;
var webSupportValue = null;
+ var allPlatformsWithoutValue = true;
if (platforms.isNotEmpty) {
for (var platform in platforms) {
final targetPlatformName =
@@ -150,6 +151,9 @@ class ExchangeableEnumGenerator
? platformValueField.toIntValue() ??
"'${platformValueField.toStringValue()}'"
: null;
+ if (allPlatformsWithoutValue && platformValue != null) {
+ allPlatformsWithoutValue = false;
+ }
if (targetPlatformName == "web") {
hasWebSupport = true;
webSupportValue = platformValue;
@@ -170,8 +174,13 @@ class ExchangeableEnumGenerator
nativeValueBody += "return $defaultValue;";
nativeValueBody += "}";
- classBuffer.writeln(
- "static final $fieldName = $extClassName._internalMultiPlatform($constantValue, $nativeValueBody);");
+ if (!allPlatformsWithoutValue) {
+ classBuffer.writeln(
+ "static final $fieldName = $extClassName._internalMultiPlatform($constantValue, $nativeValueBody);");
+ } else {
+ classBuffer.writeln(
+ "static const $fieldName = $extClassName._internal($constantValue, ${defaultValue ?? constantValue});");
+ }
} else {
classBuffer.writeln(
"static const $fieldName = $extClassName._internal($constantValue, $constantValue);");
@@ -195,13 +204,13 @@ class ExchangeableEnumGenerator
}
if (annotation.read("fromValueMethod").boolValue && (!visitor.methods.containsKey("fromValue") ||
- Util.methodHasIgnore(visitor.methods['fromNativeValue']!))) {
+ Util.methodHasIgnore(visitor.methods['fromValue']!))) {
final hasBitwiseOrOperator =
annotation.read("bitwiseOrOperator").boolValue;
classBuffer.writeln("""
///Gets a possible [$extClassName] instance from [${enumValue.type}] value.
static $extClassName? fromValue(${enumValue.type}${!Util.typeIsNullable(enumValue.type) ? '?' : ''} value) {
- if (value != null) {
+ if (value != null) {
try {
return $extClassName.values
.firstWhere((element) => element.toValue() == value);
@@ -221,7 +230,7 @@ class ExchangeableEnumGenerator
classBuffer.writeln("""
///Gets a possible [$extClassName] instance from a native value.
static $extClassName? fromNativeValue(${enumNativeValue.type}${!Util.typeIsNullable(enumNativeValue.type) ? '?' : ''} value) {
- if (value != null) {
+ if (value != null) {
try {
return $extClassName.values
.firstWhere((element) => element.toNativeValue() == value);
@@ -234,6 +243,44 @@ class ExchangeableEnumGenerator
""");
}
+ if (annotation.read("nameMethod").boolValue && annotation.read("byNameMethod").boolValue &&
+ (!visitor.methods.containsKey("byName") || Util.methodHasIgnore(visitor.methods['byName']!))) {
+ classBuffer.writeln("""
+ /// Gets a possible [$extClassName] instance value with name [name].
+ ///
+ /// Goes through [$extClassName.values] looking for a value with
+ /// name [name], as reported by [$extClassName.name].
+ /// Returns the first value with the given name, otherwise `null`.
+ static $extClassName? byName(String? name) {
+ if (name != null) {
+ try {
+ return $extClassName.values
+ .firstWhere((element) => element.name() == name);
+ } catch (e) {
+ return null;
+ }
+ }
+ return null;
+ }
+ """);
+ }
+
+ if (annotation.read("nameMethod").boolValue && annotation.read("asNameMapMethod").boolValue &&
+ (!visitor.methods.containsKey("asNameMap") || Util.methodHasIgnore(visitor.methods['asNameMap']!))) {
+ classBuffer.writeln("""
+ /// Creates a map from the names of [$extClassName] values to the values.
+ ///
+ /// The collection that this method is called on is expected to have
+ /// values with distinct names, like the `values` list of an enum class.
+ /// Only one value for each name can occur in the created map,
+ /// so if two or more values have the same name (either being the
+ /// same value, or being values of different enum type), at most one of
+ /// them will be represented in the returned map.
+ static Map asNameMap() =>
+ {for (final value in $extClassName.values) value.name(): value};
+ """);
+ }
+
for (final entry in methodEntriesSorted) {
final methodElement = entry.value;
if (Util.methodHasIgnore(methodElement)) {
@@ -273,6 +320,28 @@ class ExchangeableEnumGenerator
""");
}
+ if (annotation.read("nameMethod").boolValue && (!visitor.methods.containsKey("name") ||
+ Util.methodHasIgnore(visitor.methods['name']!))) {
+ classBuffer.writeln('///Gets the name of the value.');
+ classBuffer.writeln('String name() {');
+ classBuffer.writeln('switch(_value) {');
+ for (final entry in fieldEntriesSorted) {
+ final fieldName = entry.key;
+ final fieldElement = entry.value;
+ if (!fieldElement.isPrivate && fieldElement.isStatic) {
+ final fieldValue = fieldElement.computeConstantValue()?.getField("_value");
+ dynamic constantValue = fieldValue?.toIntValue();
+ if (enumValue.type.isDartCoreString) {
+ constantValue = "'${fieldValue?.toStringValue()}'";
+ }
+ classBuffer.writeln("case $constantValue: return '$fieldName';");
+ }
+ }
+ classBuffer.writeln('}');
+ classBuffer.writeln('return _value.toString();');
+ classBuffer.writeln('}');
+ }
+
if (annotation.read("hashCodeMethod").boolValue && (!visitor.fields.containsKey("hashCode") ||
Util.methodHasIgnore(visitor.methods['hashCode']!))) {
classBuffer.writeln("""
@@ -306,19 +375,23 @@ class ExchangeableEnumGenerator
if (enumValue.type.isDartCoreString) {
classBuffer.writeln('return _value;');
} else {
- classBuffer.writeln('switch(_value) {');
- for (final entry in fieldEntriesSorted) {
- final fieldName = entry.key;
- final fieldElement = entry.value;
- if (!fieldElement.isPrivate && fieldElement.isStatic) {
- final fieldValue =
- fieldElement.computeConstantValue()?.getField("_value");
- final constantValue = fieldValue?.toIntValue();
- classBuffer.writeln("case $constantValue: return '$fieldName';");
+ if (annotation.read("nameMethod").boolValue) {
+ classBuffer.writeln('return name();');
+ } else {
+ classBuffer.writeln('switch(_value) {');
+ for (final entry in fieldEntriesSorted) {
+ final fieldName = entry.key;
+ final fieldElement = entry.value;
+ if (!fieldElement.isPrivate && fieldElement.isStatic) {
+ final fieldValue =
+ fieldElement.computeConstantValue()?.getField("_value");
+ final constantValue = fieldValue?.toIntValue();
+ classBuffer.writeln("case $constantValue: return '$fieldName';");
+ }
}
+ classBuffer.writeln('}');
+ classBuffer.writeln('return _value.toString();');
}
- classBuffer.writeln('}');
- classBuffer.writeln('return _value.toString();');
}
classBuffer.writeln('}');
}
diff --git a/dev_packages/generators/lib/src/exchangeable_object_generator.dart b/dev_packages/generators/lib/src/exchangeable_object_generator.dart
index 1b3d935c6..498c95aa9 100644
--- a/dev_packages/generators/lib/src/exchangeable_object_generator.dart
+++ b/dev_packages/generators/lib/src/exchangeable_object_generator.dart
@@ -1,9 +1,10 @@
-import 'package:build/src/builder/build_step.dart';
-import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
-import 'package:source_gen/source_gen.dart';
+import 'package:build/src/builder/build_step.dart';
+import 'package:collection/collection.dart';
import 'package:flutter_inappwebview_internal_annotations/flutter_inappwebview_internal_annotations.dart';
+import 'package:source_gen/source_gen.dart';
import 'model_visitor.dart';
import 'util.dart';
@@ -224,29 +225,43 @@ class ExchangeableObjectGenerator
if (!hasCustomConstructor && deprecatedFields.length > 0) {
classBuffer.writeln(' {');
for (final deprecatedField in deprecatedFields) {
- final deprecatedFieldName = deprecatedField.name;
+ final deprecatedUseNewFieldNameInConstructor = _coreCheckerObjectProperty
+ .firstAnnotationOf(deprecatedField)
+ ?.getField("deprecatedUseNewFieldNameInConstructor")
+ ?.toBoolValue() ?? true;
+ if (!deprecatedUseNewFieldNameInConstructor) {
+ continue;
+ }
+
final message = _coreCheckerDeprecated
.firstAnnotationOfExact(deprecatedField)!
.getField("message")!
- .toStringValue()!;
- final fieldName = message
+ .toStringValue()!.trim();
+ if (!message.startsWith("Use ") && !message.endsWith(" instead")) {
+ continue;
+ }
+
+ final newFieldName = message
.replaceFirst("Use ", "")
.replaceFirst(" instead", "")
.trim();
- final fieldElement = visitor.fields[fieldName];
- if (fieldElement != null) {
- final fieldTypeElement = fieldElement.type.element;
+
+ final newFieldElement = visitor.fields[newFieldName];
+ final shouldUseNewFieldName = newFieldElement != null;
+ if (shouldUseNewFieldName) {
+ final deprecatedFieldName = deprecatedField.name;
+ final fieldTypeElement = newFieldElement.type.element;
final deprecatedFieldTypeElement = deprecatedField.type.element;
- final isNullable = Util.typeIsNullable(fieldElement.type);
- var hasDefaultValue = (fieldElement is ParameterElement)
- ? (fieldElement as ParameterElement).hasDefaultValue
+ final isNullable = Util.typeIsNullable(newFieldElement.type);
+ var hasDefaultValue = (newFieldElement is ParameterElement)
+ ? (newFieldElement as ParameterElement).hasDefaultValue
: false;
if (!isNullable && hasDefaultValue) {
continue;
}
- classBuffer.write('$fieldName = $fieldName ?? ');
+ classBuffer.write('$newFieldName = $newFieldName ?? ');
if (fieldTypeElement != null && deprecatedFieldTypeElement != null) {
final deprecatedIsNullable =
Util.typeIsNullable(deprecatedField.type);
@@ -274,7 +289,7 @@ class ExchangeableObjectGenerator
} else if (deprecatedField.type
.getDisplayString(withNullability: false) ==
"Uri" &&
- fieldElement.type.getDisplayString(withNullability: false) ==
+ newFieldElement.type.getDisplayString(withNullability: false) ==
"WebUri") {
if (deprecatedIsNullable) {
classBuffer.write(
@@ -304,7 +319,8 @@ class ExchangeableObjectGenerator
final nullable = annotation.read("nullableFromMapFactory").boolValue;
classBuffer
.writeln('static $extClassName${nullable ? '?' : ''} fromMap(');
- classBuffer.writeln('Map${nullable ? '?' : ''} map');
+ classBuffer.writeln(
+ 'Map${nullable ? '?' : ''} map, {EnumMethod? enumMethod}');
classBuffer.writeln(') {');
if (nullable) {
classBuffer.writeln('if (map == null) { return null; }');
@@ -324,18 +340,59 @@ class ExchangeableObjectGenerator
!(fieldElement.type.isDartCoreFunction ||
fieldElement.type is FunctionType)) {
var value = "map['$fieldName']";
- final deprecationMessage = _coreCheckerDeprecated
- .firstAnnotationOfExact(fieldElement)
- ?.getField("message")
- ?.toStringValue();
- if (deprecationMessage != null) {
- final newFieldName = deprecationMessage
- .replaceFirst("Use ", "")
- .replaceFirst(" instead", "")
- .trim();
- value = "map['$newFieldName']";
+
+ if (fieldElement.hasDeprecated) {
+ final deprecatedUseNewFieldNameInFromMapMethod = _coreCheckerObjectProperty
+ .firstAnnotationOf(fieldElement)
+ ?.getField("deprecatedUseNewFieldNameInFromMapMethod")
+ ?.toBoolValue() ?? true;
+
+ final deprecationMessage = _coreCheckerDeprecated
+ .firstAnnotationOfExact(fieldElement)
+ ?.getField("message")
+ ?.toStringValue()?.trim();
+ if (deprecationMessage != null &&
+ deprecationMessage.startsWith("Use ") &&
+ deprecationMessage.endsWith(" instead") &&
+ deprecatedUseNewFieldNameInFromMapMethod) {
+ final newFieldName = deprecationMessage
+ .replaceFirst("Use ", "")
+ .replaceFirst(" instead", "")
+ .trim();
+ final newFieldElement = fieldElements
+ .firstWhereOrNull((element) => element.name == newFieldName);
+ final shouldUseNewFieldName = newFieldElement != null &&
+ (newFieldElement.type == fieldElement.type ||
+ (fieldElement.name.startsWith(RegExp(r'android|ios')) &&
+ fieldElement.name.toLowerCase().replaceFirst(
+ RegExp(r'android|ioswk|ios'), "") ==
+ newFieldName.toLowerCase()) ||
+ (newFieldElement.type.element != null &&
+ fieldElement.type.element != null &&
+ ((hasFromNativeValueMethod(
+ newFieldElement.type.element!) &&
+ hasFromNativeValueMethod(
+ fieldElement.type.element!) ||
+ (hasFromMapMethod(
+ newFieldElement.type.element!) &&
+ hasFromMapMethod(
+ fieldElement.type.element!))))));
+ if (shouldUseNewFieldName) {
+ value = "map['$newFieldName']";
+ }
+ } else {
+ final leaveDeprecatedInFromMapMethod = _coreCheckerObjectProperty
+ .firstAnnotationOf(fieldElement)
+ ?.getField("leaveDeprecatedInFromMapMethod")
+ ?.toBoolValue() ?? false;
+ if (!leaveDeprecatedInFromMapMethod) {
+ continue;
+ }
+ }
}
+ final mapValue = value;
+
final customDeserializer = _coreCheckerObjectProperty
.firstAnnotationOf(fieldElement)
?.getField("deserializer")
@@ -345,9 +402,10 @@ class ExchangeableObjectGenerator
customDeserializer.enclosingElement.name;
if (deserializerClassName != null) {
value =
- "$deserializerClassName.${customDeserializer.name}($value)";
+ "$deserializerClassName.${customDeserializer.name}($value, enumMethod: enumMethod)";
} else {
- value = "${customDeserializer.name}($value)";
+ value =
+ "${customDeserializer.name}($value, enumMethod: enumMethod)";
}
} else {
value = getFromMapValue(value, fieldElement.type);
@@ -355,13 +413,23 @@ class ExchangeableObjectGenerator
final constructorParameter = visitor.constructorParameters[fieldName];
final isRequiredParameter = constructorParameter != null &&
(constructorParameter.isRequiredNamed ||
- constructorParameter.isFinal || fieldElement.isFinal ||
+ constructorParameter.isFinal ||
+ fieldElement.isFinal ||
!Util.typeIsNullable(constructorParameter.type)) &&
!constructorParameter.hasDefaultValue;
- if (isRequiredParameter || fieldElement.isFinal || annotation.read("fromMapForceAllInline").boolValue) {
+ if (isRequiredParameter ||
+ fieldElement.isFinal ||
+ annotation.read("fromMapForceAllInline").boolValue) {
requiredFields.add('$fieldName: $value,');
} else {
+ final isFieldNullable = Util.typeIsNullable(fieldElement.type);
+ if (!isFieldNullable) {
+ nonRequiredFields.add("if ($mapValue != null) {");
+ }
nonRequiredFields.add("instance.$fieldName = $value;");
+ if (!isFieldNullable) {
+ nonRequiredFields.add("}");
+ }
}
}
}
@@ -401,13 +469,12 @@ class ExchangeableObjectGenerator
(!visitor.methods.containsKey("toMap") ||
Util.methodHasIgnore(visitor.methods['toMap']!))) {
classBuffer.writeln('///Converts instance to a map.');
- classBuffer.writeln('Map toMap() {');
+ classBuffer.writeln('Map toMap({EnumMethod? enumMethod}) {');
classBuffer.writeln('return {');
final fieldElements = [];
if (superClass != null) {
for (final fieldElement in superClass.element.fields) {
if (!fieldElement.isPrivate &&
- !fieldElement.hasDeprecated &&
!fieldElement.isStatic &&
!(fieldElement.type.isDartCoreFunction ||
fieldElement.type is FunctionType)) {
@@ -418,7 +485,6 @@ class ExchangeableObjectGenerator
for (final entry in fieldEntriesSorted) {
final fieldElement = entry.value;
if (!fieldElement.isPrivate &&
- !fieldElement.hasDeprecated &&
!fieldElement.isStatic &&
!(fieldElement.type.isDartCoreFunction ||
fieldElement.type is FunctionType)) {
@@ -427,10 +493,19 @@ class ExchangeableObjectGenerator
}
for (final fieldElement in fieldElements) {
if (!fieldElement.isPrivate &&
- !fieldElement.hasDeprecated &&
!fieldElement.isStatic &&
!(fieldElement.type.isDartCoreFunction ||
fieldElement.type is FunctionType)) {
+ if (fieldElement.hasDeprecated) {
+ final leaveDeprecatedInToMapMethod = _coreCheckerObjectProperty
+ .firstAnnotationOf(fieldElement)
+ ?.getField("leaveDeprecatedInToMapMethod")
+ ?.toBoolValue() ?? false;
+ if (!leaveDeprecatedInToMapMethod) {
+ continue;
+ }
+ }
+
final fieldName = fieldElement.name;
var mapValue = fieldName;
final customSerializer = _coreCheckerObjectProperty
@@ -441,9 +516,9 @@ class ExchangeableObjectGenerator
final serializerClassName = customSerializer.enclosingElement.name;
if (serializerClassName != null) {
mapValue =
- "$serializerClassName.${customSerializer.name}($mapValue)";
+ "$serializerClassName.${customSerializer.name}($mapValue, enumMethod: enumMethod)";
} else {
- mapValue = "${customSerializer.name}($mapValue)";
+ mapValue = "${customSerializer.name}($mapValue, enumMethod: enumMethod)";
}
} else {
mapValue = getToMapValue(fieldName, fieldElement.type);
@@ -459,7 +534,7 @@ class ExchangeableObjectGenerator
?.getField("toMapMergeWith")
?.toBoolValue();
if (toMapMergeWith == true) {
- classBuffer.writeln('...${methodElement.name}(),');
+ classBuffer.writeln('...${methodElement.name}(enumMethod: enumMethod),');
}
}
classBuffer.writeln('};');
@@ -526,6 +601,8 @@ class ExchangeableObjectGenerator
String getFromMapValue(String value, DartType elementType) {
final fieldTypeElement = elementType.element;
+ // remove class reference terminating with "_"
+ final classNameReference = fieldTypeElement?.name?.replaceFirst("_", "");
final isNullable = Util.typeIsNullable(elementType);
final displayString = elementType.getDisplayString(withNullability: false);
if (displayString == "Uri") {
@@ -556,6 +633,12 @@ class ExchangeableObjectGenerator
} else {
return "$value != null ? DateTime.fromMillisecondsSinceEpoch($value) : null";
}
+ } else if (displayString == "Uint8List") {
+ if (!isNullable) {
+ return "Uint8List.fromList($value.cast())";
+ } else {
+ return "$value != null ? Uint8List.fromList($value.cast()) : null";
+ }
} else if (elementType.isDartCoreList || elementType.isDartCoreSet) {
final genericTypes = Util.getGenericTypes(elementType);
final genericType = genericTypes.isNotEmpty ? genericTypes.first : null;
@@ -586,23 +669,36 @@ class ExchangeableObjectGenerator
return "$value${isNullable ? '?' : ''}.cast<${genericTypes.elementAt(0)}, ${genericTypes.elementAt(1)}>()";
} else if (fieldTypeElement != null && hasFromMapMethod(fieldTypeElement)) {
final hasNullableFromMap = hasNullableFromMapFactory(fieldTypeElement);
- // remove class reference terminating with "_"
- return fieldTypeElement.name!.replaceFirst("_", "") +
- ".fromMap($value?.cast())${!isNullable && hasNullableFromMap ? '!' : ''}";
+ return classNameReference! +
+ ".fromMap($value?.cast(), enumMethod: enumMethod)${!isNullable && hasNullableFromMap ? '!' : ''}";
} else {
- final hasFromValue =
- fieldTypeElement != null && hasFromValueMethod(fieldTypeElement);
- final hasFromNativeValue = fieldTypeElement != null &&
- hasFromNativeValueMethod(fieldTypeElement);
- if (fieldTypeElement != null && (hasFromValue || hasFromNativeValue)) {
- if (hasFromNativeValue) {
- // remove class reference terminating with "_"
- value = fieldTypeElement.name!.replaceFirst("_", "") +
- '.fromNativeValue($value)';
+ final hasFromValue = fieldTypeElement != null && hasFromValueMethod(fieldTypeElement);
+ final hasFromNativeValue = fieldTypeElement != null && hasFromNativeValueMethod(fieldTypeElement);
+ final hasByName = fieldTypeElement != null && hasByNameMethod(fieldTypeElement);
+ if (fieldTypeElement != null && (hasFromValue || hasFromNativeValue || hasByName)) {
+ if ([hasFromValue, hasFromNativeValue, hasByName].where((e) => e).length > 1) {
+ String? defaultEnumMethodValue = null;
+ if (hasFromNativeValue) {
+ defaultEnumMethodValue = "EnumMethod.nativeValue";
+ } else if (hasFromValue) {
+ defaultEnumMethodValue = "EnumMethod.value";
+ } else {
+ defaultEnumMethodValue = "EnumMethod.name";
+ }
+ var wrapper = "switch (enumMethod ?? $defaultEnumMethodValue) {";
+ wrapper += "EnumMethod.nativeValue => " + (hasFromNativeValue ? classNameReference! + '.fromNativeValue($value)' : "null") + ", ";
+ wrapper += "EnumMethod.value => " + (hasFromValue ? classNameReference! + '.fromValue($value)' : "null") + ", ";
+ wrapper += "EnumMethod.name => " + (hasByName ? classNameReference! + '.byName($value)' : "null");
+ wrapper += "}";
+ value = wrapper;
} else {
- // remove class reference terminating with "_"
- value = fieldTypeElement.name!.replaceFirst("_", "") +
- '.fromValue($value)';
+ if (hasFromNativeValue) {
+ value = classNameReference! + '.fromNativeValue($value)';
+ } else if (hasFromValue) {
+ value = classNameReference! + '.fromValue($value)';
+ } else {
+ value = classNameReference! + '.byName($value)';
+ }
}
if (!isNullable) {
value += '!';
@@ -647,17 +743,35 @@ class ExchangeableObjectGenerator
} else if (fieldTypeElement != null && hasToMapMethod(fieldTypeElement)) {
return fieldName +
(Util.typeIsNullable(elementType) ? '?' : '') +
- '.toMap()';
+ '.toMap(enumMethod: enumMethod)';
} else {
- final hasToValue =
- fieldTypeElement != null && hasToValueMethod(fieldTypeElement);
- final hasToNativeValue =
- fieldTypeElement != null && hasToNativeValueMethod(fieldTypeElement);
- if (fieldTypeElement != null && (hasToValue || hasToNativeValue)) {
- if (hasToNativeValue) {
- return fieldName + (isNullable ? '?' : '') + '.toNativeValue()';
+ final hasToValue = fieldTypeElement != null && hasToValueMethod(fieldTypeElement);
+ final hasToNativeValue = fieldTypeElement != null && hasToNativeValueMethod(fieldTypeElement);
+ final hasName = fieldTypeElement != null && hasNameMethod(fieldTypeElement);
+ if (fieldTypeElement != null && (hasToValue || hasToNativeValue || hasName)) {
+ if ([hasToValue, hasToNativeValue, hasName].where((e) => e).length > 1) {
+ String? defaultEnumMethodValue = null;
+ if (hasToNativeValue) {
+ defaultEnumMethodValue = "EnumMethod.nativeValue";
+ } else if (hasToValue) {
+ defaultEnumMethodValue = "EnumMethod.value";
+ } else {
+ defaultEnumMethodValue = "EnumMethod.name";
+ }
+ var wrapper = "switch (enumMethod ?? $defaultEnumMethodValue) {";
+ wrapper += "EnumMethod.nativeValue => " + (hasToNativeValue ? (fieldName + (isNullable ? '?' : '') + '.toNativeValue()') : "null") + ", ";
+ wrapper += "EnumMethod.value => " + (hasToValue ? (fieldName + (isNullable ? '?' : '') + '.toValue()') : "null") + ", ";
+ wrapper += "EnumMethod.name => " + (hasName ? (fieldName + (isNullable ? '?' : '') + '.name()') : "null");
+ wrapper += "}";
+ return wrapper;
} else {
- return fieldName + (isNullable ? '?' : '') + '.toValue()';
+ if (hasToNativeValue) {
+ return fieldName + (isNullable ? '?' : '') + '.toNativeValue()';
+ } else if (hasToValue) {
+ return fieldName + (isNullable ? '?' : '') + '.toValue()';
+ } else {
+ return fieldName + (isNullable ? '?' : '') + '.name()';
+ }
}
}
}
@@ -781,6 +895,28 @@ class ExchangeableObjectGenerator
return false;
}
+ bool hasByNameMethod(Element element) {
+ final hasAnnotation = _coreCheckerEnum.hasAnnotationOf(element);
+ final byNameMethod = _coreCheckerEnum
+ .firstAnnotationOfExact(element)
+ ?.getField('byNameMethod')
+ ?.toBoolValue() ??
+ false;
+ if (hasAnnotation && byNameMethod) {
+ return true;
+ }
+
+ final fieldVisitor = ModelVisitor();
+ element.visitChildren(fieldVisitor);
+ for (var entry in fieldVisitor.methods.entries) {
+ if (entry.key == "byName") {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
bool hasToValueMethod(Element element) {
final hasAnnotation = _coreCheckerEnum.hasAnnotationOf(element);
final hasToValueMethod = _coreCheckerEnum
@@ -824,4 +960,26 @@ class ExchangeableObjectGenerator
return false;
}
+
+ bool hasNameMethod(Element element) {
+ final hasAnnotation = _coreCheckerEnum.hasAnnotationOf(element);
+ final hasNameMethod = _coreCheckerEnum
+ .firstAnnotationOfExact(element)
+ ?.getField('nameMethod')
+ ?.toBoolValue() ??
+ false;
+ if (hasAnnotation && hasNameMethod) {
+ return true;
+ }
+
+ final fieldVisitor = ModelVisitor();
+ element.visitChildren(fieldVisitor);
+ for (var entry in fieldVisitor.methods.entries) {
+ if (entry.key == "name") {
+ return true;
+ }
+ }
+
+ return false;
+ }
}
diff --git a/dev_packages/generators/pubspec.yaml b/dev_packages/generators/pubspec.yaml
index be0fb8110..19bff4858 100755
--- a/dev_packages/generators/pubspec.yaml
+++ b/dev_packages/generators/pubspec.yaml
@@ -4,17 +4,19 @@ version: 1.0.0
publish_to: none
environment:
- sdk: ">=2.17.0 <4.0.0"
- flutter: ">=3.0.0"
+ sdk: ^3.5.0
+ flutter: ">=3.24.0"
dependencies:
flutter:
sdk: flutter
- build: ^2.4.0
- source_gen: ^1.3.1
- flutter_inappwebview_internal_annotations: ^1.1.1
+ build: ^2.4.1
+ source_gen: ^1.5.0
+ collection: any
+ flutter_inappwebview_internal_annotations: ^1.2.0
+ # path: ../flutter_inappwebview_internal_annotations
dev_dependencies:
- build_runner: ^2.4.0
- build_test: ^2.1.7
- test: ^1.24.2
\ No newline at end of file
+ build_runner: ^2.4.12
+ build_test: ^2.2.2
+ test: ^1.25.8
\ No newline at end of file
diff --git a/flutter_inappwebview/CHANGELOG.md b/flutter_inappwebview/CHANGELOG.md
index 6bfb046d8..b45f23ceb 100755
--- a/flutter_inappwebview/CHANGELOG.md
+++ b/flutter_inappwebview/CHANGELOG.md
@@ -1,3 +1,231 @@
+## 6.2.0-beta.3
+
+- Updated dependencies to the latest versions for all platform implementations:
+ - `flutter_inappwebview_platform_interface`: `^1.4.0-beta.2` -> `^1.4.0-beta.3`
+ - `flutter_inappwebview_android`: `^1.2.0-beta.2` -> `^1.2.0-beta.3`
+ - `flutter_inappwebview_ios`: `^1.2.0-beta.2` -> `^1.2.0-beta.3`
+ - `flutter_inappwebview_macos`: `^1.2.0-beta.2` -> `^1.2.0-beta.3`
+ - `flutter_inappwebview_web`: `^1.2.0-beta.2` -> `^1.2.0-beta.3`
+ - `flutter_inappwebview_windows`: `^0.7.0-beta.2` -> `^0.7.0-beta.3`
+- Fixed "When useShouldInterceptAjaxRequest is true, some ajax requests doesn't work" [#2197](https://github.com/pichillilorenzo/flutter_inappwebview/issues/2197)
+
+#### Platform Interface
+- Added `saveState`, `restoreState` methods to `PlatformInAppWebViewController` class
+- Added `useOnAjaxReadyStateChange`, `useOnAjaxProgress`, `useOnShowFileChooser` properties to `InAppWebViewSettings`
+- Added `onShowFileChooser` WebView events
+
+#### Android Platform
+- Implemented `saveState`, `restoreState` InAppWebViewController methods
+- Implemented `onShowFileChooser` WebView event
+- Merged "Android: implemented PlatformPrintJobController.onComplete" [#2216](https://github.com/pichillilorenzo/flutter_inappwebview/pull/2216) (thanks to [Doflatango](https://github.com/Doflatango))
+
+#### macOS and iOS Platforms
+- Implemented `saveState`, `restoreState` InAppWebViewController methods
+- Implemented `PlatformProxyController` class
+- Merged "Add proxy support for iOS" [#2362](https://github.com/pichillilorenzo/flutter_inappwebview/pull/2362) (thanks to [yerkejs](https://github.com/yerkejs))
+- Fixed "[iOS] Webview opened with windowId does not receive javascript handler callback." [#2393](https://github.com/pichillilorenzo/flutter_inappwebview/issues/2393)
+- Fixed internal javascript callback handlers when the WebView has windowId not null
+- macos: Fixed crash of unhandled `onPrintRequest` WebView event
+
+### Windows
+- Merged "windows: fix WebViewEnvironment dispose crash" [#2433](https://github.com/pichillilorenzo/flutter_inappwebview/pull/2433) (thanks to [GooRingX](https://github.com/GooRingX))
+
+## 6.2.0-beta.2
+
+- Updated dependencies to the latest versions for all platform implementations:
+ - `flutter_inappwebview_platform_interface`: `^1.4.0-beta.1` -> `^1.4.0-beta.2`
+ - `flutter_inappwebview_android`: `^1.2.0-beta.1` -> `^1.2.0-beta.2`
+ - `flutter_inappwebview_ios`: `^1.2.0-beta.1` -> `^1.2.0-beta.2`
+ - `flutter_inappwebview_macos`: `^1.2.0-beta.1` -> `^1.2.0-beta.2`
+ - `flutter_inappwebview_web`: `^1.2.0-beta.1` -> `^1.2.0-beta.2`
+ - `flutter_inappwebview_windows`: `^0.7.0-beta.1` -> `^0.7.0-beta.2`
+- Fixed specific URLAuthenticationChallenge type for `onReceivedHttpAuthRequest`, `onReceivedServerTrustAuthRequest`, `onReceivedClientCertRequest` events of HeadlessInAppWebView
+- Fixed missing return type for `InAppWebViewController.getJavaScriptBridgeName` static method
+
+#### Platform Interface
+- Updated `flutter_inappwebview_internal_annotations` dependency from `^1.1.1` to `^1.2.0`
+- Updated `fromMap` static method and `toMap` method implementations
+- Updated all WebView events with return type `Future` to type `FutureOr` in order to not force the usage of `async` keyword
+- Added `byName`, `name`, `asNameMap` custom enum classes methods
+- Added `statusBarEnabled`, `browserAcceleratorKeysEnabled`, `generalAutofillEnabled`, `passwordAutosaveEnabled`, `isPinchZoomEnabled`, `hiddenPdfToolbarItems`, `reputationCheckingRequired`, `nonClientRegionSupportEnabled`, `alpha`, `isUserInteractionEnabled` properties to `InAppWebViewSettings`
+- Added `isInterfaceSupported`, `getProcessInfos`, `getFailureReportFolderPath` methods to `PlatformWebViewEnvironment` class
+- Added `isInterfaceSupported`, `setInputMethodEnabled`, `hideInputMethod`, `showInputMethod` methods to `PlatformInAppWebViewController` class
+- Added `exclusiveUserDataFolderAccess`, `isCustomCrashReportingEnabled`, `enableTrackingPrevention`, `areBrowserExtensionsEnabled`, `channelSearchKind`, `releaseChannels`, `scrollbarStyle` properties to `WebViewEnvironmentSettings`
+- Added `onDownloadStarting` WebView event and deprecated `onDownloadStartRequest` event
+- Added `onNewBrowserVersionAvailable`, `onBrowserProcessExited`, `onProcessInfosChanged` events to `PlatformWebViewEnvironment` class
+- Fixed missing PrintJobOrientation android values
+
+#### Android Platform
+- Implemented `hideInputMethod`, `showInputMethod` InAppWebViewController methods
+- Implemented `isUserInteractionEnabled`, `alpha` properties of `InAppWebViewSettings`
+- Merged "Show / Hide / Disable / Enable soft Keyboard Input (Android & iOS)" [#2408](https://github.com/pichillilorenzo/flutter_inappwebview/pull/2408) (thanks to [Mecharyry](https://github.com/Mecharyry))
+- Fixed "[Android] PrintJobOrientation _TypeError (type 'Null' is not a subtype of type 'int')" [#2413](https://github.com/pichillilorenzo/flutter_inappwebview/issues/2413)
+- Fixed "Accessibility Android" [#1694](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1694)
+- Fixed "Automatic font scale according to accessibility option 'font size' of device does not work on Android" [#540](https://github.com/pichillilorenzo/flutter_inappwebview/issues/540)
+- Fixed "callHandler method is not injected into InAppBrowser" [#1973](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1973)
+
+#### iOS Platform
+- Implemented `setInputMethodEnabled`, `hideInputMethod` InAppWebViewController methods
+- Implemented `isUserInteractionEnabled`, `alpha` properties of `InAppWebViewSettings`
+- Merged "Show / Hide / Disable / Enable soft Keyboard Input (Android & iOS)" [#2408](https://github.com/pichillilorenzo/flutter_inappwebview/pull/2408) (thanks to [Mecharyry](https://github.com/Mecharyry))
+- Fixed "In iOS version 17.2, when moving the input focus in a WebView, an unknown area appears at the top of the screen." [#1947](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1947)
+
+#### macOS Platform
+- Implemented `alpha` property of `InAppWebViewSettings`
+
+#### Windows Platform
+- Updated Microsoft.Web.WebView2 SDK version from `1.0.2792.45` to `1.0.2849.39`
+- Implemented `disableDefaultErrorPage`, `statusBarEnabled`, `browserAcceleratorKeysEnabled`, `generalAutofillEnabled`, `passwordAutosaveEnabled`, `isPinchZoomEnabled`, `allowsBackForwardNavigationGestures`, `hiddenPdfToolbarItems`, `reputationCheckingRequired`, `nonClientRegionSupportEnabled` properties of `InAppWebViewSettings`
+- Implemented `isInterfaceSupported`, `getProcessInfos`, `getFailureReportFolderPath` WebViewEnvironment methods
+- Implemented `isInterfaceSupported`, `getZoomScale` InAppWebViewController method
+- Implemented `onDownloadStarting`, `onAcceleratorKeyPressed` WebView event
+- Implemented `exclusiveUserDataFolderAccess`, `isCustomCrashReportingEnabled`, `enableTrackingPrevention`, `areBrowserExtensionsEnabled`, `channelSearchKind`, `releaseChannels`, `scrollbarStyle` properties of `WebViewEnvironmentSettings`
+- Implemented `onNewBrowserVersionAvailable`, `onBrowserProcessExited`, `onProcessInfosChanged` WebViewEnvironment events
+- Send mouse leave region event to native view
+- Fixed wrong channel name when creating a `WebViewEnvironment` instance
+- Fixed "[Windows] Has an overlay on the desktop when the application is minimized" [#2402](https://github.com/pichillilorenzo/flutter_inappwebview/issues/2402)
+- Fixed "[Windows] missing implementation of onPermissionRequest event will cause crash when requested by the webpage" [#2404](https://github.com/pichillilorenzo/flutter_inappwebview/issues/2404)
+- Fixed "Windows: getCookies return empty list" [#2314](https://github.com/pichillilorenzo/flutter_inappwebview/issues/2314)
+
+## 6.2.0-beta.1
+
+- Updated dependencies to the latest versions for all platform implementations:
+ - `flutter_inappwebview_platform_interface`: `^1.3.0` -> `^1.4.0-beta.1`
+ - `flutter_inappwebview_android`: `^1.1.3` -> `^1.2.0-beta.1`
+ - `flutter_inappwebview_ios`: `^1.1.2` -> `^1.2.0-beta.1`
+ - `flutter_inappwebview_macos`: `^1.1.2` -> `^1.2.0-beta.1`
+ - `flutter_inappwebview_web`: `^1.1.2` -> `^1.2.0-beta.1`
+ - `flutter_inappwebview_windows`: `^0.6.0` -> `^0.7.0-beta.1`
+- Fixed specific URLAuthenticationChallenge type for `onReceivedHttpAuthRequest`, `onReceivedServerTrustAuthRequest`, `onReceivedClientCertRequest` events
+
+Implemented security features to better manage access to the native javascript bridge.
+
+#### Platform Interface
+- Updated static `fromMap` implementation for some classes
+- Updated `kJavaScriptHandlerForbiddenNames` list
+- Added `PlatformInAppLocalhostServer.onData` parameter to set a custom on data server callback
+- Added `javaScriptBridgeEnabled`, `javaScriptBridgeOriginAllowList`, `javaScriptBridgeForMainFrameOnly`, `pluginScriptsOriginAllowList`, `pluginScriptsForMainFrameOnly`, `javaScriptHandlersOriginAllowList`, `javaScriptHandlersForMainFrameOnly`, `scrollMultiplier` InAppWebViewSettings parameters
+- Added `setJavaScriptBridgeName`, `getJavaScriptBridgeName` static WebView controller methods
+- Added `requestFocus` WebView method
+- Added `onProcessFailed` WebView event
+- Added `regexToAllowSyncUrlLoading` Android-specific property to `InAppWebViewSettings`
+- Added `JavaScriptHandlerFunctionData` type
+- Deprecated `JavaScriptHandlerCallback` type in favor of `JavaScriptHandlerFunction` type
+- Deprecated `InAppWebViewSettings.forceDark` and `InAppWebViewSettings.forceDarkStrategy` Android-only properties in favor of `InAppWebViewSettings.algorithmicDarkeningAllowed`
+- Fixed X509Certificate PEM base64 decoding
+
+#### Android Platform
+- Added `InAppWebViewController.enableSlowWholeDocumentDraw` static method
+- Added `CookieManager.flush` method
+- Added support for `UserScript.forMainFrameOnly` parameter
+- Implemented `requestFocus` WebView method
+- Updated UserScript at document end implementation
+- Updated `InAppWebViewController.takeScreenshot` implementation to support screenshot out of visible viewport when `InAppWebViewController.enableSlowWholeDocumentDraw` is called
+- Fixed "After dispose a InAppWebViewKeepAlive using InAppWebViewController.disposeKeepAlive. NullPointerException is thrown when main activity enter destroyed state." [#2025](https://github.com/pichillilorenzo/flutter_inappwebview/issues/2025)
+- Fixed crash when trying to open InAppBrowser with R.menu.menu_main on release mode
+- Fixed "android.webkit.WebSettingsWrapper cannot be cast to com.android.webview.chromium.ContentSettingsAdapter" [#2397](https://github.com/pichillilorenzo/flutter_inappwebview/issues/2397)
+- Merged "Prevent blank InAppBrowser Activity from being restored" [#1984](https://github.com/pichillilorenzo/flutter_inappwebview/pull/1984) (thanks to [ShuheiSuzuki-07](https://github.com/ShuheiSuzuki-07))
+- Merged "Update Android Cookie Expiration date format to 24-hour format (HH)" [#2389](https://github.com/pichillilorenzo/flutter_inappwebview/pull/2389) (thanks to [takuyaaaaaaahaaaaaa](https://github.com/takuyaaaaaaahaaaaaa))
+- Merged "[Android] allow sync navigation requests using a regular expression" [#2008](https://github.com/pichillilorenzo/flutter_inappwebview/pull/2008) (thanks to [lyb5834](https://github.com/lyb5834))
+
+#### macOS and iOS Platforms
+- Implemented `requestFocus` WebView method
+- Updated ConsoleLogJS internal PluginScript to main-frame only as using it on non-main frames could cause issues such as [#1738](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1738)
+- Moved `WKUserContentController` initialization on `preWKWebViewConfiguration` to fix possible `undefined is not an object (evaluating 'window.webkit.messageHandlers')` javascript error
+- Added support for `UserScript.allowedOriginRules` parameter
+- Merged "change priority of DispatchQueue" [#2322](https://github.com/pichillilorenzo/flutter_inappwebview/pull/2322) (thanks to [nnnlog](https://github.com/nnnlog))
+- ios: Fixed `show`, `hide` methods and `hidden` setting for `InAppBrowser`
+- macOS: Implemented also `clearFocus` WebView method
+- macOS: Implemented workaround for "[macOS] Copy Shortcut does not work if TextField outside of WebView has focus" [#2380](https://github.com/pichillilorenzo/flutter_inappwebview/issues/2380)
+
+#### Windows Platform
+- Updated `scrollMultiplier` default value from 6 to 1
+- Added support for `UserScript.allowedOriginRules` and `UserScript.forMainFrameOnly` parameters
+- Implemented `onReceivedHttpAuthRequest`, `onReceivedClientCertRequest`, `onReceivedServerTrustAuthRequest`, `onRenderProcessGone`, `onRenderProcessUnresponsive`, `onWebContentProcessDidTerminate`, `onProcessFailed` WebView events
+- Implemented `clearSslPreferences` WebView method
+- Fixed `get_optional_fl_map_value` implementation in `utils/flutter.h`
+- Fixed "Error in transparentBackground handling in Windows" [#2391](https://github.com/pichillilorenzo/flutter_inappwebview/issues/2391)
+
+#### Web Platform
+- Merged "[web] support iframe role and aria-hidden attributes" [2293](https://github.com/pichillilorenzo/flutter_inappwebview/pull/2293) (thanks to [p-mazhnik](https://github.com/p-mazhnik))
+- Fixed 'Type 'int' is not a subtype of type 'JSValue' in type cast' when compiling/running using WASM
+
+## 6.1.5
+
+- Updated dependencies to the latest versions for all platform implementations:
+ - `flutter_inappwebview_windows`: `^0.5.0` -> `^0.6.0`
+
+#### Windows Platform
+- Updated code to support multiple flutter windows
+- Fixed `InAppWebViewController.callAsyncJavaScript` not working with JSON objects
+- Fixed `onLoadResourceWithCustomScheme` WebView event called every time
+
+## 6.1.4
+
+- Updated dependencies to the latest versions for all platform implementations:
+ - `flutter_inappwebview_platform_interface`: `^1.2.0` -> `^1.3.0`
+ - `flutter_inappwebview_android`: `^1.1.1` -> `^1.1.3`
+ - `flutter_inappwebview_ios`: `^1.1.1` -> `^1.1.2`
+ - `flutter_inappwebview_macos`: `^1.1.1` -> `^1.1.2`
+ - `flutter_inappwebview_web`: `^1.1.1` -> `^1.1.2`
+ - `flutter_inappwebview_windows`: `^0.4.0` -> `^0.5.0`
+
+#### Android Platform
+- Removed webview/plugin_scripts_js/ConsoleLogJS.java file, use native WebChromeClient.onConsoleMessage instead
+
+#### Windows Platform
+- Implemented `shouldInterceptRequest`, `onLoadResourceWithCustomScheme` WebView events
+
+## 6.1.3
+
+- Updated dependencies to the latest versions for all platform implementations:
+ - `flutter_inappwebview_platform_interface`: `^1.1.0` -> `^1.2.0`
+ - `flutter_inappwebview_android`: `^1.1.0+4` -> `^1.1.1`
+ - `flutter_inappwebview_ios`: `^1.1.0+3` -> `^1.1.1`
+ - `flutter_inappwebview_macos`: `^1.1.0+3` -> `^1.1.1`
+ - `flutter_inappwebview_web`: `^1.1.0+2` -> `^1.1.1`
+ - `flutter_inappwebview_windows`: `^0.3.0` -> `^0.4.0`
+
+#### Windows Platform
+ - Updated `shouldOverrideUrlLoading` implementation using the Chrome DevTools Protocol API Fetch.requestPaused event
+
+## 6.1.2
+
+- Updated minimum platform implementation versions
+
+#### Windows Platform
+
+- Implemented `pause`, `resume`, `getCertificate` methods for `InAppWebViewController`
+- Implemented `onPermissionRequest` WebView event
+- Fixed `InAppWebViewController.evaluateJavascript` not working with JSON objects
+- Fixed `InAppWebViewManager::METHOD_CHANNEL_NAME` c++ value
+- Fixed `InAppWebViewController.takeScreenshot` to behave consistently with the other platforms
+
+## 6.1.1
+
+- Updated README
+- Updated pubspec.yaml
+- Updated minimum platform implementation versions
+
+## 6.1.0+1
+
+- Updated README
+
+## 6.1.0
+
+- Added initial Windows support
+- Added `InAppWebView` widget MacOS support
+- Added privacy manifest for MacOS
+- Migrated web support to `package:web`.
+- Updated minimum supported SDK version to Flutter 3.24/Dart 3.5.
+- Updated androidx.webkit:webkit:1.8.0 to androidx.webkit:webkit:1.12.0
+- Updated androidx.browser:browser:1.6.0 to androidx.browser:browser:1.8.0
+- Fixed "[MACOS] launching InAppBrowser with 'hidden: true' calls onExit immediately" [#1939](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1939)
+- Fixed XCode 16 build
+- Removed unsupported WebViewFeature.SUPPRESS_ERROR_PAGE
+- Merged "Add privacy manifest for iOS" [#2029](https://github.com/pichillilorenzo/flutter_inappwebview/pull/2029) (thanks to [ueman](https://github.com/ueman))
+- Merged "Remove references to deprecated v1 Android embedding" [#2176](https://github.com/pichillilorenzo/flutter_inappwebview/pull/2176) (thanks to [gmackall](https://github.com/gmackall))
+
## 6.0.0
- Updated minimum platform interface and implementation versions
diff --git a/flutter_inappwebview/README.md b/flutter_inappwebview/README.md
index 1780a4557..6d63860ad 100755
--- a/flutter_inappwebview/README.md
+++ b/flutter_inappwebview/README.md
@@ -5,10 +5,10 @@

-[](#contributors-)
+[](#contributors-)
-[](https://pub.dartlang.org/packages/flutter_inappwebview)
+[](https://pub.dartlang.org/packages/flutter_inappwebview)
[](https://pub.dev/packages/flutter_inappwebview/score)
[](https://pub.dev/packages/flutter_inappwebview/score)
[](https://pub.dev/packages/flutter_inappwebview/score)
@@ -19,13 +19,18 @@
[](https://github.com/pichillilorenzo/flutter_inappwebview)
[](https://github.com/pichillilorenzo/flutter_inappwebview)
-A Flutter plugin that allows you to add an inline webview, to use an headless webview, and to open an in-app browser window.
+###### Supported Platforms
-
+[](https://pub.dartlang.org/packages/flutter_inappwebview_platform_interface)
+[](https://pub.dartlang.org/packages/flutter_inappwebview_android)
+[](https://pub.dartlang.org/packages/flutter_inappwebview_ios)
+[](https://pub.dartlang.org/packages/flutter_inappwebview_macos)
+[](https://pub.dartlang.org/packages/flutter_inappwebview_windows)
+[](https://pub.dartlang.org/packages/flutter_inappwebview_web)
-## New Version 6.x.x is OUT NOW!
+A Flutter plugin that allows you to add an inline webview, to use an headless webview, and to open an in-app browser window.
-Migrating from version `5.x.x` is easy! Follow the online [Migration guide](https://inappwebview.dev/docs/migration-guide).
+
## Articles/Resources
@@ -47,27 +52,23 @@ Send a submission request to the [Submit App](https://inappwebview.dev/submit-ap
## Requirements
-- Dart sdk: ">=2.17.0 <4.0.0"
-- Flutter: ">=3.0.0"
+- Dart sdk: "^3.5.0"
+- Flutter: ">=3.24.0"
- Android: `minSdkVersion >= 19`, `compileSdk >= 34`, [AGP](https://developer.android.com/build/releases/gradle-plugin) version `>= 7.3.0` (use [Android Studio - Android Gradle plugin Upgrade Assistant](https://developer.android.com/build/agp-upgrade-assistant) for help), support for `androidx` (see [AndroidX Migration](https://flutter.dev/docs/development/androidx-migration) to migrate an existing app)
-- iOS 9.0+: `--ios-language swift`, Xcode version `>= 14.3`
-- MacOS 10.11+: Xcode version `>= 14.3`
+- iOS 12.0+: `--ios-language swift`, Xcode version `>= 15.0`
+- MacOS 10.14+: Xcode version `>= 15.0`
+- Windows: [NuGet CLI](https://learn.microsoft.com/en-us/nuget/install-nuget-client-tools?tabs=windows#nugetexe-cli) available on your PATH environment variable
## Installation
Add `flutter_inappwebview` as a [dependency in your pubspec.yaml file](https://flutter.io/using-packages/).
-### Installation - Web support
-
-To make it work properly on the Web platform, you need to add the `web_support.js` file inside the `` of your `web/index.html` file:
-
-```html
-
-
-
-
-
-```
+### Platform Installation Setup:
+- [Android](https://inappwebview.dev/docs/intro/#setup-android)
+- [iOS](https://inappwebview.dev/docs/intro/#setup-ios)
+- [macOS](https://inappwebview.dev/docs/intro/#setup-macos)
+- [Windows](https://inappwebview.dev/docs/intro/#setup-windows)
+- [Web](https://inappwebview.dev/docs/intro/#setup-web)
## Support
@@ -150,7 +151,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
 Rex Raphael 💻 |
 Jan Henrik Høiland 💻 |
 Iguchi Tomokatsu 💻 |
-  Jonas Uekötter 📖 |
+  Jonas Uekötter 📖 💻 |
 emakar 💻 |
 liasica 💻 |
@@ -187,6 +188,23 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
 lrorpilla 💻 |
 Michal Šrůtek 💻 |
 daisukeueta 💻 |
+  Gray Mackall 💻 |
+  Pavel Mazhnik 💻 |
+
+
+  nlog (solrin) 💻 |
+  Murmurl912 💻 |
+  Benjamin Schulz 🤔 |
+  seal-app 💻 |
+  Takuya Tominaga 💻 |
+  Sergey 💻 |
+  yuanbo li 💻 |
+
+
+  Ryan Feline 💻 |
+  Jeff Ward ⚠️ |
+  Yelzhan Yerkebulan 💻 |
+  GooRingX 💻 |
diff --git a/flutter_inappwebview/example/.metadata b/flutter_inappwebview/example/.metadata
index 8f5507649..ba5723a22 100755
--- a/flutter_inappwebview/example/.metadata
+++ b/flutter_inappwebview/example/.metadata
@@ -4,5 +4,27 @@
# This file should be version controlled and should not be manually edited.
version:
- revision: d927c9331005f81157fa39dff7b5dab415ad330b
- channel: master
+ revision: "78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9"
+ channel: "stable"
+
+project_type: app
+
+# Tracks metadata for the flutter migrate command
+migration:
+ platforms:
+ - platform: root
+ create_revision: 78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9
+ base_revision: 78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9
+ - platform: windows
+ create_revision: 78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9
+ base_revision: 78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9
+
+ # User provided section
+
+ # List of Local paths (relative to this file) that should be
+ # ignored by the migrate tool.
+ #
+ # Files that are not part of the templates will be ignored by default.
+ unmanaged_files:
+ - 'lib/main.dart'
+ - 'ios/Runner.xcodeproj/project.pbxproj'
diff --git a/flutter_inappwebview/example/android/app/build.gradle b/flutter_inappwebview/example/android/app/build.gradle
index 1a5f9e50e..a50a94003 100755
--- a/flutter_inappwebview/example/android/app/build.gradle
+++ b/flutter_inappwebview/example/android/app/build.gradle
@@ -1,3 +1,9 @@
+plugins {
+ id "com.android.application"
+ id "kotlin-android"
+ id "dev.flutter.flutter-gradle-plugin"
+}
+
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
@@ -6,11 +12,6 @@ if (localPropertiesFile.exists()) {
}
}
-def flutterRoot = localProperties.getProperty('flutter.sdk')
-if (flutterRoot == null) {
- throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
-}
-
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
@@ -21,9 +22,6 @@ if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
-apply plugin: 'com.android.application'
-apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
-
android {
namespace 'com.pichillilorenzo.flutterwebviewexample'
@@ -32,13 +30,12 @@ android {
targetCompatibility 1.8
}
- compileSdkVersion 34
-
+ compileSdk 34
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.pichillilorenzo.flutter_inappwebviewexample"
- minSdkVersion 19
+ minSdkVersion flutter.minSdkVersion
targetSdkVersion 34
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
@@ -48,6 +45,10 @@ android {
buildTypes {
release {
+ // only for com.pichillilorenzo.flutter_inappwebview_android.R.menu.menu_main
+ minifyEnabled false
+ shrinkResources false
+
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
@@ -64,9 +65,9 @@ flutter {
}
dependencies {
- testImplementation 'junit:junit:4.13'
- androidTestImplementation 'androidx.test:runner:1.2.0'
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
- implementation 'com.google.android.material:material:1.6.1'
+ testImplementation 'junit:junit:4.13.2'
+ androidTestImplementation 'androidx.test:runner:1.6.2'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
+ implementation 'com.google.android.material:material:1.12.0'
implementation 'com.android.support:multidex:1.0.3'
}
diff --git a/flutter_inappwebview/example/android/app/src/main/AndroidManifest.xml b/flutter_inappwebview/example/android/app/src/main/AndroidManifest.xml
index cc96cd822..3581175ee 100755
--- a/flutter_inappwebview/example/android/app/src/main/AndroidManifest.xml
+++ b/flutter_inappwebview/example/android/app/src/main/AndroidManifest.xml
@@ -20,11 +20,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
plugins.load(reader) }
+ repositories {
+ google()
+ mavenCentral()
+ gradlePluginPortal()
+ }
}
-plugins.each { name, path ->
- def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
- include ":$name"
- project(":$name").projectDir = pluginDirectory
+plugins {
+ id "dev.flutter.flutter-plugin-loader" version "1.0.0"
+ id "com.android.application" version '8.6.1' apply false
+ id "org.jetbrains.kotlin.android" version "1.7.10" apply false
}
+
+include ":app"
\ No newline at end of file
diff --git a/flutter_inappwebview/example/integration_test/chrome_safari_browser/open_and_close.dart b/flutter_inappwebview/example/integration_test/chrome_safari_browser/open_and_close.dart
index 4615f4573..78eb9c4dc 100644
--- a/flutter_inappwebview/example/integration_test/chrome_safari_browser/open_and_close.dart
+++ b/flutter_inappwebview/example/integration_test/chrome_safari_browser/open_and_close.dart
@@ -40,7 +40,7 @@ void openAndClose() {
activityButton: ActivityButton(
templateImage: UIImage(systemName: "sun.max"),
extensionIdentifier:
- "com.pichillilorenzo.flutterinappwebview-ios-example.test")));
+ "com.pichillilorenzo.flutterinappwebview-ios-example3.test")));
await chromeSafariBrowser.opened.future;
expect(chromeSafariBrowser.isOpened(), true);
expect(() async {
diff --git a/flutter_inappwebview/example/integration_test/headless_in_app_webview/convert_to_inappwebview.dart b/flutter_inappwebview/example/integration_test/headless_in_app_webview/convert_to_inappwebview.dart
index af88f38f4..17c853d0d 100644
--- a/flutter_inappwebview/example/integration_test/headless_in_app_webview/convert_to_inappwebview.dart
+++ b/flutter_inappwebview/example/integration_test/headless_in_app_webview/convert_to_inappwebview.dart
@@ -26,6 +26,7 @@ void convertToInAppWebView() {
expect(headlessWebView.isRunning(), true);
final InAppWebViewController controller = await controllerCompleter.future;
+ await tester.pump();
await pageLoaded.future;
final String? url = (await controller.getUrl())?.toString();
@@ -55,6 +56,7 @@ void convertToInAppWebView() {
);
final InAppWebViewController widgetController =
await widgetControllerCompleter.future;
+ await tester.pump();
expect(headlessWebView.isRunning(), false);
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/get_content_height.dart b/flutter_inappwebview/example/integration_test/in_app_webview/get_content_height.dart
index 1e1635fc9..570e8eba8 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/get_content_height.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/get_content_height.dart
@@ -33,9 +33,8 @@ void getContentHeight() {
);
final InAppWebViewController controller = await controllerCompleter.future;
- await pageLoaded.future;
-
await tester.pump();
+ await pageLoaded.future;
final contentHeight = await controller.getContentHeight();
expect(contentHeight, isNonZero);
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/get_favicons.dart b/flutter_inappwebview/example/integration_test/in_app_webview/get_favicons.dart
index d2ff44a21..402e61b06 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/get_favicons.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/get_favicons.dart
@@ -33,6 +33,7 @@ void getFavicons() {
);
final InAppWebViewController controller = await controllerCompleter.future;
+ await tester.pump();
await pageLoaded.future;
final List? favicons = await controller.getFavicons();
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/get_html.dart b/flutter_inappwebview/example/integration_test/in_app_webview/get_html.dart
index a6230478f..bd405621d 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/get_html.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/get_html.dart
@@ -33,6 +33,8 @@ void getHtml() {
);
final InAppWebViewController controller = await controllerCompleter.future;
+ // Platform view creation happens asynchronously.
+ await tester.pump();
await pageLoaded.future;
final String? html = await controller.getHtml();
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/get_meta_tags.dart b/flutter_inappwebview/example/integration_test/in_app_webview/get_meta_tags.dart
index e30b703e8..c6bc57394 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/get_meta_tags.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/get_meta_tags.dart
@@ -33,6 +33,7 @@ void getMetaTags() {
);
final InAppWebViewController controller = await controllerCompleter.future;
+ await tester.pump();
await pageLoaded.future;
List metaTags = await controller.getMetaTags();
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/get_meta_theme_color.dart b/flutter_inappwebview/example/integration_test/in_app_webview/get_meta_theme_color.dart
index 15f8fe863..b3cfcbfa2 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/get_meta_theme_color.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/get_meta_theme_color.dart
@@ -33,6 +33,7 @@ void getMetaThemeColor() {
);
final InAppWebViewController controller = await controllerCompleter.future;
+ await tester.pump();
await pageLoaded.future;
expect(await controller.getMetaThemeColor(), isNotNull);
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/get_original_url.dart b/flutter_inappwebview/example/integration_test/in_app_webview/get_original_url.dart
index 635e95d91..182a4d1d4 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/get_original_url.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/get_original_url.dart
@@ -33,6 +33,7 @@ void getOriginalUrl() {
);
final InAppWebViewController controller = await controllerCompleter.future;
+ await tester.pump();
await pageLoaded.future;
var originUrl = (await controller.getOriginalUrl())?.toString();
expect(originUrl, url.toString());
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/get_title.dart b/flutter_inappwebview/example/integration_test/in_app_webview/get_title.dart
index dcd492244..78de31c0e 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/get_title.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/get_title.dart
@@ -50,6 +50,7 @@ void getTitle() {
);
final InAppWebViewController controller = await controllerCompleter.future;
+ await tester.pump();
await pageStarted.future;
await pageLoaded.future;
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/initial_url_request.dart b/flutter_inappwebview/example/integration_test/in_app_webview/initial_url_request.dart
index 792467b3c..bb93e4bbe 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/initial_url_request.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/initial_url_request.dart
@@ -80,6 +80,8 @@ void initialUrlRequest() {
),
),
);
+ // Platform view creation happens asynchronously.
+ await tester.pump();
await pageLoaded.future;
final InAppWebViewController controller =
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/inject_css.dart b/flutter_inappwebview/example/integration_test/in_app_webview/inject_css.dart
index cb5563941..108a0bdc2 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/inject_css.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/inject_css.dart
@@ -35,6 +35,7 @@ void injectCSS() {
final InAppWebViewController controller =
await controllerCompleter.future;
+ await tester.pump();
await pageLoaded.future;
await controller.injectCSSCode(source: """
@@ -74,6 +75,7 @@ void injectCSS() {
final InAppWebViewController controller =
await controllerCompleter.future;
+ await tester.pump();
await pageLoaded.future;
await controller.injectCSSFileFromUrl(
@@ -110,6 +112,7 @@ void injectCSS() {
final InAppWebViewController controller =
await controllerCompleter.future;
+ await tester.pump();
await pageLoaded.future;
await controller.injectCSSFileFromAsset(
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/inject_javascript_file.dart b/flutter_inappwebview/example/integration_test/in_app_webview/inject_javascript_file.dart
index 1f60b5c02..b85c28790 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/inject_javascript_file.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/inject_javascript_file.dart
@@ -37,6 +37,7 @@ void injectJavascriptFile() {
final InAppWebViewController controller =
await controllerCompleter.future;
+ await tester.pump();
await pageLoaded.future;
await controller.injectJavascriptFileFromUrl(
@@ -97,6 +98,7 @@ void injectJavascriptFile() {
final InAppWebViewController controller =
await controllerCompleter.future;
+ await tester.pump();
await pageLoaded.future;
await controller.injectJavascriptFileFromAsset(
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/is_secure_context.dart b/flutter_inappwebview/example/integration_test/in_app_webview/is_secure_context.dart
index 3c5d8a6cc..8457aff11 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/is_secure_context.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/is_secure_context.dart
@@ -34,6 +34,7 @@ void isSecureContext() {
);
final InAppWebViewController controller = await controllerCompleter.future;
+ await tester.pump();
await pageLoads.stream.first;
expect(await controller.isSecureContext(), true);
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/javascript_code_evaluation.dart b/flutter_inappwebview/example/integration_test/in_app_webview/javascript_code_evaluation.dart
index 8f9a683f2..4ac6f3a6f 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/javascript_code_evaluation.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/javascript_code_evaluation.dart
@@ -40,6 +40,7 @@ void javascriptCodeEvaluation() {
);
final InAppWebViewController controller =
await controllerCompleter.future;
+ await tester.pump();
await pageLoaded.future;
var result = await controller.evaluateJavascript(source: """
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/load_data.dart b/flutter_inappwebview/example/integration_test/in_app_webview/load_data.dart
index e5fb32ee9..4ada282aa 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/load_data.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/load_data.dart
@@ -32,6 +32,8 @@ void loadData() {
);
final InAppWebViewController controller = await controllerCompleter.future;
+ // do not wait for pump to not miss the load event
+ tester.pump();
await pageLoads.stream.first;
final data = """
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/load_file.dart b/flutter_inappwebview/example/integration_test/in_app_webview/load_file.dart
index 09dbbcc85..df857e569 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/load_file.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/load_file.dart
@@ -32,6 +32,8 @@ void loadFile() {
);
final InAppWebViewController controller = await controllerCompleter.future;
+ // do not wait for pump to not miss the load event
+ tester.pump();
await pageLoads.stream.first;
await controller.loadFile(
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/load_url.dart b/flutter_inappwebview/example/integration_test/in_app_webview/load_url.dart
index bdb1f5bea..4fca15158 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/load_url.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/load_url.dart
@@ -39,6 +39,7 @@ void loadUrl() {
),
);
final InAppWebViewController controller = await controllerCompleter.future;
+ await tester.pump();
expect(await firstUrlLoad.future, initialUrl.toString());
await controller.loadUrl(
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/main.dart b/flutter_inappwebview/example/integration_test/in_app_webview/main.dart
index 6f9239dbb..4f2b9a863 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/main.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/main.dart
@@ -220,7 +220,7 @@ void main() {
contentBlocker();
httpAuthCredentialDatabase();
onConsoleMessage();
- onDownloadStartRequest();
+ onDownloadStarting();
javascriptDialogs();
onReceivedHttpError();
onLoadResourceWithCustomScheme();
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/on_console_message.dart b/flutter_inappwebview/example/integration_test/in_app_webview/on_console_message.dart
index 495d12c4b..a09ceb3ff 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/on_console_message.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/on_console_message.dart
@@ -33,7 +33,7 @@ void onConsoleMessage() {
),
),
);
-
+ await tester.pump();
final ConsoleMessage consoleMessage =
await onConsoleMessageCompleter.future;
expect(consoleMessage.message, 'message');
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/on_download_start_request.dart b/flutter_inappwebview/example/integration_test/in_app_webview/on_download_start_request.dart
index ba735534d..952c0d0e7 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/on_download_start_request.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/on_download_start_request.dart
@@ -1,6 +1,6 @@
part of 'main.dart';
-void onDownloadStartRequest() {
+void onDownloadStarting() {
final shouldSkip = kIsWeb
? true
: ![
@@ -9,7 +9,7 @@ void onDownloadStartRequest() {
TargetPlatform.macOS,
].contains(defaultTargetPlatform);
- skippableTestWidgets('onDownloadStartRequest', (WidgetTester tester) async {
+ skippableTestWidgets('onDownloadStarting', (WidgetTester tester) async {
final Completer controllerCompleter =
Completer();
final Completer onDownloadStartCompleter = Completer();
@@ -41,8 +41,9 @@ void onDownloadStartRequest() {
onWebViewCreated: (controller) {
controllerCompleter.complete(controller);
},
- onDownloadStartRequest: (controller, request) {
+ onDownloadStarting: (controller, request) {
onDownloadStartCompleter.complete(request.url.toString());
+ return null;
},
),
),
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/on_scroll_changed.dart b/flutter_inappwebview/example/integration_test/in_app_webview/on_scroll_changed.dart
index 6903cbc89..7d4fe106d 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/on_scroll_changed.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/on_scroll_changed.dart
@@ -38,9 +38,8 @@ void onScrollChanged() {
);
final InAppWebViewController controller = await controllerCompleter.future;
- await pageLoaded.future;
-
await tester.pump();
+ await pageLoaded.future;
controller.scrollTo(x: 0, y: 500);
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/on_title_changed.dart b/flutter_inappwebview/example/integration_test/in_app_webview/on_title_changed.dart
index d0f6fb5a2..cbcd342a9 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/on_title_changed.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/on_title_changed.dart
@@ -41,8 +41,8 @@ void onTitleChanged() {
);
final InAppWebViewController controller = await controllerCompleter.future;
- await pageLoaded.future;
await tester.pump();
+ await pageLoaded.future;
await controller.evaluateJavascript(
source: "document.title = 'title test';");
await expectLater(onTitleChangedCompleter.future, completes);
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/on_update_visited_history.dart b/flutter_inappwebview/example/integration_test/in_app_webview/on_update_visited_history.dart
index 9976e81e4..a43f1e4b9 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/on_update_visited_history.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/on_update_visited_history.dart
@@ -43,6 +43,7 @@ void onUpdateVisitedHistory() {
);
final InAppWebViewController controller = await controllerCompleter.future;
+ await tester.pump();
await pageLoaded.future;
await controller.evaluateJavascript(source: """
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/on_window_blur.dart b/flutter_inappwebview/example/integration_test/in_app_webview/on_window_blur.dart
index cb7b3282f..0b1fe9c3d 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/on_window_blur.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/on_window_blur.dart
@@ -29,6 +29,7 @@ void onWindowBlur() {
),
),
);
+ await tester.pump();
await expectLater(onWindowBlurCompleter.future, completes);
}, skip: shouldSkip);
}
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/on_window_focus.dart b/flutter_inappwebview/example/integration_test/in_app_webview/on_window_focus.dart
index c07fe5282..ded782e10 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/on_window_focus.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/on_window_focus.dart
@@ -29,6 +29,7 @@ void onWindowFocus() {
),
),
);
+ await tester.pump();
await expectLater(onWindowFocusCompleter.future, completes);
}, skip: shouldSkip);
}
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/print_current_page.dart b/flutter_inappwebview/example/integration_test/in_app_webview/print_current_page.dart
index 13a11c0fd..d38e206cb 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/print_current_page.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/print_current_page.dart
@@ -33,8 +33,8 @@ void printCurrentPage() {
);
final InAppWebViewController controller = await controllerCompleter.future;
- await pageLoaded.future;
await tester.pump();
+ await pageLoaded.future;
await expectLater(controller.printCurrentPage(), completes);
}, skip: shouldSkip);
}
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/programmatic_scroll.dart b/flutter_inappwebview/example/integration_test/in_app_webview/programmatic_scroll.dart
index 640e7129d..582c808af 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/programmatic_scroll.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/programmatic_scroll.dart
@@ -69,9 +69,8 @@ void programmaticScroll() {
final InAppWebViewController controller =
await controllerCompleter.future;
- await pageLoaded.future;
-
await tester.pump();
+ await pageLoaded.future;
await controller.scrollTo(x: 0, y: 0);
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/reload.dart b/flutter_inappwebview/example/integration_test/in_app_webview/reload.dart
index 5cdb218da..b01c7fa28 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/reload.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/reload.dart
@@ -71,6 +71,8 @@ void reload() {
);
final InAppWebViewController controller =
await controllerCompleter.future;
+ // do not wait for pump to not miss the load event
+ tester.pump();
String? reloadUrl = await pageLoads.stream.first;
expect(reloadUrl, url.toString());
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/set_get_settings.dart b/flutter_inappwebview/example/integration_test/in_app_webview/set_get_settings.dart
index 2c5a6d0fa..5bea368ca 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/set_get_settings.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/set_get_settings.dart
@@ -32,6 +32,8 @@ void setGetSettings() {
),
),
);
+ // Platform view creation happens asynchronously.
+ await tester.pumpAndSettle();
final InAppWebViewController controller = await controllerCompleter.future;
await pageLoaded.future;
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/user_scripts.dart b/flutter_inappwebview/example/integration_test/in_app_webview/user_scripts.dart
index 078218caf..933bfc428 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/user_scripts.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/user_scripts.dart
@@ -32,10 +32,14 @@ void userScripts() {
UserScript(
source: "var bar = 2;",
injectionTime: UserScriptInjectionTime.AT_DOCUMENT_END,
+ forMainFrameOnly:
+ defaultTargetPlatform != TargetPlatform.android,
contentWorld: ContentWorld.DEFAULT_CLIENT),
UserScript(
source: "var bar2 = 12;",
injectionTime: UserScriptInjectionTime.AT_DOCUMENT_END,
+ forMainFrameOnly:
+ defaultTargetPlatform != TargetPlatform.android,
contentWorld: ContentWorld.world(name: "test")),
]),
onWebViewCreated: (controller) {
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/web_archive.dart b/flutter_inappwebview/example/integration_test/in_app_webview/web_archive.dart
index 914011ec4..36a25f410 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/web_archive.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/web_archive.dart
@@ -60,7 +60,9 @@ void webArchive() {
controllerCompleter.complete(controller);
},
onLoadStop: (controller, url) {
- pageLoaded.complete();
+ if (!pageLoaded.isCompleted) {
+ pageLoaded.complete();
+ }
},
),
),
diff --git a/flutter_inappwebview/example/integration_test/in_app_webview/webview_windows.dart b/flutter_inappwebview/example/integration_test/in_app_webview/webview_windows.dart
index 1db16a354..cc6eb3338 100644
--- a/flutter_inappwebview/example/integration_test/in_app_webview/webview_windows.dart
+++ b/flutter_inappwebview/example/integration_test/in_app_webview/webview_windows.dart
@@ -49,7 +49,7 @@ void webViewWindows() {
),
),
);
-
+ await tester.pump();
await expectLater(pageLoaded.future, completes);
}, skip: shouldSkipTest1);
diff --git a/flutter_inappwebview/example/integration_test/proxy_controller/clear_and_set_proxy_override.dart b/flutter_inappwebview/example/integration_test/proxy_controller/clear_and_set_proxy_override.dart
index 349902e6f..8a8a4392c 100644
--- a/flutter_inappwebview/example/integration_test/proxy_controller/clear_and_set_proxy_override.dart
+++ b/flutter_inappwebview/example/integration_test/proxy_controller/clear_and_set_proxy_override.dart
@@ -5,6 +5,8 @@ void clearAndSetProxyOverride() {
? true
: ![
TargetPlatform.android,
+ TargetPlatform.iOS,
+ TargetPlatform.macOS,
].contains(defaultTargetPlatform);
skippableTestWidgets('clear and set proxy override',
@@ -13,7 +15,7 @@ void clearAndSetProxyOverride() {
Completer();
final Completer pageLoaded = Completer();
- var proxyAvailable =
+ var proxyAvailable = defaultTargetPlatform != TargetPlatform.android ||
await WebViewFeature.isFeatureSupported(WebViewFeature.PROXY_OVERRIDE);
if (proxyAvailable) {
diff --git a/flutter_inappwebview/example/ios/Flutter/AppFrameworkInfo.plist b/flutter_inappwebview/example/ios/Flutter/AppFrameworkInfo.plist
index 9625e105d..7c5696400 100755
--- a/flutter_inappwebview/example/ios/Flutter/AppFrameworkInfo.plist
+++ b/flutter_inappwebview/example/ios/Flutter/AppFrameworkInfo.plist
@@ -21,6 +21,6 @@
CFBundleVersion
1.0
MinimumOSVersion
- 11.0
+ 12.0
diff --git a/flutter_inappwebview/example/ios/Podfile b/flutter_inappwebview/example/ios/Podfile
index 88359b225..2c068c404 100644
--- a/flutter_inappwebview/example/ios/Podfile
+++ b/flutter_inappwebview/example/ios/Podfile
@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
-# platform :ios, '11.0'
+platform :ios, '12.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
diff --git a/flutter_inappwebview/example/ios/Runner.xcodeproj/project.pbxproj b/flutter_inappwebview/example/ios/Runner.xcodeproj/project.pbxproj
index b2616bdee..2e0efe407 100644
--- a/flutter_inappwebview/example/ios/Runner.xcodeproj/project.pbxproj
+++ b/flutter_inappwebview/example/ios/Runner.xcodeproj/project.pbxproj
@@ -212,6 +212,7 @@
97C146EC1CF9000F007C117D /* Resources */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
DFFD8453B8E169BF6BE74B49 /* [CP] Embed Pods Frameworks */,
+ 1F85D10872C1EEC5B3816B3D /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@@ -231,7 +232,7 @@
attributes = {
BuildIndependentTargetsInParallel = YES;
LastSwiftUpdateCheck = 1400;
- LastUpgradeCheck = 1430;
+ LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "The Chromium Authors";
TargetAttributes = {
6143FF34290959650014A1FC = {
@@ -294,6 +295,24 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
+ 1F85D10872C1EEC5B3816B3D /* [CP] Copy Pods Resources */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh",
+ "${PODS_CONFIGURATION_BUILD_DIR}/permission_handler_apple/permission_handler_apple_privacy.bundle",
+ );
+ name = "[CP] Copy Pods Resources";
+ outputPaths = (
+ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/permission_handler_apple_privacy.bundle",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
@@ -359,6 +378,7 @@
"${BUILT_PRODUCTS_DIR}/flutter_inappwebview_ios/flutter_inappwebview_ios.framework",
"${BUILT_PRODUCTS_DIR}/integration_test/integration_test.framework",
"${BUILT_PRODUCTS_DIR}/path_provider_foundation/path_provider_foundation.framework",
+ "${BUILT_PRODUCTS_DIR}/pointer_interceptor_ios/pointer_interceptor_ios.framework",
"${BUILT_PRODUCTS_DIR}/url_launcher_ios/url_launcher_ios.framework",
);
name = "[CP] Embed Pods Frameworks";
@@ -368,6 +388,7 @@
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_inappwebview_ios.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/integration_test.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider_foundation.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/pointer_interceptor_ios.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher_ios.framework",
);
runOnlyForDeploymentPostprocessing = 0;
@@ -460,7 +481,7 @@
MARKETING_VERSION = 1.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
- PRODUCT_BUNDLE_IDENTIFIER = "com.pichillilorenzo.flutterinappwebview-ios-example.test";
+ PRODUCT_BUNDLE_IDENTIFIER = "com.pichillilorenzo.flutterinappwebview-ios-example4.test";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
@@ -497,7 +518,7 @@
);
MARKETING_VERSION = 1.0;
MTL_FAST_MATH = YES;
- PRODUCT_BUNDLE_IDENTIFIER = "com.pichillilorenzo.flutterinappwebview-ios-example.test";
+ PRODUCT_BUNDLE_IDENTIFIER = "com.pichillilorenzo.flutterinappwebview-ios-example4.test";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
@@ -646,7 +667,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
- PRODUCT_BUNDLE_IDENTIFIER = "com.pichillilorenzo.flutterinappwebview-ios-example";
+ PRODUCT_BUNDLE_IDENTIFIER = "com.pichillilorenzo.flutterinappwebview-ios-example4";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -681,7 +702,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
- PRODUCT_BUNDLE_IDENTIFIER = "com.pichillilorenzo.flutterinappwebview-ios-example";
+ PRODUCT_BUNDLE_IDENTIFIER = "com.pichillilorenzo.flutterinappwebview-ios-example4";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
diff --git a/flutter_inappwebview/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/flutter_inappwebview/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index 9c585c83b..cdef6845d 100755
--- a/flutter_inappwebview/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/flutter_inappwebview/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,6 +1,6 @@
? initialUserScripts,
PullToRefreshController? pullToRefreshController})
: super(
- windowId: windowId,
- initialUserScripts: initialUserScripts,
- pullToRefreshController: pullToRefreshController);
+ windowId: windowId,
+ initialUserScripts: initialUserScripts,
+ pullToRefreshController: pullToRefreshController,
+ webViewEnvironment: webViewEnvironment,
+ );
@override
- Future onBrowserCreated() async {
+ void onBrowserCreated() {
print("\n\nBrowser Created!\n\n");
}
@override
- Future onLoadStart(url) async {}
+ void onLoadStart(url) {}
@override
- Future onLoadStop(url) async {
+ void onLoadStop(url) {
pullToRefreshController?.endRefreshing();
}
@override
- Future onPermissionRequest(request) async {
+ FutureOr onPermissionRequest(request) {
return PermissionResponse(
resources: request.resources, action: PermissionResponseAction.GRANT);
}
@@ -56,8 +58,8 @@ class MyInAppBrowser extends InAppBrowser {
}
@override
- Future shouldOverrideUrlLoading(
- navigationAction) async {
+ FutureOr shouldOverrideUrlLoading(
+ navigationAction) {
print("\n\nOverride ${navigationAction.request.url}\n\n");
return NavigationActionPolicy.ALLOW;
}
diff --git a/flutter_inappwebview/example/lib/in_app_webiew_example.screen.dart b/flutter_inappwebview/example/lib/in_app_webiew_example.screen.dart
index 79dc016fa..4acc6d966 100755
--- a/flutter_inappwebview/example/lib/in_app_webiew_example.screen.dart
+++ b/flutter_inappwebview/example/lib/in_app_webiew_example.screen.dart
@@ -1,4 +1,5 @@
import 'dart:collection';
+
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
@@ -73,8 +74,7 @@ class _InAppWebViewExampleScreenState extends State {
onRefresh: () async {
if (defaultTargetPlatform == TargetPlatform.android) {
webViewController?.reload();
- } else if (defaultTargetPlatform == TargetPlatform.iOS ||
- defaultTargetPlatform == TargetPlatform.macOS) {
+ } else if (defaultTargetPlatform == TargetPlatform.iOS) {
webViewController?.loadUrl(
urlRequest:
URLRequest(url: await webViewController?.getUrl()));
@@ -115,6 +115,7 @@ class _InAppWebViewExampleScreenState extends State {
children: [
InAppWebView(
key: webViewKey,
+ webViewEnvironment: webViewEnvironment,
initialUrlRequest:
URLRequest(url: WebUri('https://flutter.dev')),
// initialUrlRequest:
@@ -127,13 +128,13 @@ class _InAppWebViewExampleScreenState extends State {
onWebViewCreated: (controller) async {
webViewController = controller;
},
- onLoadStart: (controller, url) async {
+ onLoadStart: (controller, url) {
setState(() {
this.url = url.toString();
urlController.text = this.url;
});
},
- onPermissionRequest: (controller, request) async {
+ onPermissionRequest: (controller, request) {
return PermissionResponse(
resources: request.resources,
action: PermissionResponseAction.GRANT);
@@ -163,7 +164,7 @@ class _InAppWebViewExampleScreenState extends State {
return NavigationActionPolicy.ALLOW;
},
- onLoadStop: (controller, url) async {
+ onLoadStop: (controller, url) {
pullToRefreshController?.endRefreshing();
setState(() {
this.url = url.toString();
diff --git a/flutter_inappwebview/example/lib/main.dart b/flutter_inappwebview/example/lib/main.dart
index 21760f269..0a7802bd8 100755
--- a/flutter_inappwebview/example/lib/main.dart
+++ b/flutter_inappwebview/example/lib/main.dart
@@ -3,11 +3,10 @@ import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
-
import 'package:flutter_inappwebview_example/chrome_safari_browser_example.screen.dart';
import 'package:flutter_inappwebview_example/headless_in_app_webview.screen.dart';
-import 'package:flutter_inappwebview_example/in_app_webiew_example.screen.dart';
import 'package:flutter_inappwebview_example/in_app_browser_example.screen.dart';
+import 'package:flutter_inappwebview_example/in_app_webiew_example.screen.dart';
import 'package:flutter_inappwebview_example/web_authentication_session_example.screen.dart';
import 'package:pointer_interceptor/pointer_interceptor.dart';
@@ -15,6 +14,7 @@ import 'package:pointer_interceptor/pointer_interceptor.dart';
// import 'package:permission_handler/permission_handler.dart';
final localhostServer = InAppLocalhostServer(documentRoot: 'assets');
+WebViewEnvironment? webViewEnvironment;
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
@@ -22,12 +22,28 @@ Future main() async {
// await Permission.microphone.request();
// await Permission.storage.request();
- if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
- await InAppWebViewController.setWebContentsDebuggingEnabled(kDebugMode);
+ if (!kIsWeb && defaultTargetPlatform == TargetPlatform.windows) {
+ final availableVersion = await WebViewEnvironment.getAvailableVersion();
+ assert(availableVersion != null,
+ 'Failed to find an installed WebView2 runtime or non-stable Microsoft Edge installation.');
+
+ webViewEnvironment = await WebViewEnvironment.create(
+ settings: WebViewEnvironmentSettings(
+ additionalBrowserArguments: kDebugMode
+ ? '--enable-features=msEdgeDevToolsWdpRemoteDebugging'
+ : null,
+ userDataFolder: 'custom_path',
+ ));
+
+ webViewEnvironment?.onBrowserProcessExited = (detail) {
+ if (kDebugMode) {
+ print('Browser process exited with detail: $detail');
+ }
+ };
}
- if (!kIsWeb) {
- await localhostServer.start();
+ if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
+ await InAppWebViewController.setWebContentsDebuggingEnabled(kDebugMode);
}
runApp(MyApp());
@@ -77,24 +93,18 @@ PointerInterceptor myDrawer({required BuildContext context}) {
];
} else if (defaultTargetPlatform == TargetPlatform.macOS) {
children = [
- // ListTile(
- // title: Text('InAppWebView'),
- // onTap: () {
- // Navigator.pushReplacementNamed(context, '/');
- // },
- // ),
- // ListTile(
- // title: Text('InAppBrowser'),
- // onTap: () {
- // Navigator.pushReplacementNamed(context, '/InAppBrowser');
- // },
- // ),
ListTile(
- title: Text('InAppBrowser'),
+ title: Text('InAppWebView'),
onTap: () {
Navigator.pushReplacementNamed(context, '/');
},
),
+ ListTile(
+ title: Text('InAppBrowser'),
+ onTap: () {
+ Navigator.pushReplacementNamed(context, '/InAppBrowser');
+ },
+ ),
ListTile(
title: Text('WebAuthenticationSession'),
onTap: () {
@@ -108,6 +118,28 @@ PointerInterceptor myDrawer({required BuildContext context}) {
},
),
];
+ } else if (defaultTargetPlatform == TargetPlatform.windows ||
+ defaultTargetPlatform == TargetPlatform.linux) {
+ children = [
+ ListTile(
+ title: Text('InAppWebView'),
+ onTap: () {
+ Navigator.pushReplacementNamed(context, '/');
+ },
+ ),
+ ListTile(
+ title: Text('InAppBrowser'),
+ onTap: () {
+ Navigator.pushReplacementNamed(context, '/InAppBrowser');
+ },
+ ),
+ ListTile(
+ title: Text('HeadlessInAppWebView'),
+ onTap: () {
+ Navigator.pushReplacementNamed(context, '/HeadlessInAppWebView');
+ },
+ ),
+ ];
}
return PointerInterceptor(
child: Drawer(
@@ -152,14 +184,21 @@ class _MyAppState extends State {
}
if (defaultTargetPlatform == TargetPlatform.macOS) {
return MaterialApp(initialRoute: '/', routes: {
- // '/': (context) => InAppWebViewExampleScreen(),
- // '/InAppBrowser': (context) => InAppBrowserExampleScreen(),
- '/': (context) => InAppBrowserExampleScreen(),
+ '/': (context) => InAppWebViewExampleScreen(),
+ '/InAppBrowser': (context) => InAppBrowserExampleScreen(),
'/HeadlessInAppWebView': (context) =>
HeadlessInAppWebViewExampleScreen(),
'/WebAuthenticationSession': (context) =>
WebAuthenticationSessionExampleScreen(),
});
+ } else if (defaultTargetPlatform == TargetPlatform.windows ||
+ defaultTargetPlatform == TargetPlatform.linux) {
+ return MaterialApp(initialRoute: '/', routes: {
+ '/': (context) => InAppWebViewExampleScreen(),
+ '/InAppBrowser': (context) => InAppBrowserExampleScreen(),
+ '/HeadlessInAppWebView': (context) =>
+ HeadlessInAppWebViewExampleScreen(),
+ });
}
return MaterialApp(initialRoute: '/', routes: {
'/': (context) => InAppWebViewExampleScreen(),
diff --git a/flutter_inappwebview/example/macos/Runner.xcodeproj/project.pbxproj b/flutter_inappwebview/example/macos/Runner.xcodeproj/project.pbxproj
index 9ec203702..4df2c9849 100644
--- a/flutter_inappwebview/example/macos/Runner.xcodeproj/project.pbxproj
+++ b/flutter_inappwebview/example/macos/Runner.xcodeproj/project.pbxproj
@@ -202,7 +202,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0920;
- LastUpgradeCheck = 1430;
+ LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
33CC10EC2044A3C60003C045 = {
diff --git a/flutter_inappwebview/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/flutter_inappwebview/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index 8ff1edec0..05ad528d0 100644
--- a/flutter_inappwebview/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/flutter_inappwebview/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,6 +1,6 @@
Bool {
return true
diff --git a/flutter_inappwebview/example/macos/Runner/Info.plist b/flutter_inappwebview/example/macos/Runner/Info.plist
index 4789daa6a..0c93eff43 100644
--- a/flutter_inappwebview/example/macos/Runner/Info.plist
+++ b/flutter_inappwebview/example/macos/Runner/Info.plist
@@ -22,6 +22,13 @@
$(FLUTTER_BUILD_NUMBER)
LSMinimumSystemVersion
$(MACOSX_DEPLOYMENT_TARGET)
+ NSAppTransportSecurity
+
+ NSAllowsArbitraryLoads
+
+ NSAllowsArbitraryLoadsInWebContent
+
+
NSHumanReadableCopyright
$(PRODUCT_COPYRIGHT)
NSMainNibFile
diff --git a/flutter_inappwebview/example/pubspec.yaml b/flutter_inappwebview/example/pubspec.yaml
index fa737046b..0efca4a07 100755
--- a/flutter_inappwebview/example/pubspec.yaml
+++ b/flutter_inappwebview/example/pubspec.yaml
@@ -12,8 +12,8 @@ version: 1.0.0+1
publish_to: none
environment:
- sdk: ">=2.17.0 <4.0.0"
- flutter: ">=3.0.0"
+ sdk: ">=3.3.0 <4.0.0"
+ flutter: ">=3.19.0"
dependencies:
flutter:
@@ -21,12 +21,12 @@ dependencies:
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
- cupertino_icons: ^1.0.4
- flutter_downloader: 1.10.2
- path_provider: 2.0.15
- permission_handler: 10.2.0
- url_launcher: 6.1.11
- pointer_interceptor: ^0.9.3+4
+ cupertino_icons: ^1.0.8
+ flutter_downloader: 1.11.8
+ path_provider: 2.1.4
+ permission_handler: 11.3.1
+ url_launcher: 6.3.0
+ pointer_interceptor: ^0.10.1+2
# mime: ^1.0.4
# connectivity: ^0.4.5+6
flutter_inappwebview:
@@ -43,6 +43,8 @@ dependency_overrides:
path: ../../flutter_inappwebview_macos
flutter_inappwebview_web:
path: ../../flutter_inappwebview_web
+ flutter_inappwebview_windows:
+ path: ../../flutter_inappwebview_windows
dev_dependencies:
flutter_test:
@@ -56,7 +58,7 @@ dev_dependencies:
# git:
# url: https://github.com/flutter/plugins.git
# path: packages/integration_test
- flutter_lints: ^2.0.1
+ flutter_lints: ^4.0.0
# For information on the generic Dart part of this file, see the
# following page: https://www.dartlang.org/tools/pub/pubspec
diff --git a/flutter_inappwebview/example/test/widget_test.dart b/flutter_inappwebview/example/test/widget_test.dart
new file mode 100644
index 000000000..e69de29bb
diff --git a/flutter_inappwebview/example/web/index.html b/flutter_inappwebview/example/web/index.html
index cb50c1621..0e7eaf616 100644
--- a/flutter_inappwebview/example/web/index.html
+++ b/flutter_inappwebview/example/web/index.html
@@ -39,69 +39,6 @@
-
+
diff --git a/flutter_inappwebview/example/windows/.gitignore b/flutter_inappwebview/example/windows/.gitignore
new file mode 100644
index 000000000..5d57396c8
--- /dev/null
+++ b/flutter_inappwebview/example/windows/.gitignore
@@ -0,0 +1,19 @@
+flutter/ephemeral/
+
+# Visual Studio user-specific files.
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# Visual Studio build-related files.
+x64/
+x86/
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+cmake-build-*
\ No newline at end of file
diff --git a/flutter_inappwebview/example/windows/CMakeLists.txt b/flutter_inappwebview/example/windows/CMakeLists.txt
new file mode 100644
index 000000000..d960948af
--- /dev/null
+++ b/flutter_inappwebview/example/windows/CMakeLists.txt
@@ -0,0 +1,108 @@
+# Project-level configuration.
+cmake_minimum_required(VERSION 3.14)
+project(example LANGUAGES CXX)
+
+# The name of the executable created for the application. Change this to change
+# the on-disk name of your application.
+set(BINARY_NAME "example")
+
+# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
+# versions of CMake.
+cmake_policy(VERSION 3.14...3.25)
+
+# Define build configuration option.
+get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+if(IS_MULTICONFIG)
+ set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release"
+ CACHE STRING "" FORCE)
+else()
+ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
+ set(CMAKE_BUILD_TYPE "Debug" CACHE
+ STRING "Flutter build mode" FORCE)
+ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
+ "Debug" "Profile" "Release")
+ endif()
+endif()
+# Define settings for the Profile build mode.
+set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
+set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}")
+set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}")
+set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}")
+
+# Use Unicode for all projects.
+add_definitions(-DUNICODE -D_UNICODE)
+
+# Compilation settings that should be applied to most targets.
+#
+# Be cautious about adding new options here, as plugins use this function by
+# default. In most cases, you should add new options to specific targets instead
+# of modifying this function.
+function(APPLY_STANDARD_SETTINGS TARGET)
+ target_compile_features(${TARGET} PUBLIC cxx_std_17)
+ target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100")
+ target_compile_options(${TARGET} PRIVATE /EHsc)
+ target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0")
+ target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>")
+endfunction()
+
+# Flutter library and tool build rules.
+set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
+add_subdirectory(${FLUTTER_MANAGED_DIR})
+
+# Application build; see runner/CMakeLists.txt.
+add_subdirectory("runner")
+
+
+# Generated plugin build rules, which manage building the plugins and adding
+# them to the application.
+include(flutter/generated_plugins.cmake)
+
+
+# === Installation ===
+# Support files are copied into place next to the executable, so that it can
+# run in place. This is done instead of making a separate bundle (as on Linux)
+# so that building and running from within Visual Studio will work.
+set(BUILD_BUNDLE_DIR "$")
+# Make the "install" step default, as it's required to run.
+set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1)
+if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+ set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
+endif()
+
+set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
+set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}")
+
+install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
+ COMPONENT Runtime)
+
+install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
+ COMPONENT Runtime)
+
+install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+ COMPONENT Runtime)
+
+if(PLUGIN_BUNDLED_LIBRARIES)
+ install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
+ DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+ COMPONENT Runtime)
+endif()
+
+# Copy the native assets provided by the build.dart from all packages.
+set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/")
+install(DIRECTORY "${NATIVE_ASSETS_DIR}"
+ DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+ COMPONENT Runtime)
+
+# Fully re-copy the assets directory on each build to avoid having stale files
+# from a previous install.
+set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
+install(CODE "
+ file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
+ " COMPONENT Runtime)
+install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
+ DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
+
+# Install the AOT library on non-Debug builds only.
+install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
+ CONFIGURATIONS Profile;Release
+ COMPONENT Runtime)
diff --git a/flutter_inappwebview/example/windows/flutter/CMakeLists.txt b/flutter_inappwebview/example/windows/flutter/CMakeLists.txt
new file mode 100644
index 000000000..903f4899d
--- /dev/null
+++ b/flutter_inappwebview/example/windows/flutter/CMakeLists.txt
@@ -0,0 +1,109 @@
+# This file controls Flutter-level build steps. It should not be edited.
+cmake_minimum_required(VERSION 3.14)
+
+set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
+
+# Configuration provided via flutter tool.
+include(${EPHEMERAL_DIR}/generated_config.cmake)
+
+# TODO: Move the rest of this into files in ephemeral. See
+# https://github.com/flutter/flutter/issues/57146.
+set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper")
+
+# Set fallback configurations for older versions of the flutter tool.
+if (NOT DEFINED FLUTTER_TARGET_PLATFORM)
+ set(FLUTTER_TARGET_PLATFORM "windows-x64")
+endif()
+
+# === Flutter Library ===
+set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll")
+
+# Published to parent scope for install step.
+set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
+set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
+set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
+set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE)
+
+list(APPEND FLUTTER_LIBRARY_HEADERS
+ "flutter_export.h"
+ "flutter_windows.h"
+ "flutter_messenger.h"
+ "flutter_plugin_registrar.h"
+ "flutter_texture_registrar.h"
+)
+list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/")
+add_library(flutter INTERFACE)
+target_include_directories(flutter INTERFACE
+ "${EPHEMERAL_DIR}"
+)
+target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib")
+add_dependencies(flutter flutter_assemble)
+
+# === Wrapper ===
+list(APPEND CPP_WRAPPER_SOURCES_CORE
+ "core_implementations.cc"
+ "standard_codec.cc"
+)
+list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/")
+list(APPEND CPP_WRAPPER_SOURCES_PLUGIN
+ "plugin_registrar.cc"
+)
+list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/")
+list(APPEND CPP_WRAPPER_SOURCES_APP
+ "flutter_engine.cc"
+ "flutter_view_controller.cc"
+)
+list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/")
+
+# Wrapper sources needed for a plugin.
+add_library(flutter_wrapper_plugin STATIC
+ ${CPP_WRAPPER_SOURCES_CORE}
+ ${CPP_WRAPPER_SOURCES_PLUGIN}
+)
+apply_standard_settings(flutter_wrapper_plugin)
+set_target_properties(flutter_wrapper_plugin PROPERTIES
+ POSITION_INDEPENDENT_CODE ON)
+set_target_properties(flutter_wrapper_plugin PROPERTIES
+ CXX_VISIBILITY_PRESET hidden)
+target_link_libraries(flutter_wrapper_plugin PUBLIC flutter)
+target_include_directories(flutter_wrapper_plugin PUBLIC
+ "${WRAPPER_ROOT}/include"
+)
+add_dependencies(flutter_wrapper_plugin flutter_assemble)
+
+# Wrapper sources needed for the runner.
+add_library(flutter_wrapper_app STATIC
+ ${CPP_WRAPPER_SOURCES_CORE}
+ ${CPP_WRAPPER_SOURCES_APP}
+)
+apply_standard_settings(flutter_wrapper_app)
+target_link_libraries(flutter_wrapper_app PUBLIC flutter)
+target_include_directories(flutter_wrapper_app PUBLIC
+ "${WRAPPER_ROOT}/include"
+)
+add_dependencies(flutter_wrapper_app flutter_assemble)
+
+# === Flutter tool backend ===
+# _phony_ is a non-existent file to force this command to run every time,
+# since currently there's no way to get a full input/output list from the
+# flutter tool.
+set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_")
+set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE)
+add_custom_command(
+ OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
+ ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN}
+ ${CPP_WRAPPER_SOURCES_APP}
+ ${PHONY_OUTPUT}
+ COMMAND ${CMAKE_COMMAND} -E env
+ ${FLUTTER_TOOL_ENVIRONMENT}
+ "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat"
+ ${FLUTTER_TARGET_PLATFORM} $
+ VERBATIM
+)
+add_custom_target(flutter_assemble DEPENDS
+ "${FLUTTER_LIBRARY}"
+ ${FLUTTER_LIBRARY_HEADERS}
+ ${CPP_WRAPPER_SOURCES_CORE}
+ ${CPP_WRAPPER_SOURCES_PLUGIN}
+ ${CPP_WRAPPER_SOURCES_APP}
+)
diff --git a/flutter_inappwebview/example/windows/flutter/generated_plugin_registrant.cc b/flutter_inappwebview/example/windows/flutter/generated_plugin_registrant.cc
new file mode 100644
index 000000000..031b86957
--- /dev/null
+++ b/flutter_inappwebview/example/windows/flutter/generated_plugin_registrant.cc
@@ -0,0 +1,20 @@
+//
+// Generated file. Do not edit.
+//
+
+// clang-format off
+
+#include "generated_plugin_registrant.h"
+
+#include
+#include
+#include
+
+void RegisterPlugins(flutter::PluginRegistry* registry) {
+ FlutterInappwebviewWindowsPluginCApiRegisterWithRegistrar(
+ registry->GetRegistrarForPlugin("FlutterInappwebviewWindowsPluginCApi"));
+ PermissionHandlerWindowsPluginRegisterWithRegistrar(
+ registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
+ UrlLauncherWindowsRegisterWithRegistrar(
+ registry->GetRegistrarForPlugin("UrlLauncherWindows"));
+}
diff --git a/flutter_inappwebview/example/windows/flutter/generated_plugin_registrant.h b/flutter_inappwebview/example/windows/flutter/generated_plugin_registrant.h
new file mode 100644
index 000000000..dc139d85a
--- /dev/null
+++ b/flutter_inappwebview/example/windows/flutter/generated_plugin_registrant.h
@@ -0,0 +1,15 @@
+//
+// Generated file. Do not edit.
+//
+
+// clang-format off
+
+#ifndef GENERATED_PLUGIN_REGISTRANT_
+#define GENERATED_PLUGIN_REGISTRANT_
+
+#include
+
+// Registers Flutter plugins.
+void RegisterPlugins(flutter::PluginRegistry* registry);
+
+#endif // GENERATED_PLUGIN_REGISTRANT_
diff --git a/flutter_inappwebview/example/windows/flutter/generated_plugins.cmake b/flutter_inappwebview/example/windows/flutter/generated_plugins.cmake
new file mode 100644
index 000000000..997d0b803
--- /dev/null
+++ b/flutter_inappwebview/example/windows/flutter/generated_plugins.cmake
@@ -0,0 +1,26 @@
+#
+# Generated file, do not edit.
+#
+
+list(APPEND FLUTTER_PLUGIN_LIST
+ flutter_inappwebview_windows
+ permission_handler_windows
+ url_launcher_windows
+)
+
+list(APPEND FLUTTER_FFI_PLUGIN_LIST
+)
+
+set(PLUGIN_BUNDLED_LIBRARIES)
+
+foreach(plugin ${FLUTTER_PLUGIN_LIST})
+ add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin})
+ target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
+ list(APPEND PLUGIN_BUNDLED_LIBRARIES $)
+ list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
+endforeach(plugin)
+
+foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
+ add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin})
+ list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
+endforeach(ffi_plugin)
diff --git a/flutter_inappwebview/example/windows/runner/CMakeLists.txt b/flutter_inappwebview/example/windows/runner/CMakeLists.txt
new file mode 100644
index 000000000..394917c05
--- /dev/null
+++ b/flutter_inappwebview/example/windows/runner/CMakeLists.txt
@@ -0,0 +1,40 @@
+cmake_minimum_required(VERSION 3.14)
+project(runner LANGUAGES CXX)
+
+# Define the application target. To change its name, change BINARY_NAME in the
+# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer
+# work.
+#
+# Any new source files that you add to the application should be added here.
+add_executable(${BINARY_NAME} WIN32
+ "flutter_window.cpp"
+ "main.cpp"
+ "utils.cpp"
+ "win32_window.cpp"
+ "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
+ "Runner.rc"
+ "runner.exe.manifest"
+)
+
+# Apply the standard set of build settings. This can be removed for applications
+# that need different build settings.
+apply_standard_settings(${BINARY_NAME})
+
+# Add preprocessor definitions for the build version.
+target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"")
+target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}")
+target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}")
+target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}")
+target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}")
+
+# Disable Windows macros that collide with C++ standard library functions.
+target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX")
+
+# Add dependency libraries and include directories. Add any application-specific
+# dependencies here.
+target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app)
+target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib")
+target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
+
+# Run the Flutter tool portions of the build. This must not be removed.
+add_dependencies(${BINARY_NAME} flutter_assemble)
diff --git a/flutter_inappwebview/example/windows/runner/Runner.rc b/flutter_inappwebview/example/windows/runner/Runner.rc
new file mode 100644
index 000000000..302ceb4ba
--- /dev/null
+++ b/flutter_inappwebview/example/windows/runner/Runner.rc
@@ -0,0 +1,121 @@
+// Microsoft Visual C++ generated resource script.
+//
+#pragma code_page(65001)
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (United States) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""winres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_APP_ICON ICON "resources\\app_icon.ico"
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD)
+#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD
+#else
+#define VERSION_AS_NUMBER 1,0,0,0
+#endif
+
+#if defined(FLUTTER_VERSION)
+#define VERSION_AS_STRING FLUTTER_VERSION
+#else
+#define VERSION_AS_STRING "1.0.0"
+#endif
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION VERSION_AS_NUMBER
+ PRODUCTVERSION VERSION_AS_NUMBER
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+#ifdef _DEBUG
+ FILEFLAGS VS_FF_DEBUG
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_APP
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904e4"
+ BEGIN
+ VALUE "CompanyName", "com.pichillilorenzo" "\0"
+ VALUE "FileDescription", "example" "\0"
+ VALUE "FileVersion", VERSION_AS_STRING "\0"
+ VALUE "InternalName", "example" "\0"
+ VALUE "LegalCopyright", "Copyright (C) 2023 com.pichillilorenzo. All rights reserved." "\0"
+ VALUE "OriginalFilename", "example.exe" "\0"
+ VALUE "ProductName", "example" "\0"
+ VALUE "ProductVersion", VERSION_AS_STRING "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1252
+ END
+END
+
+#endif // English (United States) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
diff --git a/flutter_inappwebview/example/windows/runner/flutter_window.cpp b/flutter_inappwebview/example/windows/runner/flutter_window.cpp
new file mode 100644
index 000000000..955ee3038
--- /dev/null
+++ b/flutter_inappwebview/example/windows/runner/flutter_window.cpp
@@ -0,0 +1,71 @@
+#include "flutter_window.h"
+
+#include
+
+#include "flutter/generated_plugin_registrant.h"
+
+FlutterWindow::FlutterWindow(const flutter::DartProject& project)
+ : project_(project) {}
+
+FlutterWindow::~FlutterWindow() {}
+
+bool FlutterWindow::OnCreate() {
+ if (!Win32Window::OnCreate()) {
+ return false;
+ }
+
+ RECT frame = GetClientArea();
+
+ // The size here must match the window dimensions to avoid unnecessary surface
+ // creation / destruction in the startup path.
+ flutter_controller_ = std::make_unique(
+ frame.right - frame.left, frame.bottom - frame.top, project_);
+ // Ensure that basic setup of the controller was successful.
+ if (!flutter_controller_->engine() || !flutter_controller_->view()) {
+ return false;
+ }
+ RegisterPlugins(flutter_controller_->engine());
+ SetChildContent(flutter_controller_->view()->GetNativeWindow());
+
+ flutter_controller_->engine()->SetNextFrameCallback([&]() {
+ this->Show();
+ });
+
+ // Flutter can complete the first frame before the "show window" callback is
+ // registered. The following call ensures a frame is pending to ensure the
+ // window is shown. It is a no-op if the first frame hasn't completed yet.
+ flutter_controller_->ForceRedraw();
+
+ return true;
+}
+
+void FlutterWindow::OnDestroy() {
+ if (flutter_controller_) {
+ flutter_controller_ = nullptr;
+ }
+
+ Win32Window::OnDestroy();
+}
+
+LRESULT
+FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
+ WPARAM const wparam,
+ LPARAM const lparam) noexcept {
+ // Give Flutter, including plugins, an opportunity to handle window messages.
+ if (flutter_controller_) {
+ std::optional result =
+ flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
+ lparam);
+ if (result) {
+ return *result;
+ }
+ }
+
+ switch (message) {
+ case WM_FONTCHANGE:
+ flutter_controller_->engine()->ReloadSystemFonts();
+ break;
+ }
+
+ return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
+}
diff --git a/flutter_inappwebview/example/windows/runner/flutter_window.h b/flutter_inappwebview/example/windows/runner/flutter_window.h
new file mode 100644
index 000000000..6da0652f0
--- /dev/null
+++ b/flutter_inappwebview/example/windows/runner/flutter_window.h
@@ -0,0 +1,33 @@
+#ifndef RUNNER_FLUTTER_WINDOW_H_
+#define RUNNER_FLUTTER_WINDOW_H_
+
+#include
+#include
+
+#include
+
+#include "win32_window.h"
+
+// A window that does nothing but host a Flutter view.
+class FlutterWindow : public Win32Window {
+ public:
+ // Creates a new FlutterWindow hosting a Flutter view running |project|.
+ explicit FlutterWindow(const flutter::DartProject& project);
+ virtual ~FlutterWindow();
+
+ protected:
+ // Win32Window:
+ bool OnCreate() override;
+ void OnDestroy() override;
+ LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam,
+ LPARAM const lparam) noexcept override;
+
+ private:
+ // The project to run.
+ flutter::DartProject project_;
+
+ // The Flutter instance hosted by this window.
+ std::unique_ptr flutter_controller_;
+};
+
+#endif // RUNNER_FLUTTER_WINDOW_H_
diff --git a/flutter_inappwebview/example/windows/runner/main.cpp b/flutter_inappwebview/example/windows/runner/main.cpp
new file mode 100644
index 000000000..a61bf80d3
--- /dev/null
+++ b/flutter_inappwebview/example/windows/runner/main.cpp
@@ -0,0 +1,43 @@
+#include
+#include
+#include
+
+#include "flutter_window.h"
+#include "utils.h"
+
+int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
+ _In_ wchar_t *command_line, _In_ int show_command) {
+ // Attach to console when present (e.g., 'flutter run') or create a
+ // new console when running with a debugger.
+ if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
+ CreateAndAttachConsole();
+ }
+
+ // Initialize COM, so that it is available for use in the library and/or
+ // plugins.
+ ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
+
+ flutter::DartProject project(L"data");
+
+ std::vector command_line_arguments =
+ GetCommandLineArguments();
+
+ project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
+
+ FlutterWindow window(project);
+ Win32Window::Point origin(10, 10);
+ Win32Window::Size size(1280, 720);
+ if (!window.Create(L"example", origin, size)) {
+ return EXIT_FAILURE;
+ }
+ window.SetQuitOnClose(true);
+
+ ::MSG msg;
+ while (::GetMessage(&msg, nullptr, 0, 0)) {
+ ::TranslateMessage(&msg);
+ ::DispatchMessage(&msg);
+ }
+
+ ::CoUninitialize();
+ return EXIT_SUCCESS;
+}
diff --git a/flutter_inappwebview/example/windows/runner/resource.h b/flutter_inappwebview/example/windows/runner/resource.h
new file mode 100644
index 000000000..66a65d1e4
--- /dev/null
+++ b/flutter_inappwebview/example/windows/runner/resource.h
@@ -0,0 +1,16 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Runner.rc
+//
+#define IDI_APP_ICON 101
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 102
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/flutter_inappwebview/example/windows/runner/resources/app_icon.ico b/flutter_inappwebview/example/windows/runner/resources/app_icon.ico
new file mode 100644
index 000000000..c04e20caf
Binary files /dev/null and b/flutter_inappwebview/example/windows/runner/resources/app_icon.ico differ
diff --git a/flutter_inappwebview/example/windows/runner/runner.exe.manifest b/flutter_inappwebview/example/windows/runner/runner.exe.manifest
new file mode 100644
index 000000000..a42ea7687
--- /dev/null
+++ b/flutter_inappwebview/example/windows/runner/runner.exe.manifest
@@ -0,0 +1,20 @@
+
+
+
+
+ PerMonitorV2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/flutter_inappwebview/example/windows/runner/utils.cpp b/flutter_inappwebview/example/windows/runner/utils.cpp
new file mode 100644
index 000000000..b2b08734d
--- /dev/null
+++ b/flutter_inappwebview/example/windows/runner/utils.cpp
@@ -0,0 +1,65 @@
+#include "utils.h"
+
+#include
+#include
+#include
+#include
+
+#include
+
+void CreateAndAttachConsole() {
+ if (::AllocConsole()) {
+ FILE *unused;
+ if (freopen_s(&unused, "CONOUT$", "w", stdout)) {
+ _dup2(_fileno(stdout), 1);
+ }
+ if (freopen_s(&unused, "CONOUT$", "w", stderr)) {
+ _dup2(_fileno(stdout), 2);
+ }
+ std::ios::sync_with_stdio();
+ FlutterDesktopResyncOutputStreams();
+ }
+}
+
+std::vector GetCommandLineArguments() {
+ // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use.
+ int argc;
+ wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
+ if (argv == nullptr) {
+ return std::vector();
+ }
+
+ std::vector command_line_arguments;
+
+ // Skip the first argument as it's the binary name.
+ for (int i = 1; i < argc; i++) {
+ command_line_arguments.push_back(Utf8FromUtf16(argv[i]));
+ }
+
+ ::LocalFree(argv);
+
+ return command_line_arguments;
+}
+
+std::string Utf8FromUtf16(const wchar_t* utf16_string) {
+ if (utf16_string == nullptr) {
+ return std::string();
+ }
+ int target_length = ::WideCharToMultiByte(
+ CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
+ -1, nullptr, 0, nullptr, nullptr)
+ -1; // remove the trailing null character
+ int input_length = (int)wcslen(utf16_string);
+ std::string utf8_string;
+ if (target_length <= 0 || target_length > utf8_string.max_size()) {
+ return utf8_string;
+ }
+ utf8_string.resize(target_length);
+ int converted_length = ::WideCharToMultiByte(
+ CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
+ input_length, utf8_string.data(), target_length, nullptr, nullptr);
+ if (converted_length == 0) {
+ return std::string();
+ }
+ return utf8_string;
+}
diff --git a/flutter_inappwebview/example/windows/runner/utils.h b/flutter_inappwebview/example/windows/runner/utils.h
new file mode 100644
index 000000000..3879d5475
--- /dev/null
+++ b/flutter_inappwebview/example/windows/runner/utils.h
@@ -0,0 +1,19 @@
+#ifndef RUNNER_UTILS_H_
+#define RUNNER_UTILS_H_
+
+#include
+#include
+
+// Creates a console for the process, and redirects stdout and stderr to
+// it for both the runner and the Flutter library.
+void CreateAndAttachConsole();
+
+// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string
+// encoded in UTF-8. Returns an empty std::string on failure.
+std::string Utf8FromUtf16(const wchar_t* utf16_string);
+
+// Gets the command line arguments passed in as a std::vector,
+// encoded in UTF-8. Returns an empty std::vector on failure.
+std::vector GetCommandLineArguments();
+
+#endif // RUNNER_UTILS_H_
diff --git a/flutter_inappwebview/example/windows/runner/win32_window.cpp b/flutter_inappwebview/example/windows/runner/win32_window.cpp
new file mode 100644
index 000000000..786879fac
--- /dev/null
+++ b/flutter_inappwebview/example/windows/runner/win32_window.cpp
@@ -0,0 +1,309 @@
+#include "win32_window.h"
+
+#include
+#include
+
+#include "resource.h"
+
+namespace {
+
+ /// Window attribute that enables dark mode window decorations.
+ ///
+ /// Redefined in case the developer's machine has a Windows SDK older than
+ /// version 10.0.22000.0.
+ /// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute
+#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
+#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
+#endif
+
+ constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW";
+
+ /// Registry key for app theme preference.
+ ///
+ /// A value of 0 indicates apps should use dark mode. A non-zero or missing
+ /// value indicates apps should use light mode.
+ constexpr const wchar_t kGetPreferredBrightnessRegKey[] =
+ L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize";
+ constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme";
+
+ // The number of Win32Window objects that currently exist.
+ static int g_active_window_count = 0;
+
+ using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd);
+
+ // Scale helper to convert logical scaler values to physical using passed in
+ // scale factor
+ int Scale(int source, double scale_factor)
+ {
+ return static_cast(source * scale_factor);
+ }
+
+ // Dynamically loads the |EnableNonClientDpiScaling| from the User32 module.
+ // This API is only needed for PerMonitor V1 awareness mode.
+ void EnableFullDpiSupportIfAvailable(HWND hwnd)
+ {
+ HMODULE user32_module = LoadLibraryA("User32.dll");
+ if (!user32_module) {
+ return;
+ }
+ auto enable_non_client_dpi_scaling =
+ reinterpret_cast(
+ GetProcAddress(user32_module, "EnableNonClientDpiScaling"));
+ if (enable_non_client_dpi_scaling != nullptr) {
+ enable_non_client_dpi_scaling(hwnd);
+ }
+ FreeLibrary(user32_module);
+ }
+
+} // namespace
+
+// Manages the Win32Window's window class registration.
+class WindowClassRegistrar {
+public:
+ ~WindowClassRegistrar() = default;
+
+ // Returns the singleton registrar instance.
+ static WindowClassRegistrar* GetInstance()
+ {
+ if (!instance_) {
+ instance_ = new WindowClassRegistrar();
+ }
+ return instance_;
+ }
+
+ // Returns the name of the window class, registering the class if it hasn't
+ // previously been registered.
+ const wchar_t* GetWindowClass();
+
+ // Unregisters the window class. Should only be called if there are no
+ // instances of the window.
+ void UnregisterWindowClass();
+
+private:
+ WindowClassRegistrar() = default;
+
+ static WindowClassRegistrar* instance_;
+
+ bool class_registered_ = false;
+};
+
+WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr;
+
+const wchar_t* WindowClassRegistrar::GetWindowClass()
+{
+ if (!class_registered_) {
+ WNDCLASS window_class{};
+ window_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
+ window_class.lpszClassName = kWindowClassName;
+ window_class.style = CS_HREDRAW | CS_VREDRAW;
+ window_class.cbClsExtra = 0;
+ window_class.cbWndExtra = 0;
+ window_class.hInstance = GetModuleHandle(nullptr);
+ window_class.hIcon =
+ LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON));
+ window_class.hbrBackground = 0;
+ window_class.lpszMenuName = nullptr;
+ window_class.lpfnWndProc = Win32Window::WndProc;
+ RegisterClass(&window_class);
+ class_registered_ = true;
+ }
+ return kWindowClassName;
+}
+
+void WindowClassRegistrar::UnregisterWindowClass()
+{
+ UnregisterClass(kWindowClassName, nullptr);
+ class_registered_ = false;
+}
+
+Win32Window::Win32Window()
+{
+ ++g_active_window_count;
+}
+
+Win32Window::~Win32Window()
+{
+ --g_active_window_count;
+ Destroy();
+}
+
+bool Win32Window::Create(const std::wstring& title,
+ const Point& origin,
+ const Size& size)
+{
+ Destroy();
+
+ const wchar_t* window_class =
+ WindowClassRegistrar::GetInstance()->GetWindowClass();
+
+ const POINT target_point = { static_cast(origin.x),
+ static_cast(origin.y) };
+ HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST);
+ UINT dpi = FlutterDesktopGetDpiForMonitor(monitor);
+ double scale_factor = dpi / 96.0;
+
+ HWND window = CreateWindow(
+ window_class, title.c_str(), WS_OVERLAPPEDWINDOW,
+ Scale(origin.x, scale_factor), Scale(origin.y, scale_factor),
+ Scale(size.width, scale_factor), Scale(size.height, scale_factor),
+ nullptr, nullptr, GetModuleHandle(nullptr), this);
+
+ if (!window) {
+ return false;
+ }
+
+ UpdateTheme(window);
+
+ return OnCreate();
+}
+
+bool Win32Window::Show()
+{
+ return ShowWindow(window_handle_, SW_SHOWNORMAL);
+}
+
+// static
+LRESULT CALLBACK Win32Window::WndProc(HWND const window,
+ UINT const message,
+ WPARAM const wparam,
+ LPARAM const lparam) noexcept
+{
+ if (message == WM_NCCREATE) {
+ auto window_struct = reinterpret_cast(lparam);
+ SetWindowLongPtr(window, GWLP_USERDATA,
+ reinterpret_cast(window_struct->lpCreateParams));
+
+ auto that = static_cast(window_struct->lpCreateParams);
+ EnableFullDpiSupportIfAvailable(window);
+ that->window_handle_ = window;
+ }
+ else if (Win32Window* that = GetThisFromHandle(window)) {
+ return that->MessageHandler(window, message, wparam, lparam);
+ }
+
+ return DefWindowProc(window, message, wparam, lparam);
+}
+
+LRESULT
+Win32Window::MessageHandler(HWND hwnd,
+ UINT const message,
+ WPARAM const wparam,
+ LPARAM const lparam) noexcept
+{
+ switch (message) {
+ case WM_DESTROY:
+ window_handle_ = nullptr;
+ Destroy();
+ if (quit_on_close_) {
+ PostQuitMessage(0);
+ }
+ return 0;
+
+ case WM_DPICHANGED: {
+ auto newRectSize = reinterpret_cast(lparam);
+ LONG newWidth = newRectSize->right - newRectSize->left;
+ LONG newHeight = newRectSize->bottom - newRectSize->top;
+
+ SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth,
+ newHeight, SWP_NOZORDER | SWP_NOACTIVATE);
+
+ return 0;
+ }
+ case WM_SIZE: {
+ RECT rect = GetClientArea();
+ if (child_content_ != nullptr) {
+ // Size and position the child window.
+ MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left,
+ rect.bottom - rect.top, TRUE);
+ }
+ return 0;
+ }
+
+ case WM_ACTIVATE:
+ if (child_content_ != nullptr) {
+ SetFocus(child_content_);
+ }
+ return 0;
+
+ case WM_DWMCOLORIZATIONCOLORCHANGED:
+ UpdateTheme(hwnd);
+ return 0;
+ }
+
+ return DefWindowProc(window_handle_, message, wparam, lparam);
+}
+
+void Win32Window::Destroy()
+{
+ OnDestroy();
+
+ if (window_handle_) {
+ DestroyWindow(window_handle_);
+ window_handle_ = nullptr;
+ }
+ if (g_active_window_count == 0) {
+ WindowClassRegistrar::GetInstance()->UnregisterWindowClass();
+ }
+}
+
+Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept
+{
+ return reinterpret_cast(
+ GetWindowLongPtr(window, GWLP_USERDATA));
+}
+
+void Win32Window::SetChildContent(HWND content)
+{
+ child_content_ = content;
+ SetParent(content, window_handle_);
+ RECT frame = GetClientArea();
+
+ MoveWindow(content, frame.left, frame.top, frame.right - frame.left,
+ frame.bottom - frame.top, true);
+
+ SetFocus(child_content_);
+}
+
+RECT Win32Window::GetClientArea()
+{
+ RECT frame;
+ GetClientRect(window_handle_, &frame);
+ return frame;
+}
+
+HWND Win32Window::GetHandle()
+{
+ return window_handle_;
+}
+
+void Win32Window::SetQuitOnClose(bool quit_on_close)
+{
+ quit_on_close_ = quit_on_close;
+}
+
+bool Win32Window::OnCreate()
+{
+ // No-op; provided for subclasses.
+ return true;
+}
+
+void Win32Window::OnDestroy()
+{
+ // No-op; provided for subclasses.
+}
+
+void Win32Window::UpdateTheme(HWND const window)
+{
+ DWORD light_mode;
+ DWORD light_mode_size = sizeof(light_mode);
+ LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey,
+ kGetPreferredBrightnessRegValue,
+ RRF_RT_REG_DWORD, nullptr, &light_mode,
+ &light_mode_size);
+
+ if (result == ERROR_SUCCESS) {
+ BOOL enable_dark_mode = light_mode == 0;
+ DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE,
+ &enable_dark_mode, sizeof(enable_dark_mode));
+ }
+}
diff --git a/flutter_inappwebview/example/windows/runner/win32_window.h b/flutter_inappwebview/example/windows/runner/win32_window.h
new file mode 100644
index 000000000..e901dde68
--- /dev/null
+++ b/flutter_inappwebview/example/windows/runner/win32_window.h
@@ -0,0 +1,102 @@
+#ifndef RUNNER_WIN32_WINDOW_H_
+#define RUNNER_WIN32_WINDOW_H_
+
+#include
+
+#include
+#include
+#include
+
+// A class abstraction for a high DPI-aware Win32 Window. Intended to be
+// inherited from by classes that wish to specialize with custom
+// rendering and input handling
+class Win32Window {
+ public:
+ struct Point {
+ unsigned int x;
+ unsigned int y;
+ Point(unsigned int x, unsigned int y) : x(x), y(y) {}
+ };
+
+ struct Size {
+ unsigned int width;
+ unsigned int height;
+ Size(unsigned int width, unsigned int height)
+ : width(width), height(height) {}
+ };
+
+ Win32Window();
+ virtual ~Win32Window();
+
+ // Creates a win32 window with |title| that is positioned and sized using
+ // |origin| and |size|. New windows are created on the default monitor. Window
+ // sizes are specified to the OS in physical pixels, hence to ensure a
+ // consistent size this function will scale the inputted width and height as
+ // as appropriate for the default monitor. The window is invisible until
+ // |Show| is called. Returns true if the window was created successfully.
+ bool Create(const std::wstring& title, const Point& origin, const Size& size);
+
+ // Show the current window. Returns true if the window was successfully shown.
+ bool Show();
+
+ // Release OS resources associated with window.
+ void Destroy();
+
+ // Inserts |content| into the window tree.
+ void SetChildContent(HWND content);
+
+ // Returns the backing Window handle to enable clients to set icon and other
+ // window properties. Returns nullptr if the window has been destroyed.
+ HWND GetHandle();
+
+ // If true, closing this window will quit the application.
+ void SetQuitOnClose(bool quit_on_close);
+
+ // Return a RECT representing the bounds of the current client area.
+ RECT GetClientArea();
+
+ protected:
+ // Processes and route salient window messages for mouse handling,
+ // size change and DPI. Delegates handling of these to member overloads that
+ // inheriting classes can handle.
+ virtual LRESULT MessageHandler(HWND window,
+ UINT const message,
+ WPARAM const wparam,
+ LPARAM const lparam) noexcept;
+
+ // Called when CreateAndShow is called, allowing subclass window-related
+ // setup. Subclasses should return false if setup fails.
+ virtual bool OnCreate();
+
+ // Called when Destroy is called.
+ virtual void OnDestroy();
+
+ private:
+ friend class WindowClassRegistrar;
+
+ // OS callback called by message pump. Handles the WM_NCCREATE message which
+ // is passed when the non-client area is being created and enables automatic
+ // non-client DPI scaling so that the non-client area automatically
+ // responds to changes in DPI. All other messages are handled by
+ // MessageHandler.
+ static LRESULT CALLBACK WndProc(HWND const window,
+ UINT const message,
+ WPARAM const wparam,
+ LPARAM const lparam) noexcept;
+
+ // Retrieves a class instance pointer for |window|
+ static Win32Window* GetThisFromHandle(HWND const window) noexcept;
+
+ // Update the window frame's theme to match the system theme.
+ static void UpdateTheme(HWND const window);
+
+ bool quit_on_close_ = false;
+
+ // window handle for top level window.
+ HWND window_handle_ = nullptr;
+
+ // window handle for hosted content.
+ HWND child_content_ = nullptr;
+};
+
+#endif // RUNNER_WIN32_WINDOW_H_
diff --git a/flutter_inappwebview/lib/src/cookie_manager.dart b/flutter_inappwebview/lib/src/cookie_manager.dart
index 19afa2777..bebf0f303 100755
--- a/flutter_inappwebview/lib/src/cookie_manager.dart
+++ b/flutter_inappwebview/lib/src/cookie_manager.dart
@@ -3,6 +3,7 @@ import 'dart:async';
import 'package:flutter_inappwebview_platform_interface/flutter_inappwebview_platform_interface.dart';
import 'in_app_webview/in_app_webview_controller.dart';
+import 'webview_environment/webview_environment.dart';
///{@macro flutter_inappwebview_platform_interface.PlatformCookieManager}
class CookieManager {
@@ -31,12 +32,22 @@ class CookieManager {
static CookieManager? _instance;
+ WebViewEnvironment? _webViewEnvironment;
+
///Gets the [CookieManager] shared instance.
- static CookieManager instance() {
- if (_instance == null) {
- _instance = CookieManager();
+ ///
+ ///[webViewEnvironment] (Supported only on Windows) - Used to create the [CookieManager] using the specified environment.
+ static CookieManager instance({WebViewEnvironment? webViewEnvironment}) {
+ if (webViewEnvironment == null) {
+ if (_instance == null) {
+ _instance = CookieManager();
+ }
+ return _instance!;
+ } else {
+ return CookieManager.fromPlatformCreationParams(
+ PlatformCookieManagerCreationParams(
+ webViewEnvironment: webViewEnvironment.platform));
}
- return _instance!;
}
///{@macro flutter_inappwebview_platform_interface.PlatformCookieManager.setCookie}
@@ -132,6 +143,9 @@ class CookieManager {
///{@macro flutter_inappwebview_platform_interface.PlatformCookieManager.removeSessionCookies}
Future removeSessionCookies() => platform.removeSessionCookies();
+
+ ///{@macro flutter_inappwebview_platform_interface.PlatformCookieManager.flush}
+ Future flush() => platform.flush();
}
///Class that contains only iOS-specific methods of [CookieManager].
diff --git a/flutter_inappwebview/lib/src/in_app_browser/in_app_browser.dart b/flutter_inappwebview/lib/src/in_app_browser/in_app_browser.dart
index 3393cafd6..dbaeb6d63 100755
--- a/flutter_inappwebview/lib/src/in_app_browser/in_app_browser.dart
+++ b/flutter_inappwebview/lib/src/in_app_browser/in_app_browser.dart
@@ -11,25 +11,29 @@ import '../find_interaction/find_interaction_controller.dart';
import '../pull_to_refresh/main.dart';
import '../in_app_webview/in_app_webview_controller.dart';
+import '../webview_environment/webview_environment.dart';
///{@macro flutter_inappwebview_platform_interface.PlatformInAppBrowser}
class InAppBrowser implements PlatformInAppBrowserEvents {
/// Constructs a [InAppBrowser].
///
/// {@macro flutter_inappwebview_platform_interface.PlatformInAppBrowser}
- InAppBrowser(
- {ContextMenu? contextMenu,
- PullToRefreshController? pullToRefreshController,
- FindInteractionController? findInteractionController,
- UnmodifiableListView? initialUserScripts,
- int? windowId})
- : this.fromPlatformCreationParams(
+ InAppBrowser({
+ ContextMenu? contextMenu,
+ PullToRefreshController? pullToRefreshController,
+ FindInteractionController? findInteractionController,
+ UnmodifiableListView? initialUserScripts,
+ int? windowId,
+ WebViewEnvironment? webViewEnvironment,
+ }) : this.fromPlatformCreationParams(
PlatformInAppBrowserCreationParams(
- contextMenu: contextMenu,
- pullToRefreshController: pullToRefreshController?.platform,
- findInteractionController: findInteractionController?.platform,
- initialUserScripts: initialUserScripts,
- windowId: windowId),
+ contextMenu: contextMenu,
+ pullToRefreshController: pullToRefreshController?.platform,
+ findInteractionController: findInteractionController?.platform,
+ initialUserScripts: initialUserScripts,
+ windowId: windowId,
+ webViewEnvironment: webViewEnvironment?.platform,
+ ),
);
/// Constructs a [InAppBrowser] from creation params for a specific
@@ -195,96 +199,133 @@ class InAppBrowser implements PlatformInAppBrowserEvents {
@mustCallSuper
void dispose() => platform.dispose();
+ ///Use [onFormResubmission] instead.
+ @Deprecated('Use onFormResubmission instead')
@override
- Future? androidOnFormResubmission(Uri? url) {
+ FutureOr? androidOnFormResubmission(Uri? url) {
return null;
}
+ ///Use [onGeolocationPermissionsHidePrompt] instead.
+ @Deprecated("Use onGeolocationPermissionsHidePrompt instead")
@override
void androidOnGeolocationPermissionsHidePrompt() {}
+ ///Use [onGeolocationPermissionsShowPrompt] instead.
+ @Deprecated("Use onGeolocationPermissionsShowPrompt instead")
@override
- Future?
+ FutureOr?
androidOnGeolocationPermissionsShowPrompt(String origin) {
return null;
}
+ ///Use [onJsBeforeUnload] instead.
+ @Deprecated('Use onJsBeforeUnload instead')
@override
- Future? androidOnJsBeforeUnload(
+ FutureOr? androidOnJsBeforeUnload(
JsBeforeUnloadRequest jsBeforeUnloadRequest) {
return null;
}
+ ///Use [onPermissionRequest] instead.
+ @Deprecated("Use onPermissionRequest instead")
@override
- Future? androidOnPermissionRequest(
+ FutureOr? androidOnPermissionRequest(
String origin, List resources) {
return null;
}
+ ///Use [onReceivedIcon] instead.
+ @Deprecated('Use onReceivedIcon instead')
@override
void androidOnReceivedIcon(Uint8List icon) {}
+ ///Use [onReceivedLoginRequest] instead.
+ @Deprecated('Use onReceivedLoginRequest instead')
@override
void androidOnReceivedLoginRequest(LoginRequest loginRequest) {}
+ ///Use [onReceivedTouchIconUrl] instead.
+ @Deprecated('Use onReceivedTouchIconUrl instead')
@override
void androidOnReceivedTouchIconUrl(Uri url, bool precomposed) {}
+ ///Use [onRenderProcessGone] instead.
+ @Deprecated("Use onRenderProcessGone instead")
@override
void androidOnRenderProcessGone(RenderProcessGoneDetail detail) {}
+ ///Use [onRenderProcessResponsive] instead.
+ @Deprecated("Use onRenderProcessResponsive instead")
@override
- Future? androidOnRenderProcessResponsive(
+ FutureOr? androidOnRenderProcessResponsive(
Uri? url) {
return null;
}
+ ///Use [onRenderProcessUnresponsive] instead.
+ @Deprecated("Use onRenderProcessUnresponsive instead")
@override
- Future? androidOnRenderProcessUnresponsive(
+ FutureOr? androidOnRenderProcessUnresponsive(
Uri? url) {
return null;
}
+ ///Use [onSafeBrowsingHit] instead.
+ @Deprecated("Use onSafeBrowsingHit instead")
@override
- Future? androidOnSafeBrowsingHit(
+ FutureOr? androidOnSafeBrowsingHit(
Uri url, SafeBrowsingThreat? threatType) {
return null;
}
+ ///Use [onZoomScaleChanged] instead.
+ @Deprecated('Use onZoomScaleChanged instead')
@override
void androidOnScaleChanged(double oldScale, double newScale) {}
+ ///Use [shouldInterceptRequest] instead.
+ @Deprecated("Use shouldInterceptRequest instead")
@override
- Future? androidShouldInterceptRequest(
+ FutureOr? androidShouldInterceptRequest(
WebResourceRequest request) {
return null;
}
+ ///Use [onDidReceiveServerRedirectForProvisionalNavigation] instead.
+ @Deprecated('Use onDidReceiveServerRedirectForProvisionalNavigation instead')
@override
void iosOnDidReceiveServerRedirectForProvisionalNavigation() {}
+ ///Use [onNavigationResponse] instead.
+ @Deprecated('Use onNavigationResponse instead')
@override
- Future? iosOnNavigationResponse(
+ FutureOr? iosOnNavigationResponse(
IOSWKNavigationResponse navigationResponse) {
return null;
}
+ ///Use [onWebContentProcessDidTerminate] instead.
+ @Deprecated('Use onWebContentProcessDidTerminate instead')
@override
void iosOnWebContentProcessDidTerminate() {}
+ ///Use [shouldAllowDeprecatedTLS] instead.
+ @Deprecated('Use shouldAllowDeprecatedTLS instead')
@override
- Future? iosShouldAllowDeprecatedTLS(
+ FutureOr? iosShouldAllowDeprecatedTLS(
URLAuthenticationChallenge challenge) {
return null;
}
@override
- Future? onAjaxProgress(AjaxRequest ajaxRequest) {
+ FutureOr? onAjaxProgress(AjaxRequest ajaxRequest) {
return null;
}
@override
- Future? onAjaxReadyStateChange(AjaxRequest ajaxRequest) {
+ FutureOr? onAjaxReadyStateChange(
+ AjaxRequest ajaxRequest) {
return null;
}
@@ -305,19 +346,29 @@ class InAppBrowser implements PlatformInAppBrowserEvents {
void onContentSizeChanged(Size oldContentSize, Size newContentSize) {}
@override
- Future? onCreateWindow(CreateWindowAction createWindowAction) {
+ FutureOr? onCreateWindow(CreateWindowAction createWindowAction) {
return null;
}
@override
void onDidReceiveServerRedirectForProvisionalNavigation() {}
+ ///Use [onDownloadStarting] instead
+ @Deprecated('Use onDownloadStarting instead')
@override
void onDownloadStart(Uri url) {}
+ ///Use [onDownloadStarting] instead
+ @Deprecated('Use onDownloadStarting instead')
@override
void onDownloadStartRequest(DownloadStartRequest downloadStartRequest) {}
+ @override
+ FutureOr? onDownloadStarting(
+ DownloadStartRequest downloadStartRequest) {
+ return null;
+ }
+
@override
void onEnterFullscreen() {}
@@ -327,12 +378,14 @@ class InAppBrowser implements PlatformInAppBrowserEvents {
@override
void onExitFullscreen() {}
+ ///Use [FindInteractionController.onFindResultReceived] instead.
+ @Deprecated('Use FindInteractionController.onFindResultReceived instead')
@override
void onFindResultReceived(
int activeMatchOrdinal, int numberOfMatches, bool isDoneCounting) {}
@override
- Future? onFormResubmission(WebUri? url) {
+ FutureOr? onFormResubmission(WebUri? url) {
return null;
}
@@ -340,48 +393,54 @@ class InAppBrowser implements PlatformInAppBrowserEvents {
void onGeolocationPermissionsHidePrompt() {}
@override
- Future?
+ FutureOr?
onGeolocationPermissionsShowPrompt(String origin) {
return null;
}
@override
- Future? onJsAlert(JsAlertRequest jsAlertRequest) {
+ FutureOr? onJsAlert(JsAlertRequest jsAlertRequest) {
return null;
}
@override
- Future? onJsBeforeUnload(
+ FutureOr? onJsBeforeUnload(
JsBeforeUnloadRequest jsBeforeUnloadRequest) {
return null;
}
@override
- Future? onJsConfirm(JsConfirmRequest jsConfirmRequest) {
+ FutureOr? onJsConfirm(JsConfirmRequest jsConfirmRequest) {
return null;
}
@override
- Future? onJsPrompt(JsPromptRequest jsPromptRequest) {
+ FutureOr? onJsPrompt(JsPromptRequest jsPromptRequest) {
return null;
}
+ ///Use [onReceivedError] instead.
+ @Deprecated("Use onReceivedError instead")
@override
void onLoadError(Uri? url, int code, String message) {}
+ ///Use [onReceivedHttpError] instead.
+ @Deprecated("Use onReceivedHttpError instead")
@override
void onLoadHttpError(Uri? url, int statusCode, String description) {}
@override
void onLoadResource(LoadedResource resource) {}
+ ///Use [onLoadResourceWithCustomScheme] instead.
+ @Deprecated('Use onLoadResourceWithCustomScheme instead')
@override
- Future? onLoadResourceCustomScheme(Uri url) {
+ FutureOr? onLoadResourceCustomScheme(Uri url) {
return null;
}
@override
- Future? onLoadResourceWithCustomScheme(
+ FutureOr? onLoadResourceWithCustomScheme(
WebResourceRequest request) {
return null;
}
@@ -400,7 +459,7 @@ class InAppBrowser implements PlatformInAppBrowserEvents {
MediaCaptureState? oldState, MediaCaptureState? newState) {}
@override
- Future? onNavigationResponse(
+ FutureOr? onNavigationResponse(
NavigationResponse navigationResponse) {
return null;
}
@@ -412,7 +471,7 @@ class InAppBrowser implements PlatformInAppBrowserEvents {
void onPageCommitVisible(WebUri? url) {}
@override
- Future? onPermissionRequest(
+ FutureOr? onPermissionRequest(
PermissionRequest permissionRequest) {
return null;
}
@@ -420,11 +479,13 @@ class InAppBrowser implements PlatformInAppBrowserEvents {
@override
void onPermissionRequestCanceled(PermissionRequest permissionRequest) {}
+ ///Use [onPrintRequest] instead
+ @Deprecated("Use onPrintRequest instead")
@override
void onPrint(Uri? url) {}
@override
- Future? onPrintRequest(
+ FutureOr? onPrintRequest(
WebUri? url, PlatformPrintJobController? printJobController) {
return null;
}
@@ -433,8 +494,8 @@ class InAppBrowser implements PlatformInAppBrowserEvents {
void onProgressChanged(int progress) {}
@override
- Future? onReceivedClientCertRequest(
- URLAuthenticationChallenge challenge) {
+ FutureOr? onReceivedClientCertRequest(
+ ClientCertChallenge challenge) {
return null;
}
@@ -442,8 +503,8 @@ class InAppBrowser implements PlatformInAppBrowserEvents {
void onReceivedError(WebResourceRequest request, WebResourceError error) {}
@override
- Future? onReceivedHttpAuthRequest(
- URLAuthenticationChallenge challenge) {
+ FutureOr? onReceivedHttpAuthRequest(
+ HttpAuthenticationChallenge challenge) {
return null;
}
@@ -458,8 +519,8 @@ class InAppBrowser implements PlatformInAppBrowserEvents {
void onReceivedLoginRequest(LoginRequest loginRequest) {}
@override
- Future? onReceivedServerTrustAuthRequest(
- URLAuthenticationChallenge challenge) {
+ FutureOr? onReceivedServerTrustAuthRequest(
+ ServerTrustChallenge challenge) {
return null;
}
@@ -470,12 +531,13 @@ class InAppBrowser implements PlatformInAppBrowserEvents {
void onRenderProcessGone(RenderProcessGoneDetail detail) {}
@override
- Future? onRenderProcessResponsive(WebUri? url) {
+ FutureOr? onRenderProcessResponsive(
+ WebUri? url) {
return null;
}
@override
- Future? onRenderProcessUnresponsive(
+ FutureOr? onRenderProcessUnresponsive(
WebUri? url) {
return null;
}
@@ -484,7 +546,7 @@ class InAppBrowser implements PlatformInAppBrowserEvents {
void onRequestFocus() {}
@override
- Future? onSafeBrowsingHit(
+ FutureOr? onSafeBrowsingHit(
WebUri url, SafeBrowsingThreat? threatType) {
return null;
}
@@ -511,34 +573,45 @@ class InAppBrowser implements PlatformInAppBrowserEvents {
void onZoomScaleChanged(double oldScale, double newScale) {}
@override
- Future? shouldAllowDeprecatedTLS(
+ FutureOr? shouldAllowDeprecatedTLS(
URLAuthenticationChallenge challenge) {
return null;
}
@override
- Future? shouldInterceptAjaxRequest(AjaxRequest ajaxRequest) {
+ FutureOr? shouldInterceptAjaxRequest(AjaxRequest ajaxRequest) {
return null;
}
@override
- Future? shouldInterceptFetchRequest(
+ FutureOr? shouldInterceptFetchRequest(
FetchRequest fetchRequest) {
return null;
}
@override
- Future? shouldInterceptRequest(
+ FutureOr? shouldInterceptRequest(
WebResourceRequest request) {
return null;
}
@override
- Future? shouldOverrideUrlLoading(
+ FutureOr? shouldOverrideUrlLoading(
NavigationAction navigationAction) {
return null;
}
@override
void onMainWindowWillClose() {}
+
+ @override
+ void onProcessFailed(ProcessFailedDetail detail) {}
+
+ @override
+ void onAcceleratorKeyPressed(AcceleratorKeyPressedDetail detail) {}
+
+ @override
+ FutureOr onShowFileChooser(ShowFileChooserRequest request) {
+ return null;
+ }
}
diff --git a/flutter_inappwebview/lib/src/in_app_localhost_server.dart b/flutter_inappwebview/lib/src/in_app_localhost_server.dart
index daae11b7b..841f0cc29 100755
--- a/flutter_inappwebview/lib/src/in_app_localhost_server.dart
+++ b/flutter_inappwebview/lib/src/in_app_localhost_server.dart
@@ -1,4 +1,5 @@
import 'dart:async';
+import 'dart:io';
import 'package:flutter_inappwebview_platform_interface/flutter_inappwebview_platform_interface.dart';
///{@macro flutter_inappwebview_platform_interface.PlatformInAppLocalhostServer}
@@ -9,12 +10,14 @@ class InAppLocalhostServer {
String directoryIndex = 'index.html',
String documentRoot = './',
bool shared = false,
+ Future Function(HttpRequest request)? onData,
}) : this.fromPlatformCreationParams(
PlatformInAppLocalhostServerCreationParams(
port: port,
directoryIndex: directoryIndex,
documentRoot: documentRoot,
- shared: shared),
+ shared: shared,
+ onData: onData),
);
/// Constructs a [InAppLocalhostServer] from creation params for a specific
@@ -42,6 +45,9 @@ class InAppLocalhostServer {
///{@macro flutter_inappwebview_platform_interface.PlatformInAppLocalhostServer.shared}
bool get shared => platform.shared;
+ ///{@macro flutter_inappwebview_platform_interface.PlatformInAppLocalhostServer.onData}
+ Future Function(HttpRequest request)? get onData => platform.onData;
+
///{@macro flutter_inappwebview_platform_interface.PlatformInAppLocalhostServer.start}
Future start() => platform.start();
diff --git a/flutter_inappwebview/lib/src/in_app_webview/headless_in_app_webview.dart b/flutter_inappwebview/lib/src/in_app_webview/headless_in_app_webview.dart
index 5f714d677..252f3e5f8 100644
--- a/flutter_inappwebview/lib/src/in_app_webview/headless_in_app_webview.dart
+++ b/flutter_inappwebview/lib/src/in_app_webview/headless_in_app_webview.dart
@@ -1,12 +1,13 @@
+import 'dart:async';
import 'dart:collection';
-import 'dart:typed_data';
-import 'dart:ui';
import 'package:flutter/services.dart';
import 'package:flutter_inappwebview_platform_interface/flutter_inappwebview_platform_interface.dart';
+
import '../find_interaction/find_interaction_controller.dart';
-import 'in_app_webview_controller.dart';
import '../pull_to_refresh/pull_to_refresh_controller.dart';
+import '../webview_environment/webview_environment.dart';
+import 'in_app_webview_controller.dart';
///{@macro flutter_inappwebview_platform_interface.PlatformHeadlessInAppWebView}
class HeadlessInAppWebView {
@@ -36,263 +37,139 @@ class HeadlessInAppWebView {
platform: webViewControllerPlatform);
}
- HeadlessInAppWebView({
- Size initialSize = const Size(-1, -1),
- int? windowId,
- HeadlessInAppWebView? headlessWebView,
- InAppWebViewKeepAlive? keepAlive,
- bool? preventGestureDelay,
- @Deprecated('Use onGeolocationPermissionsHidePrompt instead')
- void Function(InAppWebViewController controller)?
- androidOnGeolocationPermissionsHidePrompt,
- @Deprecated('Use onGeolocationPermissionsShowPrompt instead')
- Future Function(
- InAppWebViewController controller, String origin)?
- androidOnGeolocationPermissionsShowPrompt,
- @Deprecated('Use onPermissionRequest instead')
- Future Function(
- InAppWebViewController controller,
- String origin,
- List resources)?
- androidOnPermissionRequest,
- @Deprecated('Use onSafeBrowsingHit instead')
- Future Function(InAppWebViewController controller,
- Uri url, SafeBrowsingThreat? threatType)?
- androidOnSafeBrowsingHit,
- InAppWebViewInitialData? initialData,
- String? initialFile,
- @Deprecated('Use initialSettings instead')
- InAppWebViewGroupOptions? initialOptions,
- InAppWebViewSettings? initialSettings,
- URLRequest? initialUrlRequest,
- UnmodifiableListView? initialUserScripts,
- PullToRefreshController? pullToRefreshController,
- FindInteractionController? findInteractionController,
- ContextMenu? contextMenu,
- void Function(InAppWebViewController controller, WebUri? url)?
- onPageCommitVisible,
- void Function(InAppWebViewController controller, String? title)?
- onTitleChanged,
- @Deprecated(
- 'Use onDidReceiveServerRedirectForProvisionalNavigation instead')
- void Function(InAppWebViewController controller)?
- iosOnDidReceiveServerRedirectForProvisionalNavigation,
- @Deprecated('Use onWebContentProcessDidTerminate instead')
- void Function(InAppWebViewController controller)?
- iosOnWebContentProcessDidTerminate,
- @Deprecated('Use onNavigationResponse instead')
- Future Function(
- InAppWebViewController controller,
- IOSWKNavigationResponse navigationResponse)?
- iosOnNavigationResponse,
- @Deprecated('Use shouldAllowDeprecatedTLS instead')
- Future Function(
- InAppWebViewController controller,
- URLAuthenticationChallenge challenge)?
- iosShouldAllowDeprecatedTLS,
- Future Function(
- InAppWebViewController controller, AjaxRequest ajaxRequest)?
- onAjaxProgress,
- Future Function(
- InAppWebViewController controller, AjaxRequest ajaxRequest)?
- onAjaxReadyStateChange,
- void Function(
- InAppWebViewController controller, ConsoleMessage consoleMessage)?
- onConsoleMessage,
- Future Function(InAppWebViewController controller,
- CreateWindowAction createWindowAction)?
- onCreateWindow,
- void Function(InAppWebViewController controller)? onCloseWindow,
- void Function(InAppWebViewController controller)? onWindowFocus,
- void Function(InAppWebViewController controller)? onWindowBlur,
- @Deprecated('Use onReceivedIcon instead')
- void Function(InAppWebViewController controller, Uint8List icon)?
- androidOnReceivedIcon,
- @Deprecated('Use onReceivedTouchIconUrl instead')
- void Function(InAppWebViewController controller, Uri url, bool precomposed)?
- androidOnReceivedTouchIconUrl,
- @Deprecated('Use onDownloadStartRequest instead')
- void Function(InAppWebViewController controller, Uri url)? onDownloadStart,
- void Function(InAppWebViewController controller,
- DownloadStartRequest downloadStartRequest)?
- onDownloadStartRequest,
- @Deprecated('Use FindInteractionController.onFindResultReceived instead')
- void Function(InAppWebViewController controller, int activeMatchOrdinal,
- int numberOfMatches, bool isDoneCounting)?
- onFindResultReceived,
- Future Function(
- InAppWebViewController controller, JsAlertRequest jsAlertRequest)?
- onJsAlert,
- Future Function(InAppWebViewController controller,
- JsConfirmRequest jsConfirmRequest)?
- onJsConfirm,
- Future Function(
- InAppWebViewController controller, JsPromptRequest jsPromptRequest)?
- onJsPrompt,
- @Deprecated("Use onReceivedError instead")
- void Function(InAppWebViewController controller, Uri? url, int code,
- String message)?
- onLoadError,
- void Function(InAppWebViewController controller, WebResourceRequest request,
- WebResourceError error)?
- onReceivedError,
- @Deprecated("Use onReceivedHttpError instead")
- void Function(InAppWebViewController controller, Uri? url, int statusCode,
- String description)?
- onLoadHttpError,
- void Function(InAppWebViewController controller, WebResourceRequest request,
- WebResourceResponse errorResponse)?
- onReceivedHttpError,
- void Function(InAppWebViewController controller, LoadedResource resource)?
- onLoadResource,
- @Deprecated('Use onLoadResourceWithCustomScheme instead')
- Future Function(
- InAppWebViewController controller, Uri url)?
- onLoadResourceCustomScheme,
- Future Function(
- InAppWebViewController controller, WebResourceRequest request)?
- onLoadResourceWithCustomScheme,
- void Function(InAppWebViewController controller, WebUri? url)? onLoadStart,
- void Function(InAppWebViewController controller, WebUri? url)? onLoadStop,
- void Function(InAppWebViewController controller,
- InAppWebViewHitTestResult hitTestResult)?
- onLongPressHitTestResult,
- @Deprecated("Use onPrintRequest instead")
- void Function(InAppWebViewController controller, Uri? url)? onPrint,
- Future Function(InAppWebViewController controller, WebUri? url,
- PlatformPrintJobController? printJobController)?
- onPrintRequest,
- void Function(InAppWebViewController controller, int progress)?
- onProgressChanged,
- Future Function(InAppWebViewController controller,
- URLAuthenticationChallenge challenge)?
- onReceivedClientCertRequest,
- Future Function(InAppWebViewController controller,
- URLAuthenticationChallenge challenge)?
- onReceivedHttpAuthRequest,
- Future Function(InAppWebViewController controller,
- URLAuthenticationChallenge challenge)?
- onReceivedServerTrustAuthRequest,
- void Function(InAppWebViewController controller, int x, int y)?
- onScrollChanged,
- void Function(
- InAppWebViewController controller, WebUri? url, bool? isReload)?
- onUpdateVisitedHistory,
- void Function(InAppWebViewController controller)? onWebViewCreated,
- Future Function(
- InAppWebViewController controller, AjaxRequest ajaxRequest)?
- shouldInterceptAjaxRequest,
- Future Function(
- InAppWebViewController controller, FetchRequest fetchRequest)?
- shouldInterceptFetchRequest,
- Future Function(InAppWebViewController controller,
- NavigationAction navigationAction)?
- shouldOverrideUrlLoading,
- void Function(InAppWebViewController controller)? onEnterFullscreen,
- void Function(InAppWebViewController controller)? onExitFullscreen,
- void Function(InAppWebViewController controller, int x, int y,
- bool clampedX, bool clampedY)?
- onOverScrolled,
- void Function(InAppWebViewController controller, double oldScale,
- double newScale)?
- onZoomScaleChanged,
- @Deprecated('Use shouldInterceptRequest instead')
- Future Function(
- InAppWebViewController controller, WebResourceRequest request)?
- androidShouldInterceptRequest,
- @Deprecated('Use onRenderProcessUnresponsive instead')
- Future Function(
- InAppWebViewController controller, Uri? url)?
- androidOnRenderProcessUnresponsive,
- @Deprecated('Use onRenderProcessResponsive instead')
- Future Function(
- InAppWebViewController controller, Uri? url)?
- androidOnRenderProcessResponsive,
- @Deprecated('Use onRenderProcessGone instead')
- void Function(
- InAppWebViewController controller, RenderProcessGoneDetail detail)?
- androidOnRenderProcessGone,
- @Deprecated('Use onFormResubmission instead')
- Future Function(
- InAppWebViewController controller, Uri? url)?
- androidOnFormResubmission,
- @Deprecated('Use onZoomScaleChanged instead')
- void Function(InAppWebViewController controller, double oldScale,
- double newScale)?
- androidOnScaleChanged,
- @Deprecated('Use onJsBeforeUnload instead')
- Future Function(InAppWebViewController controller,
- JsBeforeUnloadRequest jsBeforeUnloadRequest)?
- androidOnJsBeforeUnload,
- @Deprecated('Use onReceivedLoginRequest instead')
- void Function(InAppWebViewController controller, LoginRequest loginRequest)?
- androidOnReceivedLoginRequest,
- void Function(InAppWebViewController controller)?
- onDidReceiveServerRedirectForProvisionalNavigation,
- Future Function(
- InAppWebViewController controller, WebUri? url)?
- onFormResubmission,
- void Function(InAppWebViewController controller)?
- onGeolocationPermissionsHidePrompt,
- Future Function(
- InAppWebViewController controller, String origin)?
- onGeolocationPermissionsShowPrompt,
- Future Function(InAppWebViewController controller,
- JsBeforeUnloadRequest jsBeforeUnloadRequest)?
- onJsBeforeUnload,
- Future Function(
- InAppWebViewController controller,
- NavigationResponse navigationResponse)?
- onNavigationResponse,
- Future Function(InAppWebViewController controller,
- PermissionRequest permissionRequest)?
- onPermissionRequest,
- void Function(InAppWebViewController controller, Uint8List icon)?
- onReceivedIcon,
- void Function(InAppWebViewController controller, LoginRequest loginRequest)?
- onReceivedLoginRequest,
- void Function(InAppWebViewController controller,
- PermissionRequest permissionRequest)?
- onPermissionRequestCanceled,
- void Function(InAppWebViewController controller)? onRequestFocus,
- void Function(
- InAppWebViewController controller, WebUri url, bool precomposed)?
- onReceivedTouchIconUrl,
- void Function(
- InAppWebViewController controller, RenderProcessGoneDetail detail)?
- onRenderProcessGone,
- Future Function(
- InAppWebViewController controller, WebUri? url)?
- onRenderProcessResponsive,
- Future Function(
- InAppWebViewController controller, WebUri? url)?
- onRenderProcessUnresponsive,
- Future Function(InAppWebViewController controller,
- WebUri url, SafeBrowsingThreat? threatType)?
- onSafeBrowsingHit,
- void Function(InAppWebViewController controller)?
- onWebContentProcessDidTerminate,
- Future Function(
- InAppWebViewController controller,
- URLAuthenticationChallenge challenge)?
- shouldAllowDeprecatedTLS,
- Future Function(
- InAppWebViewController controller, WebResourceRequest request)?
- shouldInterceptRequest,
- Future Function(
- InAppWebViewController controller,
- MediaCaptureState? oldState,
- MediaCaptureState? newState,
- )? onCameraCaptureStateChanged,
- Future Function(
- InAppWebViewController controller,
- MediaCaptureState? oldState,
- MediaCaptureState? newState,
- )? onMicrophoneCaptureStateChanged,
- void Function(InAppWebViewController controller, Size oldContentSize,
- Size newContentSize)?
- onContentSizeChanged,
- }) : this.fromPlatformCreationParams(
+ HeadlessInAppWebView(
+ {Size initialSize = const Size(-1, -1),
+ int? windowId,
+ HeadlessInAppWebView? headlessWebView,
+ InAppWebViewKeepAlive? keepAlive,
+ bool? preventGestureDelay,
+ WebViewEnvironment? webViewEnvironment,
+ @Deprecated('Use onGeolocationPermissionsHidePrompt instead')
+ void Function(InAppWebViewController controller)?
+ androidOnGeolocationPermissionsHidePrompt,
+ @Deprecated('Use onGeolocationPermissionsShowPrompt instead')
+ FutureOr Function(
+ InAppWebViewController controller, String origin)?
+ androidOnGeolocationPermissionsShowPrompt,
+ @Deprecated('Use onPermissionRequest instead')
+ FutureOr Function(
+ InAppWebViewController controller,
+ String origin,
+ List resources)?
+ androidOnPermissionRequest,
+ @Deprecated('Use onSafeBrowsingHit instead')
+ FutureOr Function(
+ InAppWebViewController controller,
+ Uri url,
+ SafeBrowsingThreat? threatType)?
+ androidOnSafeBrowsingHit,
+ InAppWebViewInitialData? initialData,
+ String? initialFile,
+ @Deprecated('Use initialSettings instead')
+ InAppWebViewGroupOptions? initialOptions,
+ InAppWebViewSettings? initialSettings,
+ URLRequest? initialUrlRequest,
+ UnmodifiableListView? initialUserScripts,
+ PullToRefreshController? pullToRefreshController,
+ FindInteractionController? findInteractionController,
+ ContextMenu? contextMenu,
+ void Function(InAppWebViewController controller, WebUri? url)?
+ onPageCommitVisible,
+ void Function(InAppWebViewController controller, String? title)?
+ onTitleChanged,
+ @Deprecated('Use onDidReceiveServerRedirectForProvisionalNavigation instead')
+ void Function(InAppWebViewController controller)?
+ iosOnDidReceiveServerRedirectForProvisionalNavigation,
+ @Deprecated('Use onWebContentProcessDidTerminate instead')
+ void Function(InAppWebViewController controller)?
+ iosOnWebContentProcessDidTerminate,
+ @Deprecated('Use onNavigationResponse instead')
+ FutureOr Function(InAppWebViewController controller, IOSWKNavigationResponse navigationResponse)? iosOnNavigationResponse,
+ @Deprecated('Use shouldAllowDeprecatedTLS instead') FutureOr Function(InAppWebViewController controller, URLAuthenticationChallenge challenge)? iosShouldAllowDeprecatedTLS,
+ FutureOr Function(InAppWebViewController controller, AjaxRequest ajaxRequest)? onAjaxProgress,
+ FutureOr Function(InAppWebViewController controller, AjaxRequest ajaxRequest)? onAjaxReadyStateChange,
+ void Function(InAppWebViewController controller, ConsoleMessage consoleMessage)? onConsoleMessage,
+ FutureOr Function(InAppWebViewController controller, CreateWindowAction createWindowAction)? onCreateWindow,
+ void Function(InAppWebViewController controller)? onCloseWindow,
+ void Function(InAppWebViewController controller)? onWindowFocus,
+ void Function(InAppWebViewController controller)? onWindowBlur,
+ @Deprecated('Use onReceivedIcon instead') void Function(InAppWebViewController controller, Uint8List icon)? androidOnReceivedIcon,
+ @Deprecated('Use onReceivedTouchIconUrl instead') void Function(InAppWebViewController controller, Uri url, bool precomposed)? androidOnReceivedTouchIconUrl,
+ @Deprecated('Use onDownloadStarting instead') void Function(InAppWebViewController controller, Uri url)? onDownloadStart,
+ @Deprecated('Use onDownloadStarting instead') void Function(InAppWebViewController controller, DownloadStartRequest downloadStartRequest)? onDownloadStartRequest,
+ FutureOr Function(InAppWebViewController controller, DownloadStartRequest downloadStartRequest)? onDownloadStarting,
+ @Deprecated('Use FindInteractionController.onFindResultReceived instead') void Function(InAppWebViewController controller, int activeMatchOrdinal, int numberOfMatches, bool isDoneCounting)? onFindResultReceived,
+ FutureOr Function(InAppWebViewController controller, JsAlertRequest jsAlertRequest)? onJsAlert,
+ FutureOr Function(InAppWebViewController controller, JsConfirmRequest jsConfirmRequest)? onJsConfirm,
+ FutureOr Function(InAppWebViewController controller, JsPromptRequest jsPromptRequest)? onJsPrompt,
+ @Deprecated("Use onReceivedError instead") void Function(InAppWebViewController controller, Uri? url, int code, String message)? onLoadError,
+ void Function(InAppWebViewController controller, WebResourceRequest request, WebResourceError error)? onReceivedError,
+ @Deprecated("Use onReceivedHttpError instead") void Function(InAppWebViewController controller, Uri? url, int statusCode, String description)? onLoadHttpError,
+ void Function(InAppWebViewController controller, WebResourceRequest request, WebResourceResponse errorResponse)? onReceivedHttpError,
+ void Function(InAppWebViewController controller, LoadedResource resource)? onLoadResource,
+ @Deprecated('Use onLoadResourceWithCustomScheme instead') FutureOr Function(InAppWebViewController controller, Uri url)? onLoadResourceCustomScheme,
+ FutureOr Function(InAppWebViewController controller, WebResourceRequest request)? onLoadResourceWithCustomScheme,
+ void Function(InAppWebViewController controller, WebUri? url)? onLoadStart,
+ void Function(InAppWebViewController controller, WebUri? url)? onLoadStop,
+ void Function(InAppWebViewController controller, InAppWebViewHitTestResult hitTestResult)? onLongPressHitTestResult,
+ @Deprecated("Use onPrintRequest instead") void Function(InAppWebViewController controller, Uri? url)? onPrint,
+ FutureOr Function(InAppWebViewController controller, WebUri? url, PlatformPrintJobController? printJobController)? onPrintRequest,
+ void Function(InAppWebViewController controller, int progress)? onProgressChanged,
+ FutureOr Function(InAppWebViewController controller, ClientCertChallenge challenge)? onReceivedClientCertRequest,
+ FutureOr Function(InAppWebViewController controller, HttpAuthenticationChallenge challenge)? onReceivedHttpAuthRequest,
+ FutureOr Function(InAppWebViewController controller, ServerTrustChallenge challenge)? onReceivedServerTrustAuthRequest,
+ void Function(InAppWebViewController controller, int x, int y)? onScrollChanged,
+ void Function(InAppWebViewController controller, WebUri? url, bool? isReload)? onUpdateVisitedHistory,
+ void Function(InAppWebViewController controller)? onWebViewCreated,
+ FutureOr Function(InAppWebViewController controller, AjaxRequest ajaxRequest)? shouldInterceptAjaxRequest,
+ FutureOr Function(InAppWebViewController controller, FetchRequest fetchRequest)? shouldInterceptFetchRequest,
+ FutureOr Function(InAppWebViewController controller, NavigationAction navigationAction)? shouldOverrideUrlLoading,
+ void Function(InAppWebViewController controller)? onEnterFullscreen,
+ void Function(InAppWebViewController controller)? onExitFullscreen,
+ void Function(InAppWebViewController controller, int x, int y, bool clampedX, bool clampedY)? onOverScrolled,
+ void Function(InAppWebViewController controller, double oldScale, double newScale)? onZoomScaleChanged,
+ @Deprecated('Use shouldInterceptRequest instead') FutureOr Function(InAppWebViewController controller, WebResourceRequest request)? androidShouldInterceptRequest,
+ @Deprecated('Use onRenderProcessUnresponsive instead') FutureOr Function(InAppWebViewController controller, Uri? url)? androidOnRenderProcessUnresponsive,
+ @Deprecated('Use onRenderProcessResponsive instead') FutureOr Function(InAppWebViewController controller, Uri? url)? androidOnRenderProcessResponsive,
+ @Deprecated('Use onRenderProcessGone instead') void Function(InAppWebViewController controller, RenderProcessGoneDetail detail)? androidOnRenderProcessGone,
+ @Deprecated('Use onFormResubmission instead') FutureOr Function(InAppWebViewController controller, Uri? url)? androidOnFormResubmission,
+ @Deprecated('Use onZoomScaleChanged instead') void Function(InAppWebViewController controller, double oldScale, double newScale)? androidOnScaleChanged,
+ @Deprecated('Use onJsBeforeUnload instead') FutureOr Function(InAppWebViewController controller, JsBeforeUnloadRequest jsBeforeUnloadRequest)? androidOnJsBeforeUnload,
+ @Deprecated('Use onReceivedLoginRequest instead') void Function(InAppWebViewController controller, LoginRequest loginRequest)? androidOnReceivedLoginRequest,
+ void Function(InAppWebViewController controller)? onDidReceiveServerRedirectForProvisionalNavigation,
+ FutureOr Function(InAppWebViewController controller, WebUri? url)? onFormResubmission,
+ void Function(InAppWebViewController controller)? onGeolocationPermissionsHidePrompt,
+ FutureOr Function(InAppWebViewController controller, String origin)? onGeolocationPermissionsShowPrompt,
+ FutureOr Function(InAppWebViewController controller, JsBeforeUnloadRequest jsBeforeUnloadRequest)? onJsBeforeUnload,
+ FutureOr Function(InAppWebViewController controller, NavigationResponse navigationResponse)? onNavigationResponse,
+ FutureOr Function(InAppWebViewController controller, PermissionRequest permissionRequest)? onPermissionRequest,
+ void Function(InAppWebViewController controller, Uint8List icon)? onReceivedIcon,
+ void Function(InAppWebViewController controller, LoginRequest loginRequest)? onReceivedLoginRequest,
+ void Function(InAppWebViewController controller, PermissionRequest permissionRequest)? onPermissionRequestCanceled,
+ void Function(InAppWebViewController controller)? onRequestFocus,
+ void Function(InAppWebViewController controller, WebUri url, bool precomposed)? onReceivedTouchIconUrl,
+ void Function(InAppWebViewController controller, RenderProcessGoneDetail detail)? onRenderProcessGone,
+ FutureOr Function(InAppWebViewController controller, WebUri? url)? onRenderProcessResponsive,
+ FutureOr Function(InAppWebViewController controller, WebUri? url)? onRenderProcessUnresponsive,
+ FutureOr Function(InAppWebViewController controller, WebUri url, SafeBrowsingThreat? threatType)? onSafeBrowsingHit,
+ void Function(InAppWebViewController controller)? onWebContentProcessDidTerminate,
+ FutureOr Function(InAppWebViewController controller, URLAuthenticationChallenge challenge)? shouldAllowDeprecatedTLS,
+ FutureOr Function(InAppWebViewController controller, WebResourceRequest request)? shouldInterceptRequest,
+ FutureOr Function(
+ InAppWebViewController controller,
+ MediaCaptureState? oldState,
+ MediaCaptureState? newState,
+ )? onCameraCaptureStateChanged,
+ FutureOr Function(
+ InAppWebViewController controller,
+ MediaCaptureState? oldState,
+ MediaCaptureState? newState,
+ )? onMicrophoneCaptureStateChanged,
+ void Function(InAppWebViewController controller, Size oldContentSize, Size newContentSize)? onContentSizeChanged,
+ void Function(InAppWebViewController controller, ProcessFailedDetail detail)? onProcessFailed,
+ void Function(InAppWebViewController controller, AcceleratorKeyPressedDetail detail)? onAcceleratorKeyPressed,
+ FutureOr Function(InAppWebViewController controller, ShowFileChooserRequest request)? onShowFileChooser})
+ : this.fromPlatformCreationParams(
params: PlatformHeadlessInAppWebViewCreationParams(
controllerFromPlatform: (PlatformInAppWebViewController controller) =>
InAppWebViewController.fromPlatform(platform: controller),
@@ -307,6 +184,7 @@ class HeadlessInAppWebView {
pullToRefreshController: pullToRefreshController?.platform,
findInteractionController: findInteractionController?.platform,
contextMenu: contextMenu,
+ webViewEnvironment: webViewEnvironment?.platform,
onWebViewCreated: onWebViewCreated != null
? (controller) => onWebViewCreated.call(controller)
: null,
@@ -358,6 +236,10 @@ class HeadlessInAppWebView {
? (controller, downloadStartRequest) =>
onDownloadStartRequest.call(controller, downloadStartRequest)
: null,
+ onDownloadStarting: onDownloadStarting != null
+ ? (controller, downloadStartRequest) =>
+ onDownloadStarting.call(controller, downloadStartRequest)
+ : null,
onLoadResourceCustomScheme: onLoadResourceCustomScheme != null
? (controller, url) =>
onLoadResourceCustomScheme.call(controller, url)
@@ -633,6 +515,17 @@ class HeadlessInAppWebView {
onContentSizeChanged.call(
controller, oldContentSize, newContentSize)
: null,
+ onProcessFailed: onProcessFailed != null
+ ? (controller, detail) => onProcessFailed.call(controller, detail)
+ : null,
+ onAcceleratorKeyPressed: onAcceleratorKeyPressed != null
+ ? (controller, detail) =>
+ onAcceleratorKeyPressed.call(controller, detail)
+ : null,
+ onShowFileChooser: onShowFileChooser != null
+ ? (controller, request) =>
+ onShowFileChooser.call(controller, request)
+ : null,
));
///{@macro flutter_inappwebview_platform_interface.PlatformHeadlessInAppWebView.run}
diff --git a/flutter_inappwebview/lib/src/in_app_webview/in_app_webview.dart b/flutter_inappwebview/lib/src/in_app_webview/in_app_webview.dart
index e2490bfc3..6368630e7 100755
--- a/flutter_inappwebview/lib/src/in_app_webview/in_app_webview.dart
+++ b/flutter_inappwebview/lib/src/in_app_webview/in_app_webview.dart
@@ -1,19 +1,19 @@
import 'dart:async';
import 'dart:collection';
-import 'dart:typed_data';
import 'package:flutter/foundation.dart';
+import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
-import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
-import 'package:flutter/gestures.dart';
import 'package:flutter_inappwebview_platform_interface/flutter_inappwebview_platform_interface.dart';
-import 'headless_in_app_webview.dart';
-import 'in_app_webview_controller.dart';
+
import '../find_interaction/find_interaction_controller.dart';
import '../pull_to_refresh/main.dart';
import '../pull_to_refresh/pull_to_refresh_controller.dart';
+import '../webview_environment/webview_environment.dart';
+import 'headless_in_app_webview.dart';
+import 'in_app_webview_controller.dart';
///{@macro flutter_inappwebview_platform_interface.PlatformInAppWebViewWidget}
class InAppWebView extends StatefulWidget {
@@ -34,265 +34,141 @@ class InAppWebView extends StatefulWidget {
final PlatformInAppWebViewWidget platform;
///{@macro flutter_inappwebview_platform_interface.PlatformInAppWebViewWidget}
- InAppWebView({
- Key? key,
- Set>? gestureRecognizers,
- int? windowId,
- HeadlessInAppWebView? headlessWebView,
- InAppWebViewKeepAlive? keepAlive,
- bool? preventGestureDelay,
- TextDirection? layoutDirection,
- @Deprecated('Use onGeolocationPermissionsHidePrompt instead')
- void Function(InAppWebViewController controller)?
- androidOnGeolocationPermissionsHidePrompt,
- @Deprecated('Use onGeolocationPermissionsShowPrompt instead')
- Future Function(
- InAppWebViewController controller, String origin)?
- androidOnGeolocationPermissionsShowPrompt,
- @Deprecated('Use onPermissionRequest instead')
- Future Function(
- InAppWebViewController controller,
- String origin,
- List resources)?
- androidOnPermissionRequest,
- @Deprecated('Use onSafeBrowsingHit instead')
- Future Function(InAppWebViewController controller,
- Uri url, SafeBrowsingThreat? threatType)?
- androidOnSafeBrowsingHit,
- InAppWebViewInitialData? initialData,
- String? initialFile,
- @Deprecated('Use initialSettings instead')
- InAppWebViewGroupOptions? initialOptions,
- InAppWebViewSettings? initialSettings,
- URLRequest? initialUrlRequest,
- UnmodifiableListView? initialUserScripts,
- PullToRefreshController? pullToRefreshController,
- FindInteractionController? findInteractionController,
- ContextMenu? contextMenu,
- void Function(InAppWebViewController controller, WebUri? url)?
- onPageCommitVisible,
- void Function(InAppWebViewController controller, String? title)?
- onTitleChanged,
- @Deprecated(
- 'Use onDidReceiveServerRedirectForProvisionalNavigation instead')
- void Function(InAppWebViewController controller)?
- iosOnDidReceiveServerRedirectForProvisionalNavigation,
- @Deprecated('Use onWebContentProcessDidTerminate instead')
- void Function(InAppWebViewController controller)?
- iosOnWebContentProcessDidTerminate,
- @Deprecated('Use onNavigationResponse instead')
- Future Function(
- InAppWebViewController controller,
- IOSWKNavigationResponse navigationResponse)?
- iosOnNavigationResponse,
- @Deprecated('Use shouldAllowDeprecatedTLS instead')
- Future Function(
- InAppWebViewController controller,
- URLAuthenticationChallenge challenge)?
- iosShouldAllowDeprecatedTLS,
- Future Function(
- InAppWebViewController controller, AjaxRequest ajaxRequest)?
- onAjaxProgress,
- Future Function(
- InAppWebViewController controller, AjaxRequest ajaxRequest)?
- onAjaxReadyStateChange,
- void Function(
- InAppWebViewController controller, ConsoleMessage consoleMessage)?
- onConsoleMessage,
- Future Function(InAppWebViewController controller,
- CreateWindowAction createWindowAction)?
- onCreateWindow,
- void Function(InAppWebViewController controller)? onCloseWindow,
- void Function(InAppWebViewController controller)? onWindowFocus,
- void Function(InAppWebViewController controller)? onWindowBlur,
- @Deprecated('Use onReceivedIcon instead')
- void Function(InAppWebViewController controller, Uint8List icon)?
- androidOnReceivedIcon,
- @Deprecated('Use onReceivedTouchIconUrl instead')
- void Function(InAppWebViewController controller, Uri url, bool precomposed)?
- androidOnReceivedTouchIconUrl,
- @Deprecated('Use onDownloadStartRequest instead')
- void Function(InAppWebViewController controller, Uri url)? onDownloadStart,
- void Function(InAppWebViewController controller,
- DownloadStartRequest downloadStartRequest)?
- onDownloadStartRequest,
- @Deprecated('Use FindInteractionController.onFindResultReceived instead')
- void Function(InAppWebViewController controller, int activeMatchOrdinal,
- int numberOfMatches, bool isDoneCounting)?
- onFindResultReceived,
- Future