Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
The Tor Project
Applications
android-components
Commits
1e9b0308
Commit
1e9b0308
authored
Jul 11, 2019
by
Sebastian Kaspari
Browse files
Issue #3616: (Merge day) browser-engine-gecko-beta (68) -> browser-engine-gecko-release (68)
parent
788c945b
Changes
30
Expand all
Hide whitespace changes
Inline
Side-by-side
buildSrc/src/main/java/Gecko.kt
View file @
1e9b0308
...
...
@@ -16,7 +16,7 @@ internal object GeckoVersions {
/**
* GeckoView Release Version.
*/
const
val
release_version
=
"6
7
.0.20190
613202504
"
const
val
release_version
=
"6
8
.0.20190
711090008
"
}
@Suppress
(
"MaxLineLength"
)
...
...
components/browser/engine-gecko/build.gradle
View file @
1e9b0308
...
...
@@ -11,6 +11,7 @@ android {
defaultConfig
{
minSdkVersion
config
.
minSdkVersion
targetSdkVersion
config
.
targetSdkVersion
testInstrumentationRunner
"androidx.test.runner.AndroidJUnitRunner"
}
buildTypes
{
...
...
@@ -19,6 +20,10 @@ android {
proguardFiles
getDefaultProguardFile
(
'proguard-android.txt'
),
'proguard-rules.pro'
}
}
packagingOptions
{
exclude
'META-INF/proguard/androidx-annotations.pro'
}
}
dependencies
{
...
...
@@ -39,6 +44,7 @@ dependencies {
testImplementation
Dependencies
.
testing_robolectric
testImplementation
Dependencies
.
testing_mockito
testImplementation
Dependencies
.
testing_mockwebserver
testImplementation
Dependencies
.
testing_coroutines
testImplementation
project
(
':support-test'
)
testImplementation
project
(
':tooling-fetch-tests'
)
...
...
components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt
View file @
1e9b0308
...
...
@@ -6,6 +6,9 @@ package mozilla.components.browser.engine.gecko
import
android.content.Context
import
android.util.AttributeSet
import
mozilla.components.browser.engine.gecko.integration.LocaleSettingUpdater
import
mozilla.components.browser.engine.gecko.mediaquery.from
import
mozilla.components.browser.engine.gecko.mediaquery.toGeckoValue
import
mozilla.components.browser.engine.gecko.webextension.GeckoWebExtension
import
mozilla.components.concept.engine.Engine
import
mozilla.components.concept.engine.EngineSession
...
...
@@ -14,11 +17,13 @@ import mozilla.components.concept.engine.EngineSessionState
import
mozilla.components.concept.engine.EngineView
import
mozilla.components.concept.engine.Settings
import
mozilla.components.concept.engine.history.HistoryTrackingDelegate
import
mozilla.components.concept.engine.mediaquery.PreferredColorScheme
import
mozilla.components.concept.engine.utils.EngineVersion
import
mozilla.components.concept.engine.webextension.WebExtension
import
org.json.JSONObject
import
org.mozilla.geckoview.GeckoResult
import
org.mozilla.geckoview.GeckoRuntime
import
org.mozilla.geckoview.GeckoRuntimeSettings
import
org.mozilla.geckoview.GeckoSession
import
org.mozilla.geckoview.GeckoWebExecutor
import
java.lang.IllegalStateException
...
...
@@ -34,6 +39,8 @@ class GeckoEngine(
)
:
Engine
{
private
val
executor
by
lazy
{
executorProvider
.
invoke
()
}
private
val
localeUpdater
=
LocaleSettingUpdater
(
context
,
runtime
)
init
{
runtime
.
delegate
=
GeckoRuntime
.
Delegate
{
// On shutdown: The runtime is shutting down (possibly because of an unrecoverable error state). We crash
...
...
@@ -87,7 +94,7 @@ class GeckoEngine(
onSuccess
:
((
WebExtension
)
->
Unit
),
onError
:
((
String
,
Throwable
)
->
Unit
)
)
{
GeckoWebExtension
(
id
,
url
).
also
{
ext
->
GeckoWebExtension
(
id
,
url
,
allowContentMessaging
).
also
{
ext
->
runtime
.
registerWebExtension
(
ext
.
nativeExtension
).
then
({
onSuccess
(
ext
)
GeckoResult
<
Void
>()
...
...
@@ -98,6 +105,29 @@ class GeckoEngine(
}
}
/**
* See [Engine.clearData].
*/
override
fun
clearData
(
data
:
Engine
.
BrowsingData
,
host
:
String
?,
onSuccess
:
()
->
Unit
,
onError
:
(
Throwable
)
->
Unit
)
{
val
flags
=
data
.
types
.
toLong
()
if
(
host
!=
null
)
{
runtime
.
storageController
.
clearDataFromHost
(
host
,
flags
)
}
else
{
runtime
.
storageController
.
clearData
(
flags
)
}.
then
({
onSuccess
()
GeckoResult
<
Void
>()
},
{
throwable
->
onError
(
throwable
)
GeckoResult
<
Void
>()
})
}
override
fun
name
():
String
=
"Gecko"
override
val
version
:
EngineVersion
=
EngineVersion
.
parse
(
org
.
mozilla
.
geckoview
.
BuildConfig
.
MOZILLA_VERSION
)
...
...
@@ -119,6 +149,13 @@ class GeckoEngine(
get
()
=
runtime
.
settings
.
automaticFontSizeAdjustment
set
(
value
)
{
runtime
.
settings
.
automaticFontSizeAdjustment
=
value
}
override
var
automaticLanguageAdjustment
:
Boolean
get
()
=
localeUpdater
.
enabled
set
(
value
)
{
localeUpdater
.
enabled
=
value
defaultSettings
?.
automaticLanguageAdjustment
=
value
}
override
var
trackingProtectionPolicy
:
TrackingProtectionPolicy
?
get
()
=
TrackingProtectionPolicy
.
select
(
runtime
.
settings
.
contentBlocking
.
categories
)
set
(
value
)
{
...
...
@@ -143,15 +180,66 @@ class GeckoEngine(
override
var
userAgentString
:
String
?
get
()
=
defaultSettings
?.
userAgentString
?:
GeckoSession
.
getDefaultUserAgent
()
set
(
value
)
{
defaultSettings
?.
userAgentString
=
value
}
override
var
preferredColorScheme
:
PreferredColorScheme
get
()
=
PreferredColorScheme
.
from
(
runtime
.
settings
.
preferredColorScheme
)
set
(
value
)
{
runtime
.
settings
.
preferredColorScheme
=
value
.
toGeckoValue
()
}
override
var
allowAutoplayMedia
:
Boolean
get
()
=
runtime
.
settings
.
autoplayDefault
==
GeckoRuntimeSettings
.
AUTOPLAY_DEFAULT_ALLOWED
set
(
value
)
{
runtime
.
settings
.
autoplayDefault
=
if
(
value
)
{
GeckoRuntimeSettings
.
AUTOPLAY_DEFAULT_ALLOWED
}
else
{
GeckoRuntimeSettings
.
AUTOPLAY_DEFAULT_BLOCKED
}
}
override
var
suspendMediaWhenInactive
:
Boolean
get
()
=
defaultSettings
?.
suspendMediaWhenInactive
?:
false
set
(
value
)
{
defaultSettings
?.
suspendMediaWhenInactive
=
value
}
override
var
fontInflationEnabled
:
Boolean
?
get
()
=
runtime
.
settings
.
fontInflationEnabled
set
(
value
)
{
// automaticFontSizeAdjustment is set to true by default, which
// will cause an exception if fontInflationEnabled is set
// (to either true or false). We therefore need to be able to
// set our built-in default value to null so that the exception
// is only thrown if an app is configured incorrectly but not
// if it uses default values.
value
?.
let
{
runtime
.
settings
.
fontInflationEnabled
=
it
}
}
override
var
fontSizeFactor
:
Float
?
get
()
=
runtime
.
settings
.
fontSizeFactor
set
(
value
)
{
// automaticFontSizeAdjustment is set to true by default, which
// will cause an exception if fontSizeFactor is set as well.
// We therefore need to be able to set our built-in default value
// to null so that the exception is only thrown if an app is
// configured incorrectly but not if it uses default values.
value
?.
let
{
runtime
.
settings
.
fontSizeFactor
=
it
}
}
}.
apply
{
defaultSettings
?.
let
{
this
.
javascriptEnabled
=
it
.
javascriptEnabled
this
.
webFontsEnabled
=
it
.
webFontsEnabled
this
.
automaticFontSizeAdjustment
=
it
.
automaticFontSizeAdjustment
this
.
automaticLanguageAdjustment
=
it
.
automaticLanguageAdjustment
this
.
trackingProtectionPolicy
=
it
.
trackingProtectionPolicy
this
.
remoteDebuggingEnabled
=
it
.
remoteDebuggingEnabled
this
.
testingModeEnabled
=
it
.
testingModeEnabled
this
.
userAgentString
=
it
.
userAgentString
this
.
preferredColorScheme
=
it
.
preferredColorScheme
this
.
allowAutoplayMedia
=
it
.
allowAutoplayMedia
this
.
suspendMediaWhenInactive
=
it
.
suspendMediaWhenInactive
this
.
fontInflationEnabled
=
it
.
fontInflationEnabled
this
.
fontSizeFactor
=
it
.
fontSizeFactor
}
}
}
components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineSession.kt
View file @
1e9b0308
...
...
@@ -5,13 +5,12 @@
package
mozilla.components.browser.engine.gecko
import
android.annotation.SuppressLint
import
kotlin.coroutines.CoroutineContext
import
kotlinx.coroutines.CompletableDeferred
import
kotlinx.coroutines.CoroutineScope
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.Job
import
kotlinx.coroutines.launch
import
kotlinx.coroutines.runBlocking
import
mozilla.components.browser.engine.gecko.media.GeckoMediaDelegate
import
mozilla.components.browser.engine.gecko.permission.GeckoPermissionRequest
import
mozilla.components.browser.engine.gecko.prompt.GeckoPromptDelegate
import
mozilla.components.browser.errorpages.ErrorType
...
...
@@ -28,7 +27,6 @@ import mozilla.components.support.ktx.kotlin.isEmail
import
mozilla.components.support.ktx.kotlin.isGeoLocation
import
mozilla.components.support.ktx.kotlin.isPhone
import
mozilla.components.support.utils.DownloadUtils
import
mozilla.components.support.utils.ThreadUtils
import
org.mozilla.geckoview.AllowOrDeny
import
org.mozilla.geckoview.ContentBlocking
import
org.mozilla.geckoview.GeckoResult
...
...
@@ -37,7 +35,7 @@ import org.mozilla.geckoview.GeckoSession
import
org.mozilla.geckoview.GeckoSession.NavigationDelegate
import
org.mozilla.geckoview.GeckoSessionSettings
import
org.mozilla.geckoview.WebRequestError
import
java.lang.IllegalStateException
import
kotlin.coroutines.CoroutineContext
/**
* Gecko-based EngineSession implementation.
...
...
@@ -58,7 +56,10 @@ class GeckoEngineSession(
internal
lateinit
var
geckoSession
:
GeckoSession
internal
var
currentUrl
:
String
?
=
null
internal
var
scrollY
:
Int
=
0
internal
var
job
:
Job
=
Job
()
private
var
lastSessionState
:
GeckoSession
.
SessionState
?
=
null
private
var
stateBeforeCrash
:
GeckoSession
.
SessionState
?
=
null
/**
* See [EngineSession.settings]
...
...
@@ -69,6 +70,9 @@ class GeckoEngineSession(
override
var
userAgentString
:
String
?
get
()
=
geckoSession
.
settings
.
userAgentOverride
set
(
value
)
{
geckoSession
.
settings
.
userAgentOverride
=
value
}
override
var
suspendMediaWhenInactive
:
Boolean
get
()
=
geckoSession
.
settings
.
suspendMediaWhenInactive
set
(
value
)
{
geckoSession
.
settings
.
suspendMediaWhenInactive
=
value
}
}
private
var
initialLoad
=
true
...
...
@@ -134,28 +138,9 @@ class GeckoEngineSession(
/**
* See [EngineSession.saveState]
*
* See https://bugzilla.mozilla.org/show_bug.cgi?id=1441810 for
* discussion on sync vs. async, where a decision was made that
* callers should provide synchronous wrappers, if needed. In case we're
* asking for the state when persisting, a separate (independent) thread
* is used so we're not blocking anything else. In case of calling this
* method from onPause or similar, we also want a synchronous response.
*/
override
fun
saveState
():
EngineSessionState
=
runBlocking
{
val
state
=
CompletableDeferred
<
GeckoEngineSessionState
>()
ThreadUtils
.
postToBackgroundThread
{
geckoSession
.
saveState
().
then
({
sessionState
->
state
.
complete
(
GeckoEngineSessionState
(
sessionState
))
GeckoResult
<
Void
>()
},
{
throwable
->
state
.
completeExceptionally
(
throwable
)
GeckoResult
<
Void
>()
})
}
state
.
await
()
override
fun
saveState
():
EngineSessionState
{
return
GeckoEngineSessionState
(
lastSessionState
)
}
/**
...
...
@@ -267,6 +252,22 @@ class GeckoEngineSession(
geckoSession
.
exitFullScreen
()
}
/**
* See [EngineSession.recoverFromCrash]
*/
@Synchronized
override
fun
recoverFromCrash
():
Boolean
{
val
state
=
stateBeforeCrash
return
if
(
state
!=
null
)
{
geckoSession
.
restoreState
(
state
)
stateBeforeCrash
=
null
true
}
else
{
false
}
}
/**
* See [EngineSession.close].
*/
...
...
@@ -276,11 +277,6 @@ class GeckoEngineSession(
geckoSession
.
close
()
}
override
fun
recoverFromCrash
():
Boolean
{
// No-op: Functionality requires GeckoView 68.0
return
false
}
/**
* NavigationDelegate implementation for forwarding callbacks to observers of the session.
*/
...
...
@@ -320,7 +316,22 @@ class GeckoEngineSession(
is
InterceptionResponse
.
Url
->
loadUrl
(
url
)
}
}
return
GeckoResult
.
fromValue
(
if
(
response
!=
null
)
AllowOrDeny
.
DENY
else
AllowOrDeny
.
ALLOW
)
return
if
(
response
!=
null
)
{
GeckoResult
.
fromValue
(
AllowOrDeny
.
DENY
)
}
else
{
notifyObservers
{
// As the name LoadRequest.isRedirect may imply this flag is about http redirects. The flag
// is "True if and only if the request was triggered by an HTTP redirect."
onLoadRequest
(
url
=
request
.
uri
,
triggeredByRedirect
=
request
.
isRedirect
,
triggeredByWebContent
=
requestFromWebContent
)
}
GeckoResult
.
fromValue
(
AllowOrDeny
.
ALLOW
)
}
}
override
fun
onCanGoForward
(
session
:
GeckoSession
,
canGoForward
:
Boolean
)
{
...
...
@@ -393,6 +404,10 @@ class GeckoEngineSession(
onLoadingStateChange
(
false
)
}
}
override
fun
onSessionStateChange
(
session
:
GeckoSession
,
sessionState
:
GeckoSession
.
SessionState
)
{
lastSessionState
=
sessionState
}
}
@Suppress
(
"ComplexMethod"
)
...
...
@@ -479,8 +494,12 @@ class GeckoEngineSession(
}
override
fun
onCrash
(
session
:
GeckoSession
)
{
stateBeforeCrash
=
lastSessionState
geckoSession
.
close
()
createGeckoSession
()
notifyObservers
{
onCrashStateChange
(
crashed
=
true
)
}
}
override
fun
onFullScreen
(
session
:
GeckoSession
,
fullScreen
:
Boolean
)
{
...
...
@@ -561,6 +580,12 @@ class GeckoEngineSession(
}
}
private
fun
createScrollDelegate
()
=
object
:
GeckoSession
.
ScrollDelegate
{
override
fun
onScrollChanged
(
session
:
GeckoSession
,
scrollX
:
Int
,
scrollY
:
Int
)
{
this
@GeckoEngineSession
.
scrollY
=
scrollY
}
}
@Suppress
(
"ComplexMethod"
)
fun
handleLongClick
(
elementSrc
:
String
?,
elementType
:
Int
,
uri
:
String
?
=
null
):
HitResult
?
{
return
when
(
elementType
)
{
...
...
@@ -603,12 +628,9 @@ class GeckoEngineSession(
defaultSettings
?.
trackingProtectionPolicy
?.
let
{
enableTrackingProtection
(
it
)
}
defaultSettings
?.
requestInterceptor
?.
let
{
settings
.
requestInterceptor
=
it
}
defaultSettings
?.
historyTrackingDelegate
?.
let
{
settings
.
historyTrackingDelegate
=
it
}
defaultSettings
?.
testingModeEnabled
?.
let
{
geckoSession
.
settings
.
fullAccessibilityTree
=
it
}
defaultSettings
?.
userAgentString
?.
let
{
geckoSession
.
settings
.
userAgentOverride
=
it
}
defaultSettings
?.
testingModeEnabled
?.
let
{
geckoSession
.
settings
.
fullAccessibilityTree
=
it
}
defaultSettings
?.
userAgentString
?.
let
{
geckoSession
.
settings
.
userAgentOverride
=
it
}
defaultSettings
?.
suspendMediaWhenInactive
?.
let
{
geckoSession
.
settings
.
suspendMediaWhenInactive
=
it
}
geckoSession
.
open
(
runtime
)
...
...
@@ -619,6 +641,8 @@ class GeckoEngineSession(
geckoSession
.
permissionDelegate
=
createPermissionDelegate
()
geckoSession
.
promptDelegate
=
GeckoPromptDelegate
(
this
)
geckoSession
.
historyDelegate
=
createHistoryDelegate
()
geckoSession
.
mediaDelegate
=
GeckoMediaDelegate
(
this
)
geckoSession
.
scrollDelegate
=
createScrollDelegate
()
}
companion
object
{
...
...
@@ -631,7 +655,7 @@ class GeckoEngineSession(
* Provides an ErrorType corresponding to the error code provided.
*/
@Suppress
(
"ComplexMethod"
)
internal
fun
geckoErrorToErrorType
(
@WebRequestError
.
Error
errorCode
:
Int
)
=
internal
fun
geckoErrorToErrorType
(
errorCode
:
Int
)
=
when
(
errorCode
)
{
WebRequestError
.
ERROR_UNKNOWN
->
ErrorType
.
UNKNOWN
WebRequestError
.
ERROR_SECURITY_SSL
->
ErrorType
.
ERROR_SECURITY_SSL
...
...
components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineSessionState.kt
View file @
1e9b0308
...
...
@@ -26,7 +26,10 @@ class GeckoEngineSessionState internal constructor(
companion
object
{
fun
fromJSON
(
json
:
JSONObject
):
GeckoEngineSessionState
=
try
{
val
state
=
json
.
getString
(
GECKO_STATE_KEY
)
GeckoEngineSessionState
(
GeckoSession
.
SessionState
(
state
))
GeckoEngineSessionState
(
GeckoSession
.
SessionState
.
fromString
(
state
)
)
}
catch
(
e
:
JSONException
)
{
GeckoEngineSessionState
(
null
)
}
...
...
components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineView.kt
View file @
1e9b0308
...
...
@@ -8,9 +8,11 @@ import android.content.Context
import
android.graphics.Bitmap
import
android.util.AttributeSet
import
android.widget.FrameLayout
import
androidx.annotation.VisibleForTesting
import
androidx.core.view.ViewCompat
import
mozilla.components.concept.engine.EngineSession
import
mozilla.components.concept.engine.EngineView
import
mozilla.components.concept.engine.permission.PermissionRequest
import
org.mozilla.geckoview.GeckoResult
/**
...
...
@@ -21,6 +23,7 @@ class GeckoEngineView @JvmOverloads constructor(
attrs
:
AttributeSet
?
=
null
,
defStyleAttr
:
Int
=
0
)
:
FrameLayout
(
context
,
attrs
,
defStyleAttr
),
EngineView
{
@VisibleForTesting
(
otherwise
=
VisibleForTesting
.
PRIVATE
)
internal
var
currentGeckoView
=
object
:
NestedGeckoView
(
context
)
{
override
fun
onDetachedFromWindow
()
{
// We are releasing the session before GeckoView gets detached from the window. Otherwise
...
...
@@ -33,9 +36,25 @@ class GeckoEngineView @JvmOverloads constructor(
// Explicitly mark this view as important for autofill. The default "auto" doesn't seem to trigger any
// autofill behavior for us here.
@Suppress
(
"WrongConstant"
)
ViewCompat
.
setImportantForAutofill
(
this
,
0x1
/* View
.IMPORTANT_FOR_A
UTOFILL
_YES
*/
)
ViewCompat
.
setImportantForAutofill
(
this
,
ViewCompat
.
IMPORTANT_FOR_A
CCESSIBILITY
_YES
)
}
@VisibleForTesting
(
otherwise
=
VisibleForTesting
.
PRIVATE
)
internal
val
observer
=
object
:
EngineSession
.
Observer
{
override
fun
onCrashStateChange
(
crashed
:
Boolean
)
{
if
(
crashed
)
{
// When crashing the previous GeckoSession is no longer usable. Internally GeckoEngineSession will
// create a new instance. This means we will need to tell GeckoView about this new GeckoSession:
currentSession
?.
let
{
currentGeckoView
.
setSession
(
it
.
geckoSession
)
}
}
}
override
fun
onAppPermissionRequest
(
permissionRequest
:
PermissionRequest
)
=
Unit
override
fun
onContentPermissionRequest
(
permissionRequest
:
PermissionRequest
)
=
Unit
}
@VisibleForTesting
(
otherwise
=
VisibleForTesting
.
PRIVATE
)
internal
var
currentSession
:
GeckoEngineSession
?
=
null
init
{
// Currently this is just a FrameLayout with a single GeckoView instance. Eventually this
// implementation should handle at least two GeckoView so that we can switch between
...
...
@@ -45,9 +64,16 @@ class GeckoEngineView @JvmOverloads constructor(
/**
* Render the content of the given session.
*/
@Synchronized
override
fun
render
(
session
:
EngineSession
)
{
val
internalSession
=
session
as
GeckoEngineSession
currentSession
?.
apply
{
unregister
(
observer
)
}
currentSession
=
session
.
apply
{
register
(
observer
)
}
if
(
currentGeckoView
.
session
!=
internalSession
.
geckoSession
)
{
currentGeckoView
.
session
?.
let
{
// Release a previously assigned session. Otherwise GeckoView will close it
...
...
@@ -61,11 +87,27 @@ class GeckoEngineView @JvmOverloads constructor(
@Synchronized
override
fun
release
()
{
currentSession
?.
apply
{
unregister
(
observer
)
}
currentSession
=
null
currentGeckoView
.
releaseSession
()
}
override
fun
onDetachedFromWindow
()
{
super
.
onDetachedFromWindow
()
release
()
}
override
fun
canScrollVerticallyUp
()
=
currentSession
?.
let
{
it
.
scrollY
>
0
}
!=
false
override
fun
canScrollVerticallyDown
()
=
true
// waiting for this issue https://bugzilla.mozilla.org/show_bug.cgi?id=1507569
override
fun
setVerticalClipping
(
clippingHeight
:
Int
)
{
currentGeckoView
.
setVerticalClipping
(
clippingHeight
)
}
override
fun
captureThumbnail
(
onFinish
:
(
Bitmap
?)
->
Unit
)
{
val
geckoResult
=
currentGeckoView
.
capturePixels
()
geckoResult
.
then
({
bitmap
->
...
...
@@ -76,8 +118,4 @@ class GeckoEngineView @JvmOverloads constructor(
GeckoResult
<
Void
>()
})
}
override
fun
setVerticalClipping
(
clippingHeight
:
Int
)
{
// no-op: requires GeckoView 68.0
}
}
components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/integration/LocaleSettingUpdater.kt
0 → 100644
View file @
1e9b0308
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package
mozilla.components.browser.engine.gecko.integration
import
android.content.BroadcastReceiver
import
android.content.Context
import
android.content.Intent
import
android.content.IntentFilter
import
androidx.core.os.LocaleListCompat
as
LocaleList
import
org.mozilla.geckoview.GeckoRuntime
/**
* Class to set the locales setting for geckoview, updating from the locale of the device.
*/
class
LocaleSettingUpdater
(
private
val
context
:
Context
,
private
val
runtime
:
GeckoRuntime
)
:
SettingUpdater
<
Array
<
String
>>()
{
override
var
value
:
Array
<
String
>
=
findValue
()
set
(
value
)
{
runtime
.
settings
.
locales
=
value
field
=
value
}
private
val
localeChangedReceiver
by
lazy
{
object
:
BroadcastReceiver
()
{
override
fun
onReceive
(
context
:
Context
,
intent
:
Intent
?)
{
updateValue
()
}
}
}
override
fun
registerForUpdates
()
{
context
.
registerReceiver
(
localeChangedReceiver
,
IntentFilter
(
Intent
.
ACTION_LOCALE_CHANGED
))
}
override
fun
unregisterForUpdates
()
{
context
.
unregisterReceiver
(
localeChangedReceiver
)
}
override
fun
findValue
():
Array
<
String
>
{
val
localeList
=
LocaleList
.
getAdjustedDefault
()
return
arrayOfNulls
<
Unit
>(
localeList
.
size
())
.
mapIndexedNotNull
{
i
,
_
->
localeList
.
get
(
i
).
toLanguageTag
()
}
.
toTypedArray
()
}
}
components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/integration/SettingUpdater.kt
0 → 100644
View file @
1e9b0308
package
mozilla.components.browser.engine.gecko.integration
abstract
class
SettingUpdater
<
T
>
{
/**
* Toggle the automatic tracking of a setting derived from the device state.