Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
F
Flutter Inappwebview
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
李增强
Flutter Inappwebview
Commits
8b5a6347
Commit
8b5a6347
authored
Nov 27, 2018
by
pichillilorenzo
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
working on iOS inline webview implementation
parent
a5a784dd
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
922 additions
and
72 deletions
+922
-72
.idea/workspace.xml
.idea/workspace.xml
+60
-33
example/ios/Runner/Info.plist
example/ios/Runner/Info.plist
+4
-0
flutter_inappbrowser.iml
flutter_inappbrowser.iml
+1
-0
ios/Classes/FlutterWebViewController.swift
ios/Classes/FlutterWebViewController.swift
+216
-10
ios/Classes/InAppBrowserWebViewController.swift
ios/Classes/InAppBrowserWebViewController.swift
+3
-2
ios/Classes/InAppWebView.swift
ios/Classes/InAppWebView.swift
+613
-2
ios/Classes/SwiftFlutterPlugin.swift
ios/Classes/SwiftFlutterPlugin.swift
+25
-25
No files found.
.idea/workspace.xml
View file @
8b5a6347
...
...
@@ -16,10 +16,12 @@
<component
name=
"ChangeListManager"
>
<list
default=
"true"
id=
"9b41f7a2-a71e-4923-91fb-249d7815b3e7"
name=
"Default"
comment=
""
>
<change
beforePath=
"$PROJECT_DIR$/.idea/workspace.xml"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/.idea/workspace.xml"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/example/
lib/main.dart"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/example/lib/main.dar
t"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/example/
ios/Runner/Info.plist"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/example/ios/Runner/Info.plis
t"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/flutter_inappbrowser.iml"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/flutter_inappbrowser.iml"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/ios/Classes/FlutterWebViewController.swift"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/ios/Classes/FlutterWebViewController.swift"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/ios/Classes/InAppBrowserWebViewController.swift"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/ios/Classes/InAppBrowserWebViewController.swift"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/ios/Classes/InAppWebView.swift"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/ios/Classes/InAppWebView.swift"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/ios/Classes/SwiftFlutterPlugin.swift"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/ios/Classes/SwiftFlutterPlugin.swift"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/lib/flutter_inappbrowser.dart"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/lib/flutter_inappbrowser.dart"
afterDir=
"false"
/>
</list>
<ignored
path=
"$PROJECT_DIR$/.dart_tool/"
/>
<ignored
path=
"$PROJECT_DIR$/.idea/"
/>
...
...
@@ -39,8 +41,8 @@
<file
leaf-file-name=
"flutter_inappbrowser.dart"
pinned=
"false"
current-in-tab=
"false"
>
<entry
file=
"file://$PROJECT_DIR$/lib/flutter_inappbrowser.dart"
>
<provider
selected=
"true"
editor-type-id=
"text-editor"
>
<state
relative-caret-position=
"2
49
"
>
<caret
line=
"
698"
column=
"61"
selection-start-line=
"698"
selection-start-column=
"61"
selection-end-line=
"698"
selection-end-column=
"6
1"
/>
<state
relative-caret-position=
"2
50
"
>
<caret
line=
"
323"
column=
"41"
selection-start-line=
"323"
selection-start-column=
"41"
selection-end-line=
"323"
selection-end-column=
"4
1"
/>
<folding>
<element
signature=
"e#814#831#0"
expanded=
"true"
/>
</folding>
...
...
@@ -51,8 +53,8 @@
<file
leaf-file-name=
"main.dart"
pinned=
"false"
current-in-tab=
"true"
>
<entry
file=
"file://$PROJECT_DIR$/example/lib/main.dart"
>
<provider
selected=
"true"
editor-type-id=
"text-editor"
>
<state
relative-caret-position=
"
500
"
>
<caret
line=
"
376"
column=
"38"
selection-start-line=
"376"
selection-start-column=
"38"
selection-end-line=
"376"
selection-end-column=
"38
"
/>
<state
relative-caret-position=
"
288
"
>
<caret
line=
"
410"
column=
"35"
lean-forward=
"true"
selection-start-line=
"410"
selection-start-column=
"35"
selection-end-line=
"410"
selection-end-column=
"35
"
/>
<folding>
<element
signature=
"e#0#16428#0"
expanded=
"true"
/>
<element
signature=
"e#12489#12509#0"
expanded=
"true"
/>
...
...
@@ -72,7 +74,6 @@
</component>
<component
name=
"FindInProjectRecents"
>
<findStrings>
<find>
postUrl
</find>
<find>
assert(
</find>
<find>
sNotEmpty()
</find>
<find>
loadData
</find>
...
...
@@ -102,6 +103,7 @@
<find>
onScrollChanged
</find>
<find>
initialData
</find>
<find>
openData
</find>
<find>
optionsType
</find>
</findStrings>
<replaceStrings>
<replace>
activity.getPreferences(0)
</replace>
...
...
@@ -147,6 +149,7 @@
<option
value=
"$PROJECT_DIR$/pubspec.yaml"
/>
<option
value=
"$PROJECT_DIR$/CHANGELOG.md"
/>
<option
value=
"$PROJECT_DIR$/lib/flutter_inappbrowser.dart"
/>
<option
value=
"$PROJECT_DIR$/example/ios/Runner/Info.plist"
/>
<option
value=
"$PROJECT_DIR$/example/lib/main.dart"
/>
</list>
</option>
...
...
@@ -163,18 +166,6 @@
</navigator>
<panes>
<pane
id=
"AndroidView"
/>
<pane
id=
"PackagesPane"
/>
<pane
id=
"Scope"
>
<subPane
subId=
"Project Files"
>
<expand>
<path>
<item
name=
"Root"
type=
"cbb8eebc:String"
user=
"Root"
/>
<item
name=
"flutter_inappbrowser"
type=
"cbb8eebc:String"
user=
"flutter_inappbrowser"
/>
</path>
</expand>
<select
/>
</subPane>
</pane>
<pane
id=
"ProjectPane"
>
<subPane>
<expand>
...
...
@@ -182,6 +173,29 @@
<item
name=
"flutter_inappbrowser"
type=
"b2602c69:ProjectViewProjectNode"
/>
<item
name=
"flutter_inappbrowser"
type=
"462c0819:PsiDirectoryNode"
/>
</path>
<path>
<item
name=
"flutter_inappbrowser"
type=
"b2602c69:ProjectViewProjectNode"
/>
<item
name=
"flutter_inappbrowser"
type=
"462c0819:PsiDirectoryNode"
/>
<item
name=
"example"
type=
"462c0819:PsiDirectoryNode"
/>
</path>
<path>
<item
name=
"flutter_inappbrowser"
type=
"b2602c69:ProjectViewProjectNode"
/>
<item
name=
"flutter_inappbrowser"
type=
"462c0819:PsiDirectoryNode"
/>
<item
name=
"example"
type=
"462c0819:PsiDirectoryNode"
/>
<item
name=
"ios"
type=
"462c0819:PsiDirectoryNode"
/>
</path>
<path>
<item
name=
"flutter_inappbrowser"
type=
"b2602c69:ProjectViewProjectNode"
/>
<item
name=
"flutter_inappbrowser"
type=
"462c0819:PsiDirectoryNode"
/>
<item
name=
"example"
type=
"462c0819:PsiDirectoryNode"
/>
<item
name=
"ios"
type=
"462c0819:PsiDirectoryNode"
/>
<item
name=
"Runner"
type=
"462c0819:PsiDirectoryNode"
/>
</path>
<path>
<item
name=
"flutter_inappbrowser"
type=
"b2602c69:ProjectViewProjectNode"
/>
<item
name=
"flutter_inappbrowser"
type=
"462c0819:PsiDirectoryNode"
/>
<item
name=
"ios"
type=
"462c0819:PsiDirectoryNode"
/>
</path>
<path>
<item
name=
"flutter_inappbrowser"
type=
"b2602c69:ProjectViewProjectNode"
/>
<item
name=
"flutter_inappbrowser"
type=
"462c0819:PsiDirectoryNode"
/>
...
...
@@ -192,6 +206,18 @@
</subPane>
<option
name=
"show-excluded-files"
value=
"false"
/>
</pane>
<pane
id=
"PackagesPane"
/>
<pane
id=
"Scope"
>
<subPane
subId=
"Project Files"
>
<expand>
<path>
<item
name=
"Root"
type=
"cbb8eebc:String"
user=
"Root"
/>
<item
name=
"flutter_inappbrowser"
type=
"cbb8eebc:String"
user=
"flutter_inappbrowser"
/>
</path>
</expand>
<select
/>
</subPane>
</pane>
</panes>
</component>
<component
name=
"PropertiesComponent"
>
...
...
@@ -349,10 +375,10 @@
</component>
<component
name=
"ToolWindowManager"
>
<frame
x=
"0"
y=
"23"
width=
"1641"
height=
"1027"
extended-state=
"0"
/>
<editor
active=
"true"
/>
<layout>
<window_info
anchor=
"bottom"
id=
"Android Profiler"
order=
"7"
show_stripe_button=
"false"
/>
<window_info
anchor=
"bottom"
id=
"TODO"
order=
"6"
/>
<window_info
anchor=
"bottom"
id=
"Messages"
order=
"12"
visible=
"true"
weight=
"0.23594266"
/>
<window_info
anchor=
"right"
id=
"Palette	"
order=
"9"
/>
<window_info
id=
"Image Layers"
order=
"7"
/>
<window_info
id=
"Build Variants"
order=
"3"
side_tool=
"true"
/>
...
...
@@ -367,13 +393,14 @@
<window_info
id=
"Captures"
order=
"4"
weight=
"0.32936507"
/>
<window_info
id=
"Capture Tool"
order=
"6"
/>
<window_info
id=
"Designer"
order=
"2"
/>
<window_info
content_ui=
"combo"
id=
"Project"
order=
"0"
sideWeight=
"0.4963925
"
visible=
"true"
weight=
"0.13445903"
/>
<window_info
active=
"true"
id=
"Structure"
order=
"1"
sideWeight=
"0.5036075
"
side_tool=
"true"
visible=
"true"
weight=
"0.13445903"
/>
<window_info
active=
"true"
content_ui=
"combo"
id=
"Project"
order=
"0"
sideWeight=
"0.4950386
"
visible=
"true"
weight=
"0.13445903"
/>
<window_info
id=
"Structure"
order=
"1"
sideWeight=
"0.50496143
"
side_tool=
"true"
visible=
"true"
weight=
"0.13445903"
/>
<window_info
anchor=
"right"
id=
"Device File Explorer"
order=
"5"
side_tool=
"true"
/>
<window_info
anchor=
"right"
id=
"Theme Preview"
order=
"7"
/>
<window_info
anchor=
"bottom"
id=
"Debug"
order=
"3"
weight=
"0.34288865"
/>
<window_info
id=
"Favorites"
order=
"5"
side_tool=
"true"
/>
<window_info
anchor=
"right"
id=
"Flutter Inspector"
order=
"3"
weight=
"0.32938388"
/>
<window_info
anchor=
"bottom"
id=
"Messages"
order=
"12"
visible=
"true"
weight=
"0.23594266"
/>
<window_info
anchor=
"bottom"
id=
"Inspection"
order=
"5"
weight=
"0.4"
/>
<window_info
anchor=
"right"
id=
"Commander"
order=
"0"
weight=
"0.4"
/>
<window_info
anchor=
"right"
id=
"Assistant"
order=
"8"
visible=
"true"
weight=
"0.3295129"
/>
...
...
@@ -622,13 +649,6 @@
</state>
</provider>
</entry>
<entry
file=
"file://$PROJECT_DIR$/example/ios/Runner/Info.plist"
>
<provider
selected=
"true"
editor-type-id=
"text-editor"
>
<state
relative-caret-position=
"390"
>
<caret
line=
"26"
column=
"44"
selection-start-line=
"26"
selection-start-column=
"44"
selection-end-line=
"26"
selection-end-column=
"44"
/>
</state>
</provider>
</entry>
<entry
file=
"file://$PROJECT_DIR$/pubspec.yaml"
>
<provider
selected=
"true"
editor-type-id=
"text-editor"
>
<state
relative-caret-position=
"15"
>
...
...
@@ -650,10 +670,17 @@
</state>
</provider>
</entry>
<entry
file=
"file://$PROJECT_DIR$/example/ios/Runner/Info.plist"
>
<provider
selected=
"true"
editor-type-id=
"text-editor"
>
<state
relative-caret-position=
"735"
>
<caret
line=
"49"
column=
"4"
selection-start-line=
"49"
selection-start-column=
"4"
selection-end-line=
"49"
selection-end-column=
"4"
/>
</state>
</provider>
</entry>
<entry
file=
"file://$PROJECT_DIR$/lib/flutter_inappbrowser.dart"
>
<provider
selected=
"true"
editor-type-id=
"text-editor"
>
<state
relative-caret-position=
"2
49
"
>
<caret
line=
"
698"
column=
"61"
selection-start-line=
"698"
selection-start-column=
"61"
selection-end-line=
"698"
selection-end-column=
"6
1"
/>
<state
relative-caret-position=
"2
50
"
>
<caret
line=
"
323"
column=
"41"
selection-start-line=
"323"
selection-start-column=
"41"
selection-end-line=
"323"
selection-end-column=
"4
1"
/>
<folding>
<element
signature=
"e#814#831#0"
expanded=
"true"
/>
</folding>
...
...
@@ -662,8 +689,8 @@
</entry>
<entry
file=
"file://$PROJECT_DIR$/example/lib/main.dart"
>
<provider
selected=
"true"
editor-type-id=
"text-editor"
>
<state
relative-caret-position=
"
500
"
>
<caret
line=
"
376"
column=
"38"
selection-start-line=
"376"
selection-start-column=
"38"
selection-end-line=
"376"
selection-end-column=
"38
"
/>
<state
relative-caret-position=
"
288
"
>
<caret
line=
"
410"
column=
"35"
lean-forward=
"true"
selection-start-line=
"410"
selection-start-column=
"35"
selection-end-line=
"410"
selection-end-column=
"35
"
/>
<folding>
<element
signature=
"e#0#16428#0"
expanded=
"true"
/>
<element
signature=
"e#12489#12509#0"
expanded=
"true"
/>
...
...
example/ios/Runner/Info.plist
View file @
8b5a6347
...
...
@@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist
version=
"1.0"
>
<dict>
<key></key>
<string></string>
<key>
NSAppTransportSecurity
</key>
<dict>
<key>
NSAllowsLocalNetworking
</key>
...
...
@@ -44,6 +46,8 @@
<string>
UIInterfaceOrientationLandscapeLeft
</string>
<string>
UIInterfaceOrientationLandscapeRight
</string>
</array>
<key>
io.flutter.embedded_views_preview
</key>
<true/>
<key>
UIViewControllerBasedStatusBarAppearance
</key>
<false/>
</dict>
...
...
flutter_inappbrowser.iml
View file @
8b5a6347
...
...
@@ -20,6 +20,7 @@
<excludeFolder
url=
"file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/example/.dart_tool"
/>
<excludeFolder
url=
"file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/example/.pub"
/>
<excludeFolder
url=
"file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/example/build"
/>
<excludeFolder
url=
"file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/example/ios/Flutter/flutter_assets/packages"
/>
<excludeFolder
url=
"file://$MODULE_DIR$/example/ios/Flutter/flutter_assets/packages"
/>
</content>
<orderEntry
type=
"sourceFolder"
forTests=
"false"
/>
...
...
ios/Classes/FlutterWebViewController.swift
View file @
8b5a6347
...
...
@@ -6,20 +6,21 @@
//
import
Foundation
import
WebKit
public
class
FlutterWebViewController
:
NSObject
,
FlutterPlatformView
{
private
weak
var
registrar
:
FlutterPluginRegistrar
?
private
var
webView
:
InAppWebView
?
private
var
viewId
:
Int64
=
0
private
var
channel
:
FlutterMethodChannel
?
var
webView
:
InAppWebView
?
var
viewId
:
Int64
=
0
var
channel
:
FlutterMethodChannel
?
init
(
registrar
:
FlutterPluginRegistrar
,
withFrame
frame
:
CGRect
,
viewIdentifier
viewId
:
Int64
,
arguments
args
:
NSDictionary
)
{
super
.
init
()
self
.
registrar
=
registrar
self
.
viewId
=
viewId
webView
=
InAppWebView
(
frame
:
frame
)
let
channelName
=
String
(
format
:
"com.pichillilorenzo/flutter_inappwebview_%lld"
,
viewId
)
webView
=
InAppWebView
(
frame
:
frame
,
configuration
:
WKWebViewConfiguration
(),
IABController
:
nil
,
IAWController
:
self
)
let
channelName
=
"com.pichillilorenzo/flutter_inappwebview_"
+
String
(
viewId
)
self
.
channel
=
FlutterMethodChannel
(
name
:
channelName
,
binaryMessenger
:
registrar
.
messenger
())
self
.
channel
?
.
setMethodCallHandler
(
self
.
handle
)
...
...
@@ -29,7 +30,32 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView {
let
initialHeaders
=
(
args
[
"initialHeaders"
]
as?
[
String
:
String
])
!
let
initialOptions
=
(
args
[
"initialOptions"
]
as?
[
String
:
Any
])
!
webView
!.
load
(
URLRequest
(
url
:
URL
(
string
:
initialUrl
)
!
))
let
options
=
InAppWebViewOptions
()
options
.
parse
(
options
:
initialOptions
)
webView
!.
options
=
options
webView
!.
prepare
()
if
initialFile
!=
nil
{
do
{
try
webView
!.
loadFile
(
url
:
initialFile
!
,
headers
:
initialHeaders
)
}
catch
let
error
as
NSError
{
dump
(
error
)
}
return
}
if
initialData
!=
nil
{
let
data
=
(
initialData
!
[
"data"
]
as?
String
)
!
let
mimeType
=
(
initialData
!
[
"mimeType"
]
as?
String
)
!
let
encoding
=
(
initialData
!
[
"encoding"
]
as?
String
)
!
let
baseUrl
=
(
initialData
!
[
"baseUrl"
]
as?
String
)
!
webView
!.
loadData
(
data
:
data
,
mimeType
:
mimeType
,
encoding
:
encoding
,
baseUrl
:
baseUrl
)
}
else
{
webView
!.
loadUrl
(
url
:
URL
(
string
:
initialUrl
)
!
,
headers
:
initialHeaders
)
}
}
public
func
view
()
->
UIView
{
...
...
@@ -38,14 +64,194 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView {
public
func
handle
(
_
call
:
FlutterMethodCall
,
result
:
@escaping
FlutterResult
)
{
let
arguments
=
call
.
arguments
as?
NSDictionary
switch
call
.
method
{
//case "open":
//self.open(uuid: uuid, arguments: arguments!, result: result)
//break
case
"getUrl"
:
result
(
(
webView
!=
nil
)
?
webView
!.
url
?
.
absoluteString
:
nil
)
break
case
"getTitle"
:
result
(
(
webView
!=
nil
)
?
webView
!.
title
:
nil
)
break
case
"getProgress"
:
result
(
(
webView
!=
nil
)
?
Int
(
webView
!.
estimatedProgress
*
100
)
:
nil
)
break
case
"loadUrl"
:
if
webView
!=
nil
{
let
url
=
(
arguments
!
[
"url"
]
as?
String
)
!
let
headers
=
(
arguments
!
[
"headers"
]
as?
[
String
:
String
])
!
webView
!.
loadUrl
(
url
:
URL
(
string
:
url
)
!
,
headers
:
headers
)
result
(
true
)
}
else
{
result
(
false
)
}
break
case
"postUrl"
:
if
webView
!=
nil
{
let
url
=
(
arguments
!
[
"url"
]
as?
String
)
!
let
postData
=
(
arguments
!
[
"postData"
]
as?
FlutterStandardTypedData
)
!
webView
!.
postUrl
(
url
:
URL
(
string
:
url
)
!
,
postData
:
postData
.
data
,
completionHandler
:
{
()
->
Void
in
result
(
true
)
})
}
else
{
result
(
false
)
}
break
case
"loadData"
:
if
webView
!=
nil
{
let
data
=
(
arguments
!
[
"data"
]
as?
String
)
!
let
mimeType
=
(
arguments
!
[
"mimeType"
]
as?
String
)
!
let
encoding
=
(
arguments
!
[
"encoding"
]
as?
String
)
!
let
baseUrl
=
(
arguments
!
[
"baseUrl"
]
as?
String
)
!
webView
!.
loadData
(
data
:
data
,
mimeType
:
mimeType
,
encoding
:
encoding
,
baseUrl
:
baseUrl
)
result
(
true
)
}
else
{
result
(
false
)
}
break
case
"loadFile"
:
if
webView
!=
nil
{
let
url
=
(
arguments
!
[
"url"
]
as?
String
)
!
let
headers
=
(
arguments
!
[
"headers"
]
as?
[
String
:
String
])
!
do
{
try
webView
!.
loadFile
(
url
:
url
,
headers
:
headers
)
result
(
true
)
}
catch
let
error
as
NSError
{
result
(
FlutterError
(
code
:
"InAppBrowserFlutterPlugin"
,
message
:
error
.
domain
,
details
:
nil
))
return
}
}
else
{
result
(
false
)
}
break
case
"injectScriptCode"
:
if
webView
!=
nil
{
let
source
=
(
arguments
!
[
"source"
]
as?
String
)
!
webView
!.
injectScriptCode
(
source
:
source
,
result
:
result
)
}
else
{
result
(
false
)
}
break
case
"injectScriptFile"
:
if
webView
!=
nil
{
let
urlFile
=
(
arguments
!
[
"urlFile"
]
as?
String
)
!
webView
!.
injectScriptFile
(
urlFile
:
urlFile
,
result
:
result
)
}
else
{
result
(
false
)
}
break
case
"injectStyleCode"
:
if
webView
!=
nil
{
let
source
=
(
arguments
!
[
"source"
]
as?
String
)
!
webView
!.
injectStyleCode
(
source
:
source
,
result
:
result
)
}
else
{
result
(
false
)
}
break
case
"injectStyleFile"
:
if
webView
!=
nil
{
let
urlFile
=
(
arguments
!
[
"urlFile"
]
as?
String
)
!
webView
!.
injectStyleFile
(
urlFile
:
urlFile
,
result
:
result
)
}
else
{
result
(
false
)
}
break
case
"reload"
:
if
webView
!=
nil
{
webView
!.
reload
()
}
result
(
true
)
break
case
"goBack"
:
if
webView
!=
nil
{
webView
!.
goBack
()
}
result
(
true
)
break
case
"canGoBack"
:
result
((
webView
!=
nil
)
&&
webView
!.
canGoBack
)
break
case
"goForward"
:
if
webView
!=
nil
{
webView
!.
goForward
()
}
result
(
true
)
break
case
"canGoForward"
:
result
((
webView
!=
nil
)
&&
webView
!.
canGoForward
)
break
case
"goBackOrForward"
:
if
webView
!=
nil
{
let
steps
=
(
arguments
!
[
"steps"
]
as?
Int
)
!
webView
!.
goBackOrForward
(
steps
:
steps
)
}
result
(
true
)
break
case
"canGoBackOrForward"
:
let
steps
=
(
arguments
!
[
"steps"
]
as?
Int
)
!
result
((
webView
!=
nil
)
&&
webView
!.
canGoBackOrForward
(
steps
:
steps
))
break
case
"stopLoading"
:
if
webView
!=
nil
{
webView
!.
stopLoading
()
}
result
(
true
)
break
case
"isLoading"
:
result
((
webView
!=
nil
)
&&
webView
!.
isLoading
)
break
case
"takeScreenshot"
:
if
webView
!=
nil
{
webView
!.
takeScreenshot
(
completionHandler
:
{
(
screenshot
)
->
Void
in
result
(
screenshot
)
})
}
else
{
result
(
nil
)
}
break
case
"setOptions"
:
if
webView
!=
nil
{
let
inAppWebViewOptions
=
InAppWebViewOptions
()
let
inAppWebViewOptionsMap
=
arguments
!
[
"options"
]
as!
[
String
:
Any
]
inAppWebViewOptions
.
parse
(
options
:
inAppWebViewOptionsMap
)
webView
!.
setOptions
(
newOptions
:
inAppWebViewOptions
,
newOptionsMap
:
inAppWebViewOptionsMap
)
}
result
(
true
)
break
case
"getOptions"
:
result
((
webView
!=
nil
)
?
webView
!.
getOptions
()
:
nil
)
break
case
"getCopyBackForwardList"
:
result
((
webView
!=
nil
)
?
webView
!.
getCopyBackForwardList
()
:
nil
)
break
case
"dispose"
:
dispose
()
result
(
true
)
break
default
:
result
(
FlutterMethodNotImplemented
)
break
}
}
public
func
dispose
()
{
if
webView
!=
nil
{
webView
!.
IABController
=
nil
webView
!.
IAWController
=
nil
webView
!.
uiDelegate
=
nil
webView
!.
navigationDelegate
=
nil
webView
!.
scrollView
.
delegate
=
nil
webView
!.
stopLoading
()
webView
=
nil
}
}
}
ios/Classes/InAppBrowserWebViewController.swift
View file @
8b5a6347
...
...
@@ -130,9 +130,9 @@ func convertToDictionary(text: String) -> [String: Any]? {
//}
class
InAppWebView_IBWrapper
:
InAppWebView
{
required
convenience
init
?
(
coder
:
NSCoder
)
{
required
convenience
init
(
coder
:
NSCoder
)
{
let
config
=
WKWebViewConfiguration
()
self
.
init
(
frame
:
.
zero
,
configuration
:
config
)
self
.
init
(
frame
:
.
zero
,
configuration
:
config
,
IABController
:
nil
,
IAWController
:
nil
)
self
.
translatesAutoresizingMaskIntoConstraints
=
false
}
}
...
...
@@ -176,6 +176,7 @@ class InAppBrowserWebViewController: UIViewController, UIScrollViewDelegate, WKU
}
override
func
viewWillAppear
(
_
animated
:
Bool
)
{
self
.
webView
.
IABController
=
self
if
!
viewPrepared
{
prepareConstraints
()
prepareWebView
()
...
...
ios/Classes/InAppWebView.swift
View file @
8b5a6347
...
...
@@ -8,9 +8,128 @@
import
Foundation
import
WebKit
public
class
InAppWebView
:
WKWebView
{
public
class
InAppWebView
:
WKWebView
,
UIScrollViewDelegate
,
WKUIDelegate
,
WKNavigationDelegate
,
WKScriptMessageHandler
{
var
historyOffset
=
0
var
IABController
:
InAppBrowserWebViewController
?
var
IAWController
:
FlutterWebViewController
?
var
options
:
InAppWebViewOptions
?
var
currentURL
:
URL
?
var
WKNavigationMap
:
[
String
:
[
String
:
Any
]]
=
[:]
var
startPageTime
=
0
init
(
frame
:
CGRect
,
configuration
:
WKWebViewConfiguration
,
IABController
:
InAppBrowserWebViewController
?,
IAWController
:
FlutterWebViewController
?)
{
super
.
init
(
frame
:
frame
,
configuration
:
configuration
)
self
.
IABController
=
IABController
self
.
IAWController
=
IAWController
uiDelegate
=
self
navigationDelegate
=
self
scrollView
.
delegate
=
self
}
required
init
(
coder
aDecoder
:
NSCoder
)
{
super
.
init
(
coder
:
aDecoder
)
!
}
public
func
prepare
()
{
addObserver
(
self
,
forKeyPath
:
#keyPath(
WKWebView.estimatedProgress
)
,
options
:
.
new
,
context
:
nil
)
configuration
.
userContentController
=
WKUserContentController
()
configuration
.
preferences
=
WKPreferences
()
// prevent webView from bouncing
if
(
options
?
.
disallowOverScroll
)
!
{
if
responds
(
to
:
#selector(
getter: scrollView
)
)
{
scrollView
.
bounces
=
false
}
else
{
for
subview
:
UIView
in
subviews
{
if
subview
is
UIScrollView
{
(
subview
as!
UIScrollView
)
.
bounces
=
false
}
}
}
}
if
(
options
?
.
enableViewportScale
)
!
{
let
jscript
=
"var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);"
let
userScript
=
WKUserScript
(
source
:
jscript
,
injectionTime
:
.
atDocumentEnd
,
forMainFrameOnly
:
true
)
configuration
.
userContentController
.
addUserScript
(
userScript
)
}
// Prevents long press on links that cause WKWebView exit
let
jscriptWebkitTouchCallout
=
WKUserScript
(
source
:
"document.body.style.webkitTouchCallout='none';"
,
injectionTime
:
.
atDocumentEnd
,
forMainFrameOnly
:
true
)
configuration
.
userContentController
.
addUserScript
(
jscriptWebkitTouchCallout
)
let
consoleLogJSScript
=
WKUserScript
(
source
:
consoleLogJS
,
injectionTime
:
.
atDocumentStart
,
forMainFrameOnly
:
false
)
configuration
.
userContentController
.
addUserScript
(
consoleLogJSScript
)
configuration
.
userContentController
.
add
(
self
,
name
:
"consoleLog"
)
configuration
.
userContentController
.
add
(
self
,
name
:
"consoleDebug"
)
configuration
.
userContentController
.
add
(
self
,
name
:
"consoleError"
)
configuration
.
userContentController
.
add
(
self
,
name
:
"consoleInfo"
)
configuration
.
userContentController
.
add
(
self
,
name
:
"consoleWarn"
)
let
javaScriptBridgeJSScript
=
WKUserScript
(
source
:
javaScriptBridgeJS
,
injectionTime
:
.
atDocumentStart
,
forMainFrameOnly
:
false
)
configuration
.
userContentController
.
addUserScript
(
javaScriptBridgeJSScript
)
configuration
.
userContentController
.
add
(
self
,
name
:
"callHandler"
)
let
resourceObserverJSScript
=
WKUserScript
(
source
:
resourceObserverJS
,
injectionTime
:
.
atDocumentStart
,
forMainFrameOnly
:
false
)
configuration
.
userContentController
.
addUserScript
(
resourceObserverJSScript
)
configuration
.
userContentController
.
add
(
self
,
name
:
"resourceLoaded"
)
if
#available(iOS 10.0, *)
{
configuration
.
mediaTypesRequiringUserActionForPlayback
=
((
options
?
.
mediaPlaybackRequiresUserGesture
)
!
)
?
.
all
:
[]
}
else
{
// Fallback on earlier versions
configuration
.
mediaPlaybackRequiresUserAction
=
(
options
?
.
mediaPlaybackRequiresUserGesture
)
!
}
configuration
.
allowsInlineMediaPlayback
=
(
options
?
.
allowsInlineMediaPlayback
)
!
//keyboardDisplayRequiresUserAction = browserOptions?.keyboardDisplayRequiresUserAction
configuration
.
suppressesIncrementalRendering
=
(
options
?
.
suppressesIncrementalRendering
)
!
allowsBackForwardNavigationGestures
=
(
options
?
.
allowsBackForwardNavigationGestures
)
!
if
#available(iOS 9.0, *)
{
allowsLinkPreview
=
(
options
?
.
allowsLinkPreview
)
!
}
if
#available(iOS 10.0, *)
{
configuration
.
ignoresViewportScaleLimits
=
(
options
?
.
ignoresViewportScaleLimits
)
!
}
configuration
.
allowsInlineMediaPlayback
=
(
options
?
.
allowsInlineMediaPlayback
)
!
if
#available(iOS 9.0, *)
{
configuration
.
allowsPictureInPictureMediaPlayback
=
(
options
?
.
allowsPictureInPictureMediaPlayback
)
!
}
configuration
.
preferences
.
javaScriptCanOpenWindowsAutomatically
=
(
options
?
.
javaScriptCanOpenWindowsAutomatically
)
!
configuration
.
preferences
.
javaScriptEnabled
=
(
options
?
.
javaScriptEnabled
)
!
if
((
options
?
.
userAgent
)
!
!=
""
)
{
if
#available(iOS 9.0, *)
{
customUserAgent
=
(
options
?
.
userAgent
)
!
}
}
if
(
options
?
.
clearCache
)
!
{
clearCache
()
}
}
override
public
func
observeValue
(
forKeyPath
keyPath
:
String
?,
of
object
:
Any
?,
change
:
[
NSKeyValueChangeKey
:
Any
]?,
context
:
UnsafeMutableRawPointer
?)
{
if
keyPath
==
"estimatedProgress"
{
let
progress
=
Int
(
estimatedProgress
*
100
)
onProgressChanged
(
progress
:
progress
)
}
}
public
func
goBackOrForward
(
steps
:
Int
)
{
if
canGoBackOrForward
(
steps
:
steps
)
{
...
...
@@ -33,4 +152,496 @@ public class InAppWebView: WKWebView {
:
currentIndex
+
steps
>=
0
}
public
func
takeScreenshot
(
completionHandler
:
@escaping
(
_
screenshot
:
Data
?)
->
Void
)
{
if
#available(iOS 11.0, *)
{
takeSnapshot
(
with
:
nil
,
completionHandler
:
{(
image
,
error
)
->
Void
in
var
imageData
:
Data
?
=
nil
if
let
screenshot
=
image
{
imageData
=
UIImagePNGRepresentation
(
screenshot
)
!
}
completionHandler
(
imageData
)
})
}
else
{
completionHandler
(
nil
)
}
}
public
func
loadUrl
(
url
:
URL
,
headers
:
[
String
:
String
]?)
{
var
request
=
URLRequest
(
url
:
url
)
currentURL
=
url
if
let
mutableRequest
=
(
request
as
NSURLRequest
)
.
mutableCopy
()
as?
NSMutableURLRequest
{
for
(
key
,
value
)
in
headers
!
{
mutableRequest
.
setValue
(
value
,
forHTTPHeaderField
:
key
)
}
request
=
mutableRequest
as
URLRequest
}
load
(
request
)
}
public
func
postUrl
(
url
:
URL
,
postData
:
Data
,
completionHandler
:
@escaping
()
->
Void
)
{
var
request
=
URLRequest
(
url
:
url
)
currentURL
=
url
request
.
httpMethod
=
"POST"
request
.
httpBody
=
postData
let
task
=
URLSession
.
shared
.
dataTask
(
with
:
request
)
{
(
data
:
Data
?,
response
:
URLResponse
?,
error
:
Error
?)
in
var
returnString
=
""
if
data
!=
nil
{
returnString
=
String
(
data
:
data
!
,
encoding
:
.
utf8
)
??
""
}
DispatchQueue
.
main
.
async
(
execute
:
{()
->
Void
in
self
.
loadHTMLString
(
returnString
,
baseURL
:
url
)
completionHandler
()
})
}
task
.
resume
()
}
public
func
loadData
(
data
:
String
,
mimeType
:
String
,
encoding
:
String
,
baseUrl
:
String
)
{
let
url
=
URL
(
string
:
baseUrl
)
!
currentURL
=
url
if
#available(iOS 9.0, *)
{
load
(
data
.
data
(
using
:
.
utf8
)
!
,
mimeType
:
mimeType
,
characterEncodingName
:
encoding
,
baseURL
:
url
)
}
else
{
loadHTMLString
(
data
,
baseURL
:
url
)
}
}
public
func
loadFile
(
url
:
String
,
headers
:
[
String
:
String
]?)
throws
{
let
key
=
SwiftFlutterPlugin
.
registrar
!.
lookupKey
(
forAsset
:
url
)
let
assetURL
=
Bundle
.
main
.
url
(
forResource
:
key
,
withExtension
:
nil
)
if
assetURL
==
nil
{
throw
NSError
(
domain
:
url
+
" asset file cannot be found!"
,
code
:
0
)
}
let
absoluteUrl
=
URL
(
string
:
url
)
!.
absoluteURL
loadUrl
(
url
:
absoluteUrl
,
headers
:
headers
)
}
func
setOptions
(
newOptions
:
InAppWebViewOptions
,
newOptionsMap
:
[
String
:
Any
])
{
if
newOptionsMap
[
"disallowOverScroll"
]
!=
nil
&&
options
?
.
disallowOverScroll
!=
newOptions
.
disallowOverScroll
{
if
responds
(
to
:
#selector(
getter: scrollView
)
)
{
scrollView
.
bounces
=
!
newOptions
.
disallowOverScroll
}
else
{
for
subview
:
UIView
in
subviews
{
if
subview
is
UIScrollView
{
(
subview
as!
UIScrollView
)
.
bounces
=
!
newOptions
.
disallowOverScroll
}
}
}
}
if
newOptionsMap
[
"enableViewportScale"
]
!=
nil
&&
options
?
.
enableViewportScale
!=
newOptions
.
enableViewportScale
&&
newOptions
.
enableViewportScale
{
let
jscript
=
"var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);"
evaluateJavaScript
(
jscript
,
completionHandler
:
nil
)
}
if
newOptionsMap
[
"mediaPlaybackRequiresUserGesture"
]
!=
nil
&&
options
?
.
mediaPlaybackRequiresUserGesture
!=
newOptions
.
mediaPlaybackRequiresUserGesture
{
if
#available(iOS 10.0, *)
{
configuration
.
mediaTypesRequiringUserActionForPlayback
=
(
newOptions
.
mediaPlaybackRequiresUserGesture
)
?
.
all
:
[]
}
else
{
// Fallback on earlier versions
configuration
.
mediaPlaybackRequiresUserAction
=
newOptions
.
mediaPlaybackRequiresUserGesture
}
}
if
newOptionsMap
[
"allowsInlineMediaPlayback"
]
!=
nil
&&
options
?
.
allowsInlineMediaPlayback
!=
newOptions
.
allowsInlineMediaPlayback
{
configuration
.
allowsInlineMediaPlayback
=
newOptions
.
allowsInlineMediaPlayback
}
// if newOptionsMap["keyboardDisplayRequiresUserAction"] != nil && browserOptions?.keyboardDisplayRequiresUserAction != newOptions.keyboardDisplayRequiresUserAction {
// self.webView.keyboardDisplayRequiresUserAction = newOptions.keyboardDisplayRequiresUserAction
// }
if
newOptionsMap
[
"suppressesIncrementalRendering"
]
!=
nil
&&
options
?
.
suppressesIncrementalRendering
!=
newOptions
.
suppressesIncrementalRendering
{
configuration
.
suppressesIncrementalRendering
=
newOptions
.
suppressesIncrementalRendering
}
if
newOptionsMap
[
"allowsBackForwardNavigationGestures"
]
!=
nil
&&
options
?
.
allowsBackForwardNavigationGestures
!=
newOptions
.
allowsBackForwardNavigationGestures
{
allowsBackForwardNavigationGestures
=
newOptions
.
allowsBackForwardNavigationGestures
}
if
newOptionsMap
[
"allowsLinkPreview"
]
!=
nil
&&
options
?
.
allowsLinkPreview
!=
newOptions
.
allowsLinkPreview
{
if
#available(iOS 9.0, *)
{
allowsLinkPreview
=
newOptions
.
allowsLinkPreview
}
}
if
newOptionsMap
[
"ignoresViewportScaleLimits"
]
!=
nil
&&
options
?
.
ignoresViewportScaleLimits
!=
newOptions
.
ignoresViewportScaleLimits
{
if
#available(iOS 10.0, *)
{
configuration
.
ignoresViewportScaleLimits
=
newOptions
.
ignoresViewportScaleLimits
}
}
if
newOptionsMap
[
"allowsInlineMediaPlayback"
]
!=
nil
&&
options
?
.
allowsInlineMediaPlayback
!=
newOptions
.
allowsInlineMediaPlayback
{
configuration
.
allowsInlineMediaPlayback
=
newOptions
.
allowsInlineMediaPlayback
}
if
newOptionsMap
[
"allowsPictureInPictureMediaPlayback"
]
!=
nil
&&
options
?
.
allowsPictureInPictureMediaPlayback
!=
newOptions
.
allowsPictureInPictureMediaPlayback
{
if
#available(iOS 9.0, *)
{
configuration
.
allowsPictureInPictureMediaPlayback
=
newOptions
.
allowsPictureInPictureMediaPlayback
}
}
if
newOptionsMap
[
"javaScriptCanOpenWindowsAutomatically"
]
!=
nil
&&
options
?
.
javaScriptCanOpenWindowsAutomatically
!=
newOptions
.
javaScriptCanOpenWindowsAutomatically
{
configuration
.
preferences
.
javaScriptCanOpenWindowsAutomatically
=
newOptions
.
javaScriptCanOpenWindowsAutomatically
}
if
newOptionsMap
[
"javaScriptEnabled"
]
!=
nil
&&
options
?
.
javaScriptEnabled
!=
newOptions
.
javaScriptEnabled
{
configuration
.
preferences
.
javaScriptEnabled
=
newOptions
.
javaScriptEnabled
}
if
newOptionsMap
[
"userAgent"
]
!=
nil
&&
options
?
.
userAgent
!=
newOptions
.
userAgent
&&
(
newOptions
.
userAgent
!=
""
)
{
if
#available(iOS 9.0, *)
{
customUserAgent
=
newOptions
.
userAgent
}
}
if
newOptionsMap
[
"clearCache"
]
!=
nil
&&
newOptions
.
clearCache
{
clearCache
()
}
self
.
options
=
newOptions
}
func
getOptions
()
->
[
String
:
Any
]?
{
if
(
self
.
options
==
nil
)
{
return
nil
}
return
self
.
options
!.
getHashMap
()
}
public
func
clearCache
()
{
if
#available(iOS 9.0, *)
{
//let websiteDataTypes = NSSet(array: [WKWebsiteDataTypeDiskCache, WKWebsiteDataTypeMemoryCache])
let
date
=
NSDate
(
timeIntervalSince1970
:
0
)
WKWebsiteDataStore
.
default
()
.
removeData
(
ofTypes
:
WKWebsiteDataStore
.
allWebsiteDataTypes
(),
modifiedSince
:
date
as
Date
,
completionHandler
:{
})
}
else
{
var
libraryPath
=
NSSearchPathForDirectoriesInDomains
(
FileManager
.
SearchPathDirectory
.
libraryDirectory
,
FileManager
.
SearchPathDomainMask
.
userDomainMask
,
false
)
.
first
!
libraryPath
+=
"/Cookies"
do
{
try
FileManager
.
default
.
removeItem
(
atPath
:
libraryPath
)
}
catch
{
print
(
"can't clear cache"
)
}
URLCache
.
shared
.
removeAllCachedResponses
()
}
}
public
func
injectDeferredObject
(
source
:
String
,
withWrapper
jsWrapper
:
String
,
result
:
FlutterResult
?)
{
let
jsonData
:
Data
?
=
try
?
JSONSerialization
.
data
(
withJSONObject
:
[
source
],
options
:
[])
let
sourceArrayString
=
String
(
data
:
jsonData
!
,
encoding
:
String
.
Encoding
.
utf8
)
if
sourceArrayString
!=
nil
{
let
sourceString
:
String
?
=
(
sourceArrayString
!
as
NSString
)
.
substring
(
with
:
NSRange
(
location
:
1
,
length
:
(
sourceArrayString
?
.
count
??
0
)
-
2
))
let
jsToInject
=
String
(
format
:
jsWrapper
,
sourceString
!
)
evaluateJavaScript
(
jsToInject
,
completionHandler
:
{(
value
,
error
)
in
if
result
==
nil
{
return
}
if
error
!=
nil
{
let
userInfo
=
(
error
!
as
NSError
)
.
userInfo
self
.
onConsoleMessage
(
sourceURL
:
(
userInfo
[
"WKJavaScriptExceptionSourceURL"
]
as?
URL
)?
.
absoluteString
??
""
,
lineNumber
:
userInfo
[
"WKJavaScriptExceptionLineNumber"
]
as!
Int
,
message
:
userInfo
[
"WKJavaScriptExceptionMessage"
]
as!
String
,
messageLevel
:
"ERROR"
)
}
if
value
==
nil
{
result
!
(
""
)
return
}
do
{
let
data
:
Data
=
(
"["
+
String
(
describing
:
value
!
)
+
"]"
)
.
data
(
using
:
String
.
Encoding
.
utf8
,
allowLossyConversion
:
false
)
!
let
json
:
Array
<
Any
>
=
try
JSONSerialization
.
jsonObject
(
with
:
data
,
options
:
[])
as!
Array
<
Any
>
if
json
[
0
]
is
String
{
result
!
(
json
[
0
])
}
else
{
result
!
(
value
)
}
}
catch
let
error
as
NSError
{
result
!
(
FlutterError
(
code
:
"InAppBrowserFlutterPlugin"
,
message
:
"Failed to load:
\(
error
.
localizedDescription
)
"
,
details
:
error
))
}
})
}
}
public
func
injectScriptCode
(
source
:
String
,
result
:
FlutterResult
?)
{
let
jsWrapper
=
"(function(){return JSON.stringify(eval(%@));})();"
injectDeferredObject
(
source
:
source
,
withWrapper
:
jsWrapper
,
result
:
result
)
}
public
func
injectScriptFile
(
urlFile
:
String
,
result
:
FlutterResult
?)
{
let
jsWrapper
=
"(function(d) { var c = d.createElement('script'); c.src = %@; d.body.appendChild(c); })(document);"
injectDeferredObject
(
source
:
urlFile
,
withWrapper
:
jsWrapper
,
result
:
result
)
}
public
func
injectStyleCode
(
source
:
String
,
result
:
FlutterResult
?)
{
let
jsWrapper
=
"(function(d) { var c = d.createElement('style'); c.innerHTML = %@; d.body.appendChild(c); })(document);"
injectDeferredObject
(
source
:
source
,
withWrapper
:
jsWrapper
,
result
:
result
)
}
public
func
injectStyleFile
(
urlFile
:
String
,
result
:
FlutterResult
?)
{
let
jsWrapper
=
"(function(d) { var c = d.createElement('link'); c.rel='stylesheet', c.type='text/css'; c.href = %@; d.body.appendChild(c); })(document);"
injectDeferredObject
(
source
:
urlFile
,
withWrapper
:
jsWrapper
,
result
:
result
)
}
public
func
getCopyBackForwardList
()
->
[
String
:
Any
]
{
let
currentList
=
backForwardList
let
currentIndex
=
currentList
.
backList
.
count
var
completeList
=
currentList
.
backList
if
currentList
.
currentItem
!=
nil
{
completeList
.
append
(
currentList
.
currentItem
!
)
}
completeList
.
append
(
contentsOf
:
currentList
.
forwardList
)
var
history
:
[[
String
:
String
]]
=
[]
for
historyItem
in
completeList
{
var
historyItemMap
:
[
String
:
String
]
=
[:]
historyItemMap
[
"originalUrl"
]
=
historyItem
.
initialURL
.
absoluteString
historyItemMap
[
"title"
]
=
historyItem
.
title
historyItemMap
[
"url"
]
=
historyItem
.
url
.
absoluteString
history
.
append
(
historyItemMap
)
}
var
result
:
[
String
:
Any
]
=
[:]
result
[
"history"
]
=
history
result
[
"currentIndex"
]
=
currentIndex
return
result
;
}
public
func
webView
(
_
webView
:
WKWebView
,
decidePolicyFor
navigationAction
:
WKNavigationAction
,
decisionHandler
:
@escaping
(
WKNavigationActionPolicy
)
->
Void
)
{
if
let
url
=
navigationAction
.
request
.
url
{
if
url
.
absoluteString
!=
url
.
absoluteString
&&
(
options
?
.
useOnLoadResource
)
!
{
WKNavigationMap
[
url
.
absoluteString
]
=
[
"startTime"
:
currentTimeInMilliSeconds
(),
"request"
:
navigationAction
.
request
]
}
if
navigationAction
.
navigationType
==
.
linkActivated
&&
(
options
?
.
useShouldOverrideUrlLoading
)
!
{
shouldOverrideUrlLoading
(
url
:
url
)
decisionHandler
(
.
cancel
)
return
}
if
navigationAction
.
navigationType
==
.
linkActivated
||
navigationAction
.
navigationType
==
.
backForward
{
currentURL
=
url
}
}
decisionHandler
(
.
allow
)
}
public
func
webView
(
_
webView
:
WKWebView
,
decidePolicyFor
navigationResponse
:
WKNavigationResponse
,
decisionHandler
:
@escaping
(
WKNavigationResponsePolicy
)
->
Void
)
{
if
(
options
?
.
useOnLoadResource
)
!
{
if
let
url
=
navigationResponse
.
response
.
url
{
if
WKNavigationMap
[
url
.
absoluteString
]
!=
nil
{
let
startResourceTime
=
(
WKNavigationMap
[
url
.
absoluteString
]
!
[
"startTime"
]
as!
Int
)
let
startTime
=
startResourceTime
-
startPageTime
;
let
duration
=
currentTimeInMilliSeconds
()
-
startResourceTime
;
onLoadResource
(
response
:
navigationResponse
.
response
,
fromRequest
:
WKNavigationMap
[
url
.
absoluteString
]
!
[
"request"
]
as?
URLRequest
,
withData
:
Data
(),
startTime
:
startTime
,
duration
:
duration
)
}
}
}
decisionHandler
(
.
allow
)
}
public
func
webView
(
_
webView
:
WKWebView
,
didStartProvisionalNavigation
navigation
:
WKNavigation
!
)
{
self
.
startPageTime
=
currentTimeInMilliSeconds
()
onLoadStart
(
url
:
(
currentURL
?
.
absoluteString
)
!
)
}
public
func
webView
(
_
webView
:
WKWebView
,
didFinish
navigation
:
WKNavigation
!
)
{
self
.
WKNavigationMap
=
[:]
onLoadStop
(
url
:
(
url
?
.
absoluteString
)
!
)
}
public
func
webView
(
_
view
:
WKWebView
,
didFailProvisionalNavigation
navigation
:
WKNavigation
!
,
withError
error
:
Error
)
{
webView
(
view
,
didFail
:
navigation
,
withError
:
error
)
}
public
func
webView
(
_
webView
:
WKWebView
,
didFail
navigation
:
WKNavigation
!
,
withError
error
:
Error
)
{
onLoadError
(
url
:
(
currentURL
?
.
absoluteString
)
!
,
error
:
error
)
}
public
func
scrollViewDidScroll
(
_
scrollView
:
UIScrollView
)
{
if
navigationDelegate
!=
nil
{
let
x
=
Int
(
scrollView
.
contentOffset
.
x
/
scrollView
.
contentScaleFactor
)
let
y
=
Int
(
scrollView
.
contentOffset
.
y
/
scrollView
.
contentScaleFactor
)
onScrollChanged
(
x
:
x
,
y
:
y
)
}
}
public
func
onLoadStart
(
url
:
String
)
{
var
arguments
:
[
String
:
Any
]
=
[
"url"
:
url
]
if
IABController
!=
nil
{
arguments
[
"uuid"
]
=
IABController
!.
uuid
}
getChannel
()
.
invokeMethod
(
"onLoadStart"
,
arguments
:
arguments
)
}
public
func
onLoadStop
(
url
:
String
)
{
var
arguments
:
[
String
:
Any
]
=
[
"url"
:
url
]
if
IABController
!=
nil
{
arguments
[
"uuid"
]
=
IABController
!.
uuid
}
getChannel
()
.
invokeMethod
(
"onLoadStop"
,
arguments
:
arguments
)
}
public
func
onLoadError
(
url
:
String
,
error
:
Error
)
{
var
arguments
:
[
String
:
Any
]
=
[
"url"
:
url
,
"code"
:
error
.
_code
,
"message"
:
error
.
localizedDescription
]
if
IABController
!=
nil
{
arguments
[
"uuid"
]
=
IABController
!.
uuid
}
getChannel
()
.
invokeMethod
(
"onLoadError"
,
arguments
:
arguments
)
}
public
func
onProgressChanged
(
progress
:
Int
)
{
var
arguments
:
[
String
:
Any
]
=
[
"progress"
:
progress
]
if
IABController
!=
nil
{
arguments
[
"uuid"
]
=
IABController
!.
uuid
}
getChannel
()
.
invokeMethod
(
"onProgressChanged"
,
arguments
:
arguments
)
}
public
func
onLoadResource
(
response
:
URLResponse
,
fromRequest
request
:
URLRequest
?,
withData
data
:
Data
,
startTime
:
Int
,
duration
:
Int
)
{
var
headersResponse
=
(
response
as!
HTTPURLResponse
)
.
allHeaderFields
as!
[
String
:
String
]
headersResponse
.
lowercaseKeys
()
var
headersRequest
=
request
!.
allHTTPHeaderFields
!
as
[
String
:
String
]
headersRequest
.
lowercaseKeys
()
var
arguments
:
[
String
:
Any
]
=
[
"response"
:
[
"url"
:
response
.
url
!.
absoluteString
,
"statusCode"
:
(
response
as!
HTTPURLResponse
)
.
statusCode
,
"headers"
:
headersResponse
,
"startTime"
:
startTime
,
"duration"
:
duration
,
"data"
:
data
],
"request"
:
[
"url"
:
request
!.
url
!.
absoluteString
,
"headers"
:
headersRequest
,
"method"
:
request
!.
httpMethod
!
]
]
if
IABController
!=
nil
{
arguments
[
"uuid"
]
=
IABController
!.
uuid
}
getChannel
()
.
invokeMethod
(
"onLoadResource"
,
arguments
:
arguments
)
}
public
func
onScrollChanged
(
x
:
Int
,
y
:
Int
)
{
var
arguments
:
[
String
:
Any
]
=
[
"x"
:
x
,
"y"
:
y
]
if
IABController
!=
nil
{
arguments
[
"uuid"
]
=
IABController
!.
uuid
}
getChannel
()
.
invokeMethod
(
"onScrollChanged"
,
arguments
:
arguments
)
}
public
func
shouldOverrideUrlLoading
(
url
:
URL
)
{
var
arguments
:
[
String
:
Any
]
=
[
"url"
:
url
.
absoluteString
]
if
IABController
!=
nil
{
arguments
[
"uuid"
]
=
IABController
!.
uuid
}
getChannel
()
.
invokeMethod
(
"shouldOverrideUrlLoading"
,
arguments
:
arguments
)
}
public
func
onConsoleMessage
(
sourceURL
:
String
,
lineNumber
:
Int
,
message
:
String
,
messageLevel
:
String
)
{
var
arguments
:
[
String
:
Any
]
=
[
"sourceURL"
:
sourceURL
,
"lineNumber"
:
lineNumber
,
"message"
:
message
,
"messageLevel"
:
messageLevel
]
if
IABController
!=
nil
{
arguments
[
"uuid"
]
=
IABController
!.
uuid
}
getChannel
()
.
invokeMethod
(
"onConsoleMessage"
,
arguments
:
arguments
)
}
public
func
onCallJsHandler
(
handlerName
:
String
,
args
:
String
)
{
var
arguments
:
[
String
:
Any
]
=
[
"handlerName"
:
handlerName
,
"args"
:
args
]
if
IABController
!=
nil
{
arguments
[
"uuid"
]
=
IABController
!.
uuid
}
getChannel
()
.
invokeMethod
(
"onCallJsHandler"
,
arguments
:
arguments
)
}
public
func
userContentController
(
_
userContentController
:
WKUserContentController
,
didReceive
message
:
WKScriptMessage
)
{
if
message
.
name
.
starts
(
with
:
"console"
)
{
var
messageLevel
=
"LOG"
switch
(
message
.
name
)
{
case
"consoleLog"
:
messageLevel
=
"LOG"
break
;
case
"consoleDebug"
:
// on Android, console.debug is TIP
messageLevel
=
"TIP"
break
;
case
"consoleError"
:
messageLevel
=
"ERROR"
break
;
case
"consoleInfo"
:
// on Android, console.info is LOG
messageLevel
=
"LOG"
break
;
case
"consoleWarn"
:
messageLevel
=
"WARNING"
break
;
default
:
messageLevel
=
"LOG"
break
;
}
onConsoleMessage
(
sourceURL
:
""
,
lineNumber
:
1
,
message
:
message
.
body
as!
String
,
messageLevel
:
messageLevel
)
}
else
if
message
.
name
==
"resourceLoaded"
&&
(
options
?
.
useOnLoadResource
)
!
{
if
let
resource
=
convertToDictionary
(
text
:
message
.
body
as!
String
)
{
let
url
=
URL
(
string
:
resource
[
"name"
]
as!
String
)
!
if
!
UIApplication
.
shared
.
canOpenURL
(
url
)
{
return
}
let
startTime
=
Int
(
resource
[
"startTime"
]
as!
Double
)
let
duration
=
Int
(
resource
[
"duration"
]
as!
Double
)
var
urlRequest
=
URLRequest
(
url
:
url
)
urlRequest
.
allHTTPHeaderFields
=
[:]
let
config
=
URLSessionConfiguration
.
default
let
session
=
URLSession
(
configuration
:
config
)
let
task
=
session
.
dataTask
(
with
:
urlRequest
)
{
(
data
,
response
,
error
)
in
if
error
!=
nil
{
print
(
error
)
return
}
var
withData
=
data
if
withData
==
nil
{
withData
=
Data
()
}
self
.
onLoadResource
(
response
:
response
!
,
fromRequest
:
urlRequest
,
withData
:
withData
!
,
startTime
:
startTime
,
duration
:
duration
)
}
task
.
resume
()
}
}
else
if
message
.
name
==
"callHandler"
{
let
body
=
message
.
body
as!
[
String
:
Any
]
let
handlerName
=
body
[
"handlerName"
]
as!
String
let
args
=
body
[
"args"
]
as!
String
onCallJsHandler
(
handlerName
:
handlerName
,
args
:
args
)
}
}
private
func
getChannel
()
->
FlutterMethodChannel
{
return
(
IABController
!=
nil
)
?
SwiftFlutterPlugin
.
channel
!
:
IAWController
!.
channel
!
;
}
}
ios/Classes/SwiftFlutterPlugin.swift
View file @
8b5a6347
...
...
@@ -36,7 +36,7 @@ extension Dictionary where Key: ExpressibleByStringLiteral {
public
class
SwiftFlutterPlugin
:
NSObject
,
FlutterPlugin
{
static
var
registrar
:
FlutterPluginRegistrar
?
var
channel
:
FlutterMethodChannel
static
var
channel
:
FlutterMethodChannel
?
var
webViewControllers
:
[
String
:
InAppBrowserWebViewController
?]
=
[:]
var
safariViewControllers
:
[
String
:
Any
?]
=
[:]
...
...
@@ -45,7 +45,7 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
private
var
previousStatusBarStyle
=
-
1
public
init
(
with
registrar
:
FlutterPluginRegistrar
)
{
channel
=
FlutterMethodChannel
(
name
:
"com.pichillilorenzo/flutter_inappbrowser"
,
binaryMessenger
:
registrar
.
messenger
())
SwiftFlutterPlugin
.
channel
=
FlutterMethodChannel
(
name
:
"com.pichillilorenzo/flutter_inappbrowser"
,
binaryMessenger
:
registrar
.
messenger
())
}
public
static
func
register
(
with
registrar
:
FlutterPluginRegistrar
)
{
...
...
@@ -220,14 +220,14 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
}
break
case
"setOptions"
:
let
optionsType
=
arguments
!
[
"optionsType"
]
as!
String
;
let
optionsType
=
arguments
!
[
"optionsType"
]
as!
String
switch
(
optionsType
){
case
"InAppBrowserOptions"
:
let
inAppBrowserOptions
=
InAppBrowserOptions
()
;
let
inAppBro
eserOptionsMap
=
arguments
!
[
"options"
]
as!
[
String
:
Any
];
inAppBrowserOptions
.
parse
(
options
:
inAppBro
eserOptionsMap
);
self
.
setOptions
(
uuid
:
uuid
,
options
:
inAppBrowserOptions
,
optionsMap
:
inAppBro
eserOptionsMap
);
break
;
let
inAppBrowserOptions
=
InAppBrowserOptions
()
let
inAppBro
wserOptionsMap
=
arguments
!
[
"options"
]
as!
[
String
:
Any
]
inAppBrowserOptions
.
parse
(
options
:
inAppBro
wserOptionsMap
)
self
.
setOptions
(
uuid
:
uuid
,
options
:
inAppBrowserOptions
,
optionsMap
:
inAppBro
wserOptionsMap
)
break
default
:
result
(
FlutterError
(
code
:
"InAppBrowserFlutterPlugin"
,
message
:
"Options "
+
optionsType
+
" not available."
,
details
:
nil
))
}
...
...
@@ -237,8 +237,8 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
result
(
self
.
getOptions
(
uuid
:
uuid
))
break
case
"getCopyBackForwardList"
:
result
(
self
.
getCopyBackForwardList
(
uuid
:
uuid
))
;
break
;
result
(
self
.
getCopyBackForwardList
(
uuid
:
uuid
))
break
default
:
result
(
FlutterMethodNotImplemented
)
break
...
...
@@ -279,7 +279,7 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
let
optionsFallback
=
(
arguments
[
"optionsFallback"
]
as?
[
String
:
Any
])
!
open
(
uuid
:
uuid
,
uuidFallback
:
uuidFallback
,
inAppBrowser
:
absoluteUrl
!
,
headers
:
headers
,
withOptions
:
safariOptions
,
useChromeSafariBrowser
:
true
,
withOptionsFallback
:
optionsFallback
,
result
:
result
)
;
open
(
uuid
:
uuid
,
uuidFallback
:
uuidFallback
,
inAppBrowser
:
absoluteUrl
!
,
headers
:
headers
,
withOptions
:
safariOptions
,
useChromeSafariBrowser
:
true
,
withOptionsFallback
:
optionsFallback
,
result
:
result
)
}
else
{
let
options
=
(
arguments
[
"options"
]
as?
[
String
:
Any
])
!
...
...
@@ -702,21 +702,21 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
func
onBrowserCreated
(
uuid
:
String
,
webView
:
WKWebView
)
{
if
let
webViewController
=
self
.
webViewControllers
[
uuid
]
{
channel
.
invokeMethod
(
"onBrowserCreated"
,
arguments
:
[
"uuid"
:
uuid
])
SwiftFlutterPlugin
.
channel
!
.
invokeMethod
(
"onBrowserCreated"
,
arguments
:
[
"uuid"
:
uuid
])
}
}
func
onLoadStart
(
uuid
:
String
,
webView
:
WKWebView
)
{
if
let
webViewController
=
self
.
webViewControllers
[
uuid
]
{
let
url
:
String
=
webViewController
!.
currentURL
!.
absoluteString
channel
.
invokeMethod
(
"onLoadStart"
,
arguments
:
[
"uuid"
:
uuid
,
"url"
:
url
])
SwiftFlutterPlugin
.
channel
!
.
invokeMethod
(
"onLoadStart"
,
arguments
:
[
"uuid"
:
uuid
,
"url"
:
url
])
}
}
func
onLoadStop
(
uuid
:
String
,
webView
:
WKWebView
)
{
if
let
webViewController
=
self
.
webViewControllers
[
uuid
]
{
let
url
:
String
=
webViewController
!.
currentURL
!.
absoluteString
channel
.
invokeMethod
(
"onLoadStop"
,
arguments
:
[
"uuid"
:
uuid
,
"url"
:
url
])
SwiftFlutterPlugin
.
channel
!
.
invokeMethod
(
"onLoadStop"
,
arguments
:
[
"uuid"
:
uuid
,
"url"
:
url
])
}
}
...
...
@@ -724,13 +724,13 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
if
let
webViewController
=
self
.
webViewControllers
[
uuid
]
{
let
url
:
String
=
webViewController
!.
currentURL
!.
absoluteString
let
arguments
=
[
"uuid"
:
uuid
,
"url"
:
url
,
"code"
:
error
.
_code
,
"message"
:
error
.
localizedDescription
]
as
[
String
:
Any
]
channel
.
invokeMethod
(
"onLoadError"
,
arguments
:
arguments
)
SwiftFlutterPlugin
.
channel
!
.
invokeMethod
(
"onLoadError"
,
arguments
:
arguments
)
}
}
func
onProgressChanged
(
uuid
:
String
,
webView
:
WKWebView
,
progress
:
Int
)
{
if
let
webViewController
=
self
.
webViewControllers
[
uuid
]
{
channel
.
invokeMethod
(
"onProgressChanged"
,
arguments
:
[
"uuid"
:
uuid
,
"progress"
:
progress
])
SwiftFlutterPlugin
.
channel
!
.
invokeMethod
(
"onProgressChanged"
,
arguments
:
[
"uuid"
:
uuid
,
"progress"
:
progress
])
}
}
...
...
@@ -758,50 +758,50 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
"method"
:
request
!.
httpMethod
!
]
]
channel
.
invokeMethod
(
"onLoadResource"
,
arguments
:
arguments
)
SwiftFlutterPlugin
.
channel
!
.
invokeMethod
(
"onLoadResource"
,
arguments
:
arguments
)
}
}
func
onScrollChanged
(
uuid
:
String
,
webView
:
WKWebView
,
x
:
Int
,
y
:
Int
)
{
if
let
webViewController
=
self
.
webViewControllers
[
uuid
]
{
channel
.
invokeMethod
(
"onScrollChanged"
,
arguments
:
[
"uuid"
:
uuid
,
"x"
:
x
,
"y"
:
y
])
SwiftFlutterPlugin
.
channel
!
.
invokeMethod
(
"onScrollChanged"
,
arguments
:
[
"uuid"
:
uuid
,
"x"
:
x
,
"y"
:
y
])
}
}
func
onExit
(
uuid
:
String
)
{
channel
.
invokeMethod
(
"onExit"
,
arguments
:
[
"uuid"
:
uuid
])
SwiftFlutterPlugin
.
channel
!
.
invokeMethod
(
"onExit"
,
arguments
:
[
"uuid"
:
uuid
])
}
func
shouldOverrideUrlLoading
(
uuid
:
String
,
webView
:
WKWebView
,
url
:
URL
)
{
if
self
.
webViewControllers
[
uuid
]
!=
nil
{
channel
.
invokeMethod
(
"shouldOverrideUrlLoading"
,
arguments
:
[
"uuid"
:
uuid
,
"url"
:
url
.
absoluteString
])
SwiftFlutterPlugin
.
channel
!
.
invokeMethod
(
"shouldOverrideUrlLoading"
,
arguments
:
[
"uuid"
:
uuid
,
"url"
:
url
.
absoluteString
])
}
}
func
onConsoleMessage
(
uuid
:
String
,
sourceURL
:
String
,
lineNumber
:
Int
,
message
:
String
,
messageLevel
:
String
)
{
if
self
.
webViewControllers
[
uuid
]
!=
nil
{
channel
.
invokeMethod
(
"onConsoleMessage"
,
arguments
:
[
"uuid"
:
uuid
,
"sourceURL"
:
sourceURL
,
"lineNumber"
:
lineNumber
,
"message"
:
message
,
"messageLevel"
:
messageLevel
])
SwiftFlutterPlugin
.
channel
!
.
invokeMethod
(
"onConsoleMessage"
,
arguments
:
[
"uuid"
:
uuid
,
"sourceURL"
:
sourceURL
,
"lineNumber"
:
lineNumber
,
"message"
:
message
,
"messageLevel"
:
messageLevel
])
}
}
func
onChromeSafariBrowserOpened
(
uuid
:
String
)
{
if
self
.
safariViewControllers
[
uuid
]
!=
nil
{
channel
.
invokeMethod
(
"onChromeSafariBrowserOpened"
,
arguments
:
[
"uuid"
:
uuid
])
SwiftFlutterPlugin
.
channel
!
.
invokeMethod
(
"onChromeSafariBrowserOpened"
,
arguments
:
[
"uuid"
:
uuid
])
}
}
func
onChromeSafariBrowserLoaded
(
uuid
:
String
)
{
if
self
.
safariViewControllers
[
uuid
]
!=
nil
{
channel
.
invokeMethod
(
"onChromeSafariBrowserLoaded"
,
arguments
:
[
"uuid"
:
uuid
])
SwiftFlutterPlugin
.
channel
!
.
invokeMethod
(
"onChromeSafariBrowserLoaded"
,
arguments
:
[
"uuid"
:
uuid
])
}
}
func
onChromeSafariBrowserClosed
(
uuid
:
String
)
{
channel
.
invokeMethod
(
"onChromeSafariBrowserClosed"
,
arguments
:
[
"uuid"
:
uuid
])
SwiftFlutterPlugin
.
channel
!
.
invokeMethod
(
"onChromeSafariBrowserClosed"
,
arguments
:
[
"uuid"
:
uuid
])
}
func
onCallJsHandler
(
uuid
:
String
,
webView
:
WKWebView
,
handlerName
:
String
,
args
:
String
)
{
channel
.
invokeMethod
(
"onCallJsHandler"
,
arguments
:
[
"uuid"
:
uuid
,
"handlerName"
:
handlerName
,
"args"
:
args
])
SwiftFlutterPlugin
.
channel
!
.
invokeMethod
(
"onCallJsHandler"
,
arguments
:
[
"uuid"
:
uuid
,
"handlerName"
:
handlerName
,
"args"
:
args
])
}
func
safariExit
(
uuid
:
String
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment