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
d89cd5df
Commit
d89cd5df
authored
Sep 21, 2018
by
pichillilorenzo
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
updated android and ios options, added downloader on android, fixed back-button webview android
parent
fb689181
Changes
13
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
244 additions
and
519 deletions
+244
-519
.idea/workspace.xml
.idea/workspace.xml
+36
-24
android/src/main/AndroidManifest.xml
android/src/main/AndroidManifest.xml
+1
-0
android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowser.java
...om/pichillilorenzo/flutter_inappbrowser/InAppBrowser.java
+18
-453
android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserOptions.java
...illilorenzo/flutter_inappbrowser/InAppBrowserOptions.java
+11
-9
android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserWebChromeClient.java
...nzo/flutter_inappbrowser/InAppBrowserWebChromeClient.java
+2
-4
android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserWebViewClient.java
...renzo/flutter_inappbrowser/InAppBrowserWebViewClient.java
+1
-0
android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/RequestPermissionHandler.java
...orenzo/flutter_inappbrowser/RequestPermissionHandler.java
+46
-0
android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/WebViewActivity.java
...pichillilorenzo/flutter_inappbrowser/WebViewActivity.java
+119
-22
android/src/main/res/layout/activity_web_view.xml
android/src/main/res/layout/activity_web_view.xml
+1
-0
android/src/main/res/menu/menu_main.xml
android/src/main/res/menu/menu_main.xml
+1
-1
example/lib/main.dart
example/lib/main.dart
+2
-0
ios/Classes/InAppBrowserOptions.swift
ios/Classes/InAppBrowserOptions.swift
+2
-2
ios/Classes/InAppBrowserWebViewController.swift
ios/Classes/InAppBrowserWebViewController.swift
+4
-4
No files found.
.idea/workspace.xml
View file @
d89cd5df
This diff is collapsed.
Click to expand it.
android/src/main/AndroidManifest.xml
View file @
d89cd5df
...
...
@@ -3,6 +3,7 @@
package=
"com.pichillilorenzo.flutter_inappbrowser"
>
<uses-permission
android:name=
"android.permission.INTERNET"
/>
<uses-permission
android:name=
"android.permission.WRITE_EXTERNAL_STORAGE"
/>
<application
android:theme=
"@style/AppTheme"
>
...
...
android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowser.java
View file @
d89cd5df
This diff is collapsed.
Click to expand it.
android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserOptions.java
View file @
d89cd5df
package
com.pichillilorenzo.flutter_inappbrowser
;
import
android.os.Build
;
import
android.support.annotation.RequiresApi
;
import
android.util.Log
;
import
java.lang.reflect.Field
;
...
...
@@ -14,11 +12,14 @@ public class InAppBrowserOptions {
boolean
clearCache
=
false
;
boolean
clearSessionCache
=
false
;
String
userAgent
=
""
;
boolean
spinne
r
=
true
;
boolean
progressBa
r
=
true
;
boolean
hidden
=
false
;
boolean
toolbarTop
=
true
;
String
toolbarTopColor
=
"toolbarTopColor"
;
String
toolbarTopBackgroundColor
=
""
;
String
toolbarTopFixedTitle
=
""
;
boolean
hideUrlBar
=
false
;
boolean
hideTitleBar
=
false
;
boolean
closeOnCannotGoBack
=
true
;
boolean
mediaPlaybackRequiresUserGesture
=
true
;
boolean
javaScriptCanOpenWindowsAutomatically
=
false
;
boolean
javaScriptEnabled
=
true
;
...
...
@@ -29,15 +30,16 @@ public class InAppBrowserOptions {
boolean
useWideViewPort
=
true
;
boolean
safeBrowsingEnabled
=
true
;
@RequiresApi
(
api
=
Build
.
VERSION_CODES
.
KITKAT
)
public
void
parse
(
HashMap
<
String
,
Object
>
options
)
{
Iterator
it
=
options
.
entrySet
().
iterator
();
while
(
it
.
hasNext
())
{
Map
.
Entry
<
String
,
Object
>
pair
=
(
Map
.
Entry
<
String
,
Object
>)
it
.
next
();
try
{
this
.
getClass
().
getField
(
pair
.
getKey
()).
set
(
this
,
pair
.
getValue
());
}
catch
(
NoSuchFieldException
|
IllegalAccessException
e
)
{
// silent
this
.
getClass
().
getDeclaredField
(
pair
.
getKey
()).
set
(
this
,
pair
.
getValue
());
}
catch
(
NoSuchFieldException
e
)
{
Log
.
d
(
"InAppBrowserOptions"
,
e
.
getMessage
());
}
catch
(
IllegalAccessException
e
)
{
Log
.
d
(
"InAppBrowserOptions"
,
e
.
getMessage
());
}
}
}
...
...
@@ -48,7 +50,7 @@ public class InAppBrowserOptions {
try
{
options
.
put
(
f
.
getName
(),
f
.
get
(
this
));
}
catch
(
IllegalAccessException
e
)
{
// silent
Log
.
d
(
"InAppBrowserOptions"
,
e
.
getMessage
());
}
}
return
options
;
...
...
android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserWebChromeClient.java
View file @
d89cd5df
...
...
@@ -4,8 +4,6 @@ import android.content.Intent;
import
android.graphics.Bitmap
;
import
android.net.Uri
;
import
android.os.Build
;
import
android.support.annotation.RequiresApi
;
import
android.util.Log
;
import
android.view.View
;
import
android.webkit.ValueCallback
;
import
android.webkit.WebChromeClient
;
...
...
@@ -44,8 +42,8 @@ public class InAppBrowserWebChromeClient extends WebChromeClient {
@Override
public
void
onReceivedTitle
(
WebView
view
,
String
title
)
{
super
.
onReceivedTitle
(
view
,
title
);
if
(
activity
.
getSupportActionBar
()
!=
null
)
activity
.
getSupportActionBar
()
.
setTitle
(
title
);
if
(
activity
.
actionBar
!=
null
&&
activity
.
options
.
toolbarTopFixedTitle
.
isEmpty
()
)
activity
.
actionBar
.
setTitle
(
title
);
}
@Override
...
...
android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserWebViewClient.java
View file @
d89cd5df
...
...
@@ -150,4 +150,5 @@ public class InAppBrowserWebViewClient extends WebViewClient {
// By default handle 401 like we'd normally do!
super
.
onReceivedHttpAuthRequest
(
view
,
handler
,
host
,
realm
);
}
}
android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/RequestPermissionHandler.java
0 → 100644
View file @
d89cd5df
package
com.pichillilorenzo.flutter_inappbrowser
;
import
android.app.Activity
;
import
android.content.pm.PackageManager
;
import
android.support.annotation.NonNull
;
import
android.support.v4.app.ActivityCompat
;
import
android.support.v4.content.ContextCompat
;
import
java.util.Arrays
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
public
abstract
class
RequestPermissionHandler
implements
ActivityCompat
.
OnRequestPermissionsResultCallback
{
public
static
int
REQUEST_CODE_WRITE_EXTERNAL_STORAGE
=
0
;
private
static
Map
<
Integer
,
List
<
Runnable
>>
actionDictionary
=
new
HashMap
<>();
public
static
void
checkAndRun
(
Activity
activity
,
String
permission
,
int
requestCode
,
Runnable
runnable
)
{
int
permissionCheck
=
ContextCompat
.
checkSelfPermission
(
activity
.
getApplicationContext
(),
permission
);
if
(
permissionCheck
!=
PackageManager
.
PERMISSION_GRANTED
)
{
if
(
actionDictionary
.
containsKey
(
requestCode
))
actionDictionary
.
get
(
requestCode
).
add
(
runnable
);
else
actionDictionary
.
put
(
requestCode
,
Arrays
.
asList
(
runnable
));
ActivityCompat
.
requestPermissions
(
activity
,
new
String
[]{
permission
},
requestCode
);
}
else
runnable
.
run
();
}
@Override
public
void
onRequestPermissionsResult
(
int
requestCode
,
@NonNull
String
permissions
[],
@NonNull
int
[]
grantResults
)
{
if
((
grantResults
.
length
>
0
)
&&
(
grantResults
[
0
]
==
PackageManager
.
PERMISSION_GRANTED
))
{
List
<
Runnable
>
callbacks
=
actionDictionary
.
get
(
requestCode
);
for
(
Runnable
runnable
:
callbacks
)
{
runnable
.
run
();
callbacks
.
remove
(
runnable
);
}
}
}
}
android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/WebViewActivity.java
View file @
d89cd5df
package
com.pichillilorenzo.flutter_inappbrowser
;
import
android.annotation.TargetApi
;
import
android.app.ProgressDialog
;
import
android.Manifest
;
import
android.app.Activity
;
import
android.app.DownloadManager
;
import
android.content.Context
;
import
android.content.Intent
;
import
android.content.pm.PackageManager
;
import
android.graphics.Color
;
import
android.graphics.drawable.ColorDrawable
;
import
android.net.Uri
;
import
android.os.Build
;
import
android.os.Environment
;
import
android.support.annotation.RequiresApi
;
import
android.support.v4.app.ActivityCompat
;
import
android.support.v4.content.ContextCompat
;
import
android.support.v7.app.ActionBar
;
import
android.support.v7.app.AppCompatActivity
;
import
android.os.Bundle
;
import
android.util.Log
;
import
android.view.Display
;
import
android.view.KeyEvent
;
import
android.view.Menu
;
import
android.view.MenuInflater
;
import
android.view.MenuItem
;
import
android.view.View
;
import
android.view.WindowManager
;
import
android.webkit.CookieManager
;
import
android.webkit.DownloadListener
;
import
android.webkit.URLUtil
;
import
android.webkit.ValueCallback
;
import
android.webkit.WebSettings
;
import
android.webkit.WebView
;
import
android.widget.AutoCompleteTextView
;
import
android.widget.ImageView
;
import
android.widget.ProgressBar
;
import
android.widget.SearchView
;
import
android.widget.Toast
;
import
java.util.HashMap
;
import
java.util.Map
;
...
...
@@ -31,6 +43,7 @@ import io.flutter.plugin.common.MethodChannel;
public
class
WebViewActivity
extends
AppCompatActivity
{
WebView
webView
;
ActionBar
actionBar
;
InAppBrowserWebViewClient
inAppBrowserWebViewClient
;
InAppBrowserWebChromeClient
inAppBrowserWebChromeClient
;
SearchView
searchView
;
...
...
@@ -38,23 +51,23 @@ public class WebViewActivity extends AppCompatActivity {
ProgressBar
progressBar
;
public
boolean
isLoading
=
false
;
@RequiresApi
(
api
=
Build
.
VERSION_CODES
.
KITKAT
)
@Override
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
setContentView
(
R
.
layout
.
activity_web_view
);
webView
=
findViewById
(
R
.
id
.
webView
);
progressBar
=
findViewById
(
R
.
id
.
progressBar
);
progressBar
.
setMax
(
100
);
Bundle
b
=
getIntent
().
getExtras
();
String
url
=
b
.
getString
(
"url"
);
options
=
new
InAppBrowserOptions
();
options
.
parse
((
HashMap
<
String
,
Object
>)
b
.
getSerializable
(
"options"
));
InAppBrowser
.
webViewActivity
=
this
;
actionBar
=
getSupportActionBar
();
prepareWebView
();
webView
.
loadUrl
(
url
);
...
...
@@ -69,47 +82,96 @@ public class WebViewActivity extends AppCompatActivity {
inAppBrowserWebViewClient
=
new
InAppBrowserWebViewClient
(
this
);
webView
.
setWebViewClient
(
inAppBrowserWebViewClient
);
final
Activity
activity
=
this
;
webView
.
setDownloadListener
(
new
DownloadListener
()
{
@Override
public
void
onDownloadStart
(
final
String
url
,
final
String
userAgent
,
final
String
contentDisposition
,
final
String
mimetype
,
final
long
contentLength
)
{
RequestPermissionHandler
.
checkAndRun
(
activity
,
Manifest
.
permission
.
WRITE_EXTERNAL_STORAGE
,
RequestPermissionHandler
.
REQUEST_CODE_WRITE_EXTERNAL_STORAGE
,
new
Runnable
(){
@Override
public
void
run
(){
DownloadManager
.
Request
request
=
new
DownloadManager
.
Request
(
Uri
.
parse
(
url
));
final
String
filename
=
URLUtil
.
guessFileName
(
url
,
contentDisposition
,
mimetype
);
request
.
allowScanningByMediaScanner
();
request
.
setNotificationVisibility
(
DownloadManager
.
Request
.
VISIBILITY_VISIBLE_NOTIFY_COMPLETED
);
//Notify client once download is completed!
request
.
setVisibleInDownloadsUi
(
true
);
request
.
setDestinationInExternalPublicDir
(
Environment
.
DIRECTORY_DOWNLOADS
,
filename
);
DownloadManager
dm
=
(
DownloadManager
)
getSystemService
(
DOWNLOAD_SERVICE
);
if
(
dm
!=
null
)
{
dm
.
enqueue
(
request
);
Toast
.
makeText
(
getApplicationContext
(),
"Downloading File: "
+
filename
,
//To notify the Client that the file is being downloaded
Toast
.
LENGTH_LONG
).
show
();
}
else
{
Toast
.
makeText
(
getApplicationContext
(),
"Cannot Download File: "
+
filename
,
//To notify the Client that the file cannot be downloaded
Toast
.
LENGTH_LONG
).
show
();
}
}
});
}
});
WebSettings
settings
=
webView
.
getSettings
();
if
(
options
.
hidden
)
hide
();
else
show
();
settings
.
setJavaScriptEnabled
(
options
.
javaScriptEnabled
);
settings
.
setJavaScriptCanOpenWindowsAutomatically
(
options
.
javaScriptCanOpenWindowsAutomatically
);
settings
.
setBuiltInZoomControls
(
options
.
builtInZoomControls
);
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
O
)
{
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
O
)
settings
.
setSafeBrowsingEnabled
(
options
.
safeBrowsingEnabled
);
}
settings
.
setMediaPlaybackRequiresUserGesture
(
options
.
mediaPlaybackRequiresUserGesture
);
settings
.
setDatabaseEnabled
(
options
.
databaseEnabled
);
settings
.
setDomStorageEnabled
(
options
.
domStorageEnabled
);
if
(!
options
.
userAgent
.
isEmpty
())
{
if
(!
options
.
userAgent
.
isEmpty
())
settings
.
setUserAgentString
(
options
.
userAgent
);
}
if
(
options
.
clearCache
)
{
if
(
options
.
clearCache
)
clearCache
();
}
else
if
(
options
.
clearSessionCache
)
{
else
if
(
options
.
clearSessionCache
)
CookieManager
.
getInstance
().
removeSessionCookie
();
}
// Enable Thirdparty Cookies on >=Android 5.0 device
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
LOLLIPOP
)
{
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
LOLLIPOP
)
CookieManager
.
getInstance
().
setAcceptThirdPartyCookies
(
webView
,
true
);
}
settings
.
setLoadWithOverviewMode
(
true
);
settings
.
setUseWideViewPort
(
options
.
useWideViewPort
);
settings
.
setSupportZoom
(
options
.
supportZoom
);
// fix webview scaling
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
KITKAT
)
{
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
KITKAT
)
settings
.
setLayoutAlgorithm
(
WebSettings
.
LayoutAlgorithm
.
TEXT_AUTOSIZING
);
}
else
{
else
settings
.
setTextZoom
(
100
);
if
(
options
.
progressBar
)
{
progressBar
=
findViewById
(
R
.
id
.
progressBar
);
progressBar
.
setMax
(
100
);
}
actionBar
.
setDisplayShowTitleEnabled
(!
options
.
hideTitleBar
);
if
(!
options
.
toolbarTop
)
actionBar
.
hide
();
if
(!
options
.
toolbarTopBackgroundColor
.
isEmpty
())
actionBar
.
setBackgroundDrawable
(
new
ColorDrawable
(
Color
.
parseColor
(
options
.
toolbarTopBackgroundColor
)));
if
(!
options
.
toolbarTopFixedTitle
.
isEmpty
())
actionBar
.
setTitle
(
options
.
toolbarTopFixedTitle
);
}
@Override
...
...
@@ -119,13 +181,25 @@ public class WebViewActivity extends AppCompatActivity {
inflater
.
inflate
(
R
.
menu
.
menu_main
,
menu
);
searchView
=
(
SearchView
)
menu
.
findItem
(
R
.
id
.
menu_search
).
getActionView
();
searchView
.
setFocusable
(
true
);
if
(
options
.
hideUrlBar
)
menu
.
findItem
(
R
.
id
.
menu_search
).
setVisible
(
false
);
searchView
.
setQuery
(
webView
.
getUrl
(),
false
);
getSupportActionBar
().
setTitle
(
webView
.
getTitle
());
if
(
options
.
toolbarTopFixedTitle
.
isEmpty
())
actionBar
.
setTitle
(
webView
.
getTitle
());
searchView
.
setOnQueryTextListener
(
new
SearchView
.
OnQueryTextListener
()
{
@Override
public
boolean
onQueryTextSubmit
(
String
query
)
{
if
(!
query
.
isEmpty
())
{
webView
.
loadUrl
(
query
);
searchView
.
setQuery
(
""
,
false
);
searchView
.
setIconified
(
true
);
return
true
;
}
return
false
;
}
...
...
@@ -133,6 +207,26 @@ public class WebViewActivity extends AppCompatActivity {
public
boolean
onQueryTextChange
(
String
newText
)
{
return
false
;
}
});
searchView
.
setOnCloseListener
(
new
SearchView
.
OnCloseListener
()
{
@Override
public
boolean
onClose
()
{
if
(
searchView
.
getQuery
().
toString
().
isEmpty
())
searchView
.
setQuery
(
webView
.
getUrl
(),
false
);
return
false
;
}
});
searchView
.
setOnQueryTextFocusChangeListener
(
new
View
.
OnFocusChangeListener
()
{
@Override
public
void
onFocusChange
(
View
view
,
boolean
b
)
{
if
(!
b
)
{
searchView
.
setQuery
(
""
,
false
);
searchView
.
setIconified
(
true
);
}
}
});
return
true
;
...
...
@@ -158,7 +252,10 @@ public class WebViewActivity extends AppCompatActivity {
public
boolean
onKeyDown
(
int
keyCode
,
KeyEvent
event
)
{
if
((
keyCode
==
KeyEvent
.
KEYCODE_BACK
))
{
if
(
canGoBack
())
goBack
();
else
if
(
options
.
closeOnCannotGoBack
)
close
();
return
true
;
}
return
super
.
onKeyDown
(
keyCode
,
event
);
...
...
android/src/main/res/layout/activity_web_view.xml
View file @
d89cd5df
...
...
@@ -4,6 +4,7 @@
xmlns:tools=
"http://schemas.android.com/tools"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:clickable=
"true"
android:focusableInTouchMode=
"true"
android:orientation=
"vertical"
tools:context=
".WebViewActivity"
>
...
...
android/src/main/res/menu/menu_main.xml
View file @
d89cd5df
...
...
@@ -44,6 +44,6 @@
android:id=
"@+id/menu_search"
android:title=
"@string/menu_search"
appcompat:actionViewClass=
"android.widget.SearchView"
appcompat:showAsAction=
"ifRoom"
/>
appcompat:showAsAction=
"ifRoom
|withText
"
/>
</menu>
example/lib/main.dart
View file @
d89cd5df
...
...
@@ -67,6 +67,8 @@ class _MyAppState extends State<MyApp> {
body:
new
Center
(
child:
new
RaisedButton
(
onPressed:
()
{
inAppBrowser
.
open
(
"https://flutter.io/"
,
options:
{
//"toolbarTopFixedTitle": "Fixed title",
"hideUrlBar"
:
true
,
//"toolbarTop": false,
//"toolbarBottom": false
});
...
...
ios/Classes/InAppBrowserOptions.swift
View file @
d89cd5df
...
...
@@ -18,10 +18,10 @@ public class InAppBrowserOptions: NSObject {
var
hidden
=
false
var
disallowOverScroll
=
false
var
toolbarTop
=
true
var
toolbarTopColor
=
""
var
toolbarTop
Background
Color
=
""
var
toolbarTopTranslucent
=
true
var
toolbarBottom
=
true
var
toolbarBottomColor
=
""
var
toolbarBottom
Background
Color
=
""
var
toolbarBottomTranslucent
=
true
var
hideUrlBar
=
false
var
presentationStyle
=
0
//fullscreen
...
...
ios/Classes/InAppBrowserWebViewController.swift
View file @
d89cd5df
...
...
@@ -141,8 +141,8 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
}
if
(
browserOptions
?
.
toolbarTop
)
!
{
if
browserOptions
?
.
toolbarTopColor
!=
""
{
self
.
toolbarTop
.
backgroundColor
=
color
(
fromHexString
:
(
browserOptions
?
.
toolbarTopColor
)
!
)
if
browserOptions
?
.
toolbarTop
Background
Color
!=
""
{
self
.
toolbarTop
.
backgroundColor
=
color
(
fromHexString
:
(
browserOptions
?
.
toolbarTop
Background
Color
)
!
)
}
}
else
{
...
...
@@ -156,8 +156,8 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
}
if
(
browserOptions
?
.
toolbarBottom
)
!
{
if
browserOptions
?
.
toolbarBottomColor
!=
""
{
self
.
toolbarBottom
.
backgroundColor
=
color
(
fromHexString
:
(
browserOptions
?
.
toolbarBottomColor
)
!
)
if
browserOptions
?
.
toolbarBottom
Background
Color
!=
""
{
self
.
toolbarBottom
.
backgroundColor
=
color
(
fromHexString
:
(
browserOptions
?
.
toolbarBottom
Background
Color
)
!
)
}
self
.
toolbarBottom
.
isTranslucent
=
(
browserOptions
?
.
toolbarBottomTranslucent
)
!
}
...
...
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