Repository: wordpress-mobile/WordPress-Android (language: kotlin)

Issue:
ApplicationNotResponding in UserAgent
ANRs weren't available in Sentry until the last release, so this issue is not newly introduced. Please keep that in mind while debugging the issue so as not to limit it to the changes introduced recently.

**Sentry Url**: https://sentry.io/share/issue/09ee294fc5b3453bb0b2920117ae4387/
**User Count**: 712
**Count**: 1339
**First Release**: org.wordpress.android@15.0-rc-1+874
**First Seen**: 2020-06-03T13:44:42.073000Z
**Last Seen**: 2020-06-24T01:23:36Z
**24 Hours**: 296
**30 Days**: 1334


```
ApplicationNotResponding: Application Not Responding for at least 5000 ms.
     at org.wordpress.android.fluxc.network.UserAgent.<init>(UserAgent.java:18)
     at org.wordpress.android.modules.AppConfigModule.provideUserAgent(AppConfigModule.java:22)
     at org.wordpress.android.modules.AppConfigModule_ProvideUserAgentFactory.provideUserAgent(AppConfigModule_ProvideUserAgentFactory.java:37)
     at org.wordpress.android.modules.AppConfigModule_ProvideUserAgentFactory.get(AppConfigModule_ProvideUserAgentFactory.java:27)
     at org.wordpress.android.modules.AppConfigModule_ProvideUserAgentFactory.get(AppConfigModule_ProvideUserAgentFactory.java:10)
     at org.wordpress.android.fluxc.module.ReleaseNetworkModule_ProvideAccountRestClientFactory.get(ReleaseNetworkModule_ProvideAccountRestClientFactory.java:61)
     at org.wordpress.android.fluxc.module.ReleaseNetworkModule_ProvideAccountRestClientFactory.get(ReleaseNetworkModule_ProvideAccountRestClientFactory.java:15)
     at org.wordpress.android.fluxc.store.AccountStore_Factory.get(AccountStore_Factory.java:44)
     at org.wordpress.android.fluxc.store.AccountStore_Factory.get(AccountStore_Factory.java:12)
     at org.wordpress.android.modules.DaggerAppComponent.injectWordPress(DaggerAppComponent.java:5578)
...
(28 additional frame(s) were not displayed)
```



Discussion hints:
This issue has been marked as stale because:

 * It has been inactive for the past year.
 * It isn't in a project or a milestone.
 * It hasn’t been labeled `[Pri] Blocker`, `[Pri] High`, or `good first issue`.

Please comment with an update if you believe this issue is still valid or if it can be closed. This issue will also be reviewed for validity and priority during regularly scheduled triage sessions.

Sentry Issue: [WORDPRESS-ANDROID-2VFK](https://a8c.sentry.io/issues/5001030238/?referrer=github_integration)
Thanks for reporting! 👍 <!-- generated_by_dangermattic -->

Probably fixed with https://github.com/wordpress-mobile/WordPress-Android/pull/20296 since there are no occurrences after `24.3.1`. Feel free to reopen if the issue persist
Sentry Issue: [JETPACK-ANDROID-P3K](https://a8c.sentry.io/issues/5132003514/?referrer=github_integration)
Sentry Issue: [WORDPRESS-ANDROID-2VYY](https://a8c.sentry.io/issues/5052740778/?referrer=github_integration)
Sentry Issue: [JETPACK-ANDROID-NWK](https://a8c.sentry.io/issues/5124816194/?referrer=github_integration)
> Probably fixed with https://github.com/wordpress-mobile/WordPress-Android/pull/20296 since there are no occurrences after 24.3.1. Feel free to reopen if the issue persist

I'm reopening this issue since the ANR still persist after the fix and is related to a know limitation of the `getDefaultUserAgent` call https://issuetracker.google.com/issues/289118199#comment9

The issue seems to occur almost exclusively on low end devices.
Sentry Issue: [WORDPRESS-ANDROID-23MM](https://a8c.sentry.io/issues/3312111479/?referrer=github_integration)
Sentry Issue: [JETPACK-ANDROID-N3J](https://a8c.sentry.io/issues/5095961906/?referrer=github_integration)
Sentry Issue: [WORDPRESS-ANDROID-2WA6](https://a8c.sentry.io/issues/5083633345/?referrer=github_integration)
Sentry Issue: [WORDPRESS-ANDROID-2WCX](https://a8c.sentry.io/issues/5089808627/?referrer=github_integration)
Sentry Issue: [WORDPRESS-ANDROID-2WA4](https://a8c.sentry.io/issues/5083460695/?referrer=github_integration)
The ANR roots in two places:

1. [The AppConfigModule](https://github.com/wordpress-mobile/WordPress-Android/blob/trunk/WordPress/src/main/java/org/wordpress/android/modules/AppConfigModule.java#L30) that uses [the FluxC implemantation](https://github.com/wordpress-mobile/WordPress-FluxC-Android/blob/trunk/fluxc/src/main/java/org/wordpress/android/fluxc/network/UserAgent.kt).
```
io.sentry.android.core.ApplicationNotResponding: Background ANR
    at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:509)
    at WV.ir.<init>(chromium-TrichromeWebViewGoogle6432.aab-stable-626111933:43)
    at WV.rC.<init>(chromium-TrichromeWebViewGoogle6432.aab-stable-626111933:8)
    at org.chromium.android_webview.AwBrowserProcess.f(chromium-TrichromeWebViewGoogle6432.aab-stable-626111933:106)
    at com.android.webview.chromium.M.e(chromium-TrichromeWebViewGoogle6432.aab-stable-626111933:208)
    at com.android.webview.chromium.M.b(chromium-TrichromeWebViewGoogle6432.aab-stable-626111933:42)
    at com.android.webview.chromium.WebViewChromiumFactoryProvider.getStatics(chromium-TrichromeWebViewGoogle6432.aab-stable-626111933:16)
    at android.webkit.WebSettings.getDefaultUserAgent(WebSettings.java:1355)
    at org.wordpress.android.fluxc.network.UserAgent.<init>(UserAgent.kt:17)
    at org.wordpress.android.modules.AppConfigModule.provideUserAgent(AppConfigModule.java:30)
```

2. [The AppInitialiser](https://github.com/wordpress-mobile/WordPress-Android/blob/trunk/WordPress/src/main/java/org/wordpress/android/AppInitializer.kt#L1063).
```
io.sentry.android.core.ApplicationNotResponding: Background ANR
    at android.webkit.WebViewFactory.getProvider(WebViewFactory.java:227)
    at android.webkit.WebSettings.getDefaultUserAgent(WebSettings.java:1355)
    at org.wordpress.android.AppInitializer$Companion$defaultUserAgent$2.invoke(AppInitializer.kt:1065)
    at org.wordpress.android.AppInitializer$Companion$defaultUserAgent$2.invoke(AppInitializer.kt:1063)
    at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
    at org.wordpress.android.AppInitializer$Companion.getDefaultUserAgent(AppInitializer.kt:1063)
    at org.wordpress.android.AppInitializer$Companion$userAgent$2.invoke(AppInitializer.kt:1097)
    at org.wordpress.android.AppInitializer$Companion$userAgent$2.invoke(AppInitializer.kt:1096)
    at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
    at org.wordpress.android.AppInitializer$Companion.getUserAgent(AppInitializer.kt:1096)
    at org.wordpress.android.AppInitializer.init(AppInitializer.kt:308)
    at org.wordpress.android.WordPressApp.onCreate(WordPressApp.java:20)
```
@antonis, is your investigation ongoing? Can I assign this issue and [WORDPRESS-ANDROID-2WA6](https://a8c.sentry.io/issues/5083633345/?referrer=github_integration) to you?
Hey @irfano 👋 
I'll be glad to continue looking at this. I've requested feedback internally (ref pcdRpT-5Us-p2#comment-9676) to see if we can avoid calling `getDefaultUserAgent` on initialisation when possible. I think that this might also be one of the root causes of https://github.com/wordpress-mobile/WordPress-Android/issues/20147

Pull request: Removes multiple calls to the WebSettings.getDefaultUserAgent api
Fixes #12259

## Description
This PR replaces multiple calls to the `WebSettings.getDefaultUserAgent`([which is not recommended](https://issuetracker.google.com/issues/289118199#comment9)) with just one, hoping to prevent the ANR of #12259 and probably reduce the crash count in #20147

The current implementation is making 27 calls to the `WebSettings.getDefaultUserAgent` function during the app startup and more later. One of those was in [the AppInitialiser](https://github.com/wordpress-mobile/WordPress-Android/blob/trunk/WordPress/src/main/java/org/wordpress/android/AppInitializer.kt#L1063) and the rest were calls to [the AppConfigModule](https://github.com/wordpress-mobile/WordPress-Android/blob/trunk/WordPress/src/main/java/org/wordpress/android/modules/AppConfigModule.java#L30) that uses [the FluxC implementation](https://github.com/wordpress-mobile/WordPress-FluxC-Android/blob/trunk/fluxc/src/main/java/org/wordpress/android/fluxc/network/UserAgent.kt).

Since I wasn't able to reproduce the ANR my plan is to monitor how this fix would affect the occurrences of the issue. If the issue persist I would probably try a more drastic approach of changing the user agent used for the api calls and keep the full user agent using the `WebSettings.getDefaultUserAgent` only for the WebViews.

Internal ref: pcdRpT-5Us-p2#comment-9676

-----

## To Test:
* Since this PR should not change the behaviour of the app but the refactored code affects all network calls a sanity check of the app is recommended. 
* Test Jetpack and WordPress, rest and xmlrpc
* Verify that the `AppInitializer.userAgentString` is [logged correctly](https://github.com/wordpress-mobile/WordPress-Android/blob/fix/12259-userAgent/WordPress/src/main/java/org/wordpress/android/AppInitializer.kt#L368)
-----

## Regression Notes

1. Potential unintended areas of impact

    - All Networking 😅 

2. What I did to test those areas of impact (or what existing automated tests I relied on)

    - Manual testing

3. What automated tests I added (or what prevented me from doing so)

    - Updated an existing test

-----

## PR Submission Checklist:

- [x] I have completed the Regression Notes.
- [x] I have considered adding accessibility improvements for my changes.
- [x] I have considered if this change warrants user-facing release notes and have added them to `RELEASE-NOTES.txt` if necessary.

-----

## Testing Checklist (strike-out the not-applying and unnecessary ones):

- [ ] WordPress.com sites and self-hosted Jetpack sites.
- [ ] Portrait and landscape orientations.
- [ ] Light and dark modes.
- [ ] Fonts: Larger, smaller and bold text.
- [ ] High contrast.
- [ ] Talkback.
- [ ] Languages with large words or with letters/accents not frequently used in English.
- [ ] Right-to-left languages. (Even if translation isn’t complete, formatting should still respect the right-to-left layout)
- [ ] Large and small screen sizes. (Tablet and smaller phones)
- [ ] Multi-tasking: Split screen and Pop-up view. (Android 10 or higher)

Test command: ./gradlew :WordPress:testWordpressVanillaDebugUnitTest --tests "org.wordpress.android.ui.sitemonitor.SiteMonitorUtilsTest"

Fix patch:
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index cca5a3431484..6676965acff1 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -2,7 +2,7 @@
 
 24.7
 -----
-
+* [*] [internal] Updates the way the app retrieves the User-Agent request header [https://github.com/wordpress-mobile/WordPress-Android/pull/20603]
 
 24.6
 -----
diff --git a/WordPress/src/main/java/org/wordpress/android/AppInitializer.kt b/WordPress/src/main/java/org/wordpress/android/AppInitializer.kt
index 3c9a689f24f4..118e30e38f8c 100644
--- a/WordPress/src/main/java/org/wordpress/android/AppInitializer.kt
+++ b/WordPress/src/main/java/org/wordpress/android/AppInitializer.kt
@@ -22,9 +22,7 @@ import android.os.Build.VERSION_CODES
 import android.os.Bundle
 import android.os.SystemClock
 import android.text.TextUtils
-import android.util.AndroidRuntimeException
 import android.util.Log
-import android.webkit.WebSettings
 import android.webkit.WebView
 import androidx.annotation.RequiresApi
 import androidx.appcompat.app.AppCompatDelegate
@@ -55,6 +53,7 @@ import org.wordpress.android.fluxc.generated.ListActionBuilder
 import org.wordpress.android.fluxc.generated.PostActionBuilder
 import org.wordpress.android.fluxc.generated.SiteActionBuilder
 import org.wordpress.android.fluxc.generated.ThemeActionBuilder
+import org.wordpress.android.fluxc.network.UserAgent
 import org.wordpress.android.fluxc.network.rest.wpcom.site.PrivateAtomicCookie
 import org.wordpress.android.fluxc.store.AccountStore
 import org.wordpress.android.fluxc.store.AccountStore.OnAccountChanged
@@ -124,6 +123,9 @@ class AppInitializer @Inject constructor(
     wellSqlInitializer: WellSqlInitializer,
     private val application: Application
 ) : DefaultLifecycleObserver {
+    @Inject
+    lateinit var userAgent: UserAgent
+
     @Inject
     lateinit var dispatcher: Dispatcher
 
@@ -305,7 +307,7 @@ class AppInitializer @Inject constructor(
                 .installDefaultEventBus()
         }
 
-        RestClientUtils.setUserAgent(userAgent)
+        RestClientUtils.setUserAgent(userAgent.toString())
 
         if (!initialized) {
             zendeskHelper.setupZendesk(
@@ -363,6 +365,8 @@ class AppInitializer @Inject constructor(
             initAppOpsManager()
         }
 
+        AppLog.i(T.UTILS, "AppInitializer.userAgentString: $userAgent")
+
         initialized = true
     }
 
@@ -1052,55 +1056,6 @@ class AppInitializer @Inject constructor(
             )
         }
 
-        /**
-         * Device's default User-Agent string.
-         * E.g.:
-         * "Mozilla/5.0 (Linux; Android 6.0; Android SDK built for x86_64 Build/MASTER; wv)
-         * AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.119 Mobile
-         * Safari/537.36"
-         */
-        @Suppress("SwallowedException")
-        val defaultUserAgent: String by lazy {
-            try {
-                WebSettings.getDefaultUserAgent(context)
-            } catch (e: AndroidRuntimeException) {
-                // Catch AndroidRuntimeException that could be raised by the WebView() constructor.
-                // See https://github.com/wordpress-mobile/WordPress-Android/issues/3594
-
-                // initialize with the empty string, it's a rare issue
-                ""
-            } catch (expected: NullPointerException) {
-                // Catch NullPointerException that could be raised by WebSettings.getDefaultUserAgent()
-                // See https://github.com/wordpress-mobile/WordPress-Android/issues/3838
-
-                // initialize with the empty string, it's a rare issue
-                ""
-            } catch (e: IllegalArgumentException) {
-                // Catch IllegalArgumentException that could be raised by WebSettings.getDefaultUserAgent()
-                // See https://github.com/wordpress-mobile/WordPress-Android/issues/9015
-
-                // initialize with the empty string, it's a rare issue
-                ""
-            }
-        }
-
-        /**
-         * User-Agent string when making HTTP connections, for both API traffic and WebViews. Appends
-         * "wp-android/version" to WebView's default User-Agent string for the webservers to get the full feature list
-         * of the browser and serve content accordingly, e.g.:
-         * "Mozilla/5.0 (Linux; Android 6.0; Android SDK built for x86_64 Build/MASTER; wv)
-         * AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.119 Mobile
-         * Safari/537.36 wp-android/4.7"
-         * Note that app versions prior to 2.7 simply used "wp-android" as the user agent
-         **/
-        val userAgent: String by lazy {
-            if (TextUtils.isEmpty(defaultUserAgent)) {
-                WordPress.USER_AGENT_APPNAME + "/" + PackageUtils.getVersionName(context)
-            } else {
-                (defaultUserAgent + " " + WordPress.USER_AGENT_APPNAME + "/" + PackageUtils.getVersionName(context))
-            }
-        }
-
         fun getBitmapCache(): BitmapLruCache {
             if (bitmapCache == null) {
                 // The cache size will be measured in kilobytes rather than number of items.
diff --git a/WordPress/src/main/java/org/wordpress/android/WordPress.kt b/WordPress/src/main/java/org/wordpress/android/WordPress.kt
index 928455ca34c0..1ed866d9a713 100644
--- a/WordPress/src/main/java/org/wordpress/android/WordPress.kt
+++ b/WordPress/src/main/java/org/wordpress/android/WordPress.kt
@@ -70,11 +70,5 @@ abstract class WordPress : Application() {
         fun getRestClientUtilsV2() = AppInitializer.restClientUtilsV2
 
         fun getRestClientUtilsV0() = AppInitializer.restClientUtilsV0
-
-        @JvmStatic
-        fun getDefaultUserAgent() = AppInitializer.defaultUserAgent
-
-        @JvmStatic
-        fun getUserAgent() = AppInitializer.userAgent
     }
 }
diff --git a/WordPress/src/main/java/org/wordpress/android/modules/AppConfigModule.java b/WordPress/src/main/java/org/wordpress/android/modules/AppConfigModule.java
index 86ec20e8b317..8845f7dbe586 100644
--- a/WordPress/src/main/java/org/wordpress/android/modules/AppConfigModule.java
+++ b/WordPress/src/main/java/org/wordpress/android/modules/AppConfigModule.java
@@ -11,6 +11,8 @@
 import org.wordpress.android.fluxc.network.UserAgent;
 import org.wordpress.android.fluxc.network.rest.wpcom.auth.AppSecrets;
 
+import javax.inject.Singleton;
+
 import dagger.Module;
 import dagger.Provides;
 import dagger.hilt.InstallIn;
@@ -25,6 +27,7 @@ public AppSecrets provideAppSecrets() {
         return new AppSecrets(BuildConfig.OAUTH_APP_ID, BuildConfig.OAUTH_APP_SECRET);
     }
 
+    @Singleton
     @Provides
     public UserAgent provideUserAgent(@ApplicationContext Context appContext) {
         return new UserAgent(appContext, WordPress.USER_AGENT_APPNAME);
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/WebViewActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/WebViewActivity.java
index 1999b39538e2..9bc91fe38fa8 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/WebViewActivity.java
+++ b/WordPress/src/main/java/org/wordpress/android/ui/WebViewActivity.java
@@ -13,13 +13,15 @@
 import androidx.appcompat.widget.Toolbar;
 
 import org.wordpress.android.R;
-import org.wordpress.android.WordPress;
 import org.wordpress.android.analytics.AnalyticsTracker;
+import org.wordpress.android.fluxc.network.UserAgent;
 import org.wordpress.android.util.extensions.CompatExtensionsKt;
 
 import java.util.HashMap;
 import java.util.Map;
 
+import javax.inject.Inject;
+
 /**
  * Basic activity for displaying a WebView.
  */
@@ -35,6 +37,8 @@ public abstract class WebViewActivity extends LocaleAwareActivity {
 
     protected WebView mWebView;
 
+    @Inject UserAgent mUserAgent;
+
     @Override
     public void onCreate(@Nullable Bundle savedInstanceState) {
         supportRequestWindowFeature(Window.FEATURE_PROGRESS);
@@ -64,7 +68,7 @@ public void handleOnBackPressed() {
         mWebView = (WebView) findViewById(R.id.webView);
         mWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
         // Setting this user agent makes Calypso sites hide any WordPress UIs (e.g. Masterbar, banners, etc.).
-        mWebView.getSettings().setUserAgentString(WordPress.getUserAgent());
+        mWebView.getSettings().setUserAgentString(mUserAgent.toString());
         configureWebView();
 
         if (savedInstanceState == null) {
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/blaze/BlazeFeatureUtils.kt b/WordPress/src/main/java/org/wordpress/android/ui/blaze/BlazeFeatureUtils.kt
index ba72a052d6f5..3cace3456986 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/blaze/BlazeFeatureUtils.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/blaze/BlazeFeatureUtils.kt
@@ -1,12 +1,12 @@
 package org.wordpress.android.ui.blaze
 
-import org.wordpress.android.WordPress
 import org.wordpress.android.analytics.AnalyticsTracker
 import org.wordpress.android.fluxc.model.PostModel
 import org.wordpress.android.fluxc.model.SiteModel
 import org.wordpress.android.fluxc.model.page.PageModel
 import org.wordpress.android.fluxc.model.page.PageStatus
 import org.wordpress.android.fluxc.model.post.PostStatus
+import org.wordpress.android.fluxc.network.UserAgent
 import org.wordpress.android.ui.WPWebViewActivity
 import org.wordpress.android.ui.blaze.blazecampaigns.campaigndetail.CampaignDetailPageSource
 import org.wordpress.android.ui.blaze.blazecampaigns.campaignlisting.CampaignListingPageSource
@@ -18,6 +18,7 @@ import org.wordpress.android.util.config.BlazeManageCampaignFeatureConfig
 import javax.inject.Inject
 
 class BlazeFeatureUtils @Inject constructor(
+    private val userAgent: UserAgent,
     private val analyticsTrackerWrapper: AnalyticsTrackerWrapper,
     private val appPrefsWrapper: AppPrefsWrapper,
     private val blazeFeatureConfig: BlazeFeatureConfig,
@@ -153,7 +154,7 @@ class BlazeFeatureUtils @Inject constructor(
         )
     }
 
-    fun getUserAgent() = WordPress.getUserAgent()
+    fun getUserAgent() = userAgent.toString()
 
     fun getAuthenticationPostData(authenticationUrl: String,
                                   urlToLoad: String,
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/layoutpicker/LayoutPreviewFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/layoutpicker/LayoutPreviewFragment.kt
index 03292ed578f8..83d878c0642a 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/layoutpicker/LayoutPreviewFragment.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/layoutpicker/LayoutPreviewFragment.kt
@@ -18,6 +18,7 @@ import androidx.lifecycle.ViewModelProvider
 import org.wordpress.android.R
 import org.wordpress.android.WordPress
 import org.wordpress.android.databinding.LayoutPickerPreviewFragmentBinding
+import org.wordpress.android.fluxc.network.UserAgent
 import org.wordpress.android.ui.FullscreenBottomSheetDialogFragment
 import org.wordpress.android.ui.PreviewMode.DESKTOP
 import org.wordpress.android.ui.PreviewMode.MOBILE
@@ -38,6 +39,9 @@ private const val JS_EVALUATION_DELAY = 250L
 private const val JS_READY_CALLBACK_ID = 926L
 
 abstract class LayoutPreviewFragment : FullscreenBottomSheetDialogFragment() {
+    @Inject
+    lateinit var userAgent: UserAgent
+
     @Inject
     lateinit var displayUtilsWrapper: DisplayUtilsWrapper
 
@@ -125,7 +129,7 @@ abstract class LayoutPreviewFragment : FullscreenBottomSheetDialogFragment() {
 
         binding?.previewTypeSelectorButton?.setOnClickListener { viewModel.onPreviewModePressed() }
 
-        binding?.webView?.settings?.userAgentString = WordPress.getUserAgent()
+        binding?.webView?.settings?.userAgentString = userAgent.toString()
         binding?.webView?.webViewClient = object : WebViewClient() {
             override fun onPageFinished(view: WebView?, url: String?) {
                 super.onPageFinished(view, url)
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/media/ExoPlayerUtils.kt b/WordPress/src/main/java/org/wordpress/android/ui/media/ExoPlayerUtils.kt
index adc9f5779c82..1fe579a18b6f 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/media/ExoPlayerUtils.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/media/ExoPlayerUtils.kt
@@ -19,13 +19,14 @@ import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
 import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory
 import com.google.android.exoplayer2.util.Util
 import dagger.Reusable
-import org.wordpress.android.WordPress
+import org.wordpress.android.fluxc.network.UserAgent
 import org.wordpress.android.ui.utils.AuthenticationUtils
 import javax.inject.Inject
 
 @Reusable
 @Suppress("DEPRECATION")
 class ExoPlayerUtils @Inject constructor(
+    private val userAgent: UserAgent,
     private val authenticationUtils: AuthenticationUtils,
     private val appContext: Context
 ) {
@@ -33,7 +34,7 @@ class ExoPlayerUtils @Inject constructor(
 
     fun buildHttpDataSourceFactory(url: String): DefaultHttpDataSourceFactory {
         if (httpDataSourceFactory == null) {
-            httpDataSourceFactory = DefaultHttpDataSourceFactory(WordPress.getUserAgent())
+            httpDataSourceFactory = DefaultHttpDataSourceFactory(userAgent.toString())
         }
         httpDataSourceFactory?.defaultRequestProperties?.set(authenticationUtils.getAuthHeaders(url))
         return httpDataSourceFactory as DefaultHttpDataSourceFactory
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/media/MediaSettingsActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/media/MediaSettingsActivity.java
index 3d96fd3386c7..b1fe511abc3b 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/media/MediaSettingsActivity.java
+++ b/WordPress/src/main/java/org/wordpress/android/ui/media/MediaSettingsActivity.java
@@ -67,6 +67,7 @@
 import org.wordpress.android.fluxc.generated.MediaActionBuilder;
 import org.wordpress.android.fluxc.model.MediaModel;
 import org.wordpress.android.fluxc.model.SiteModel;
+import org.wordpress.android.fluxc.network.UserAgent;
 import org.wordpress.android.fluxc.store.MediaStore;
 import org.wordpress.android.fluxc.store.MediaStore.MediaPayload;
 import org.wordpress.android.fluxc.store.MediaStore.OnMediaChanged;
@@ -153,6 +154,8 @@ private enum MediaType {
 
     private MediaType mMediaType;
 
+    @Inject UserAgent mUserAgent;
+
     @Inject MediaStore mMediaStore;
     @Inject Dispatcher mDispatcher;
     @Inject ImageManager mImageManager;
@@ -1031,7 +1034,7 @@ private void saveMediaToDevice() {
         }
         request.allowScanningByMediaScanner();
         request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
-        request.addRequestHeader("User-Agent", WordPress.getUserAgent());
+        request.addRequestHeader("User-Agent", mUserAgent.toString());
 
         mDownloadId = dm.enqueue(request);
         invalidateOptionsMenu();
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.kt
index 2f03f2e9b8c4..2a95431d0ce3 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.kt
@@ -54,7 +54,6 @@ import org.wordpress.android.BuildConfig
 import org.wordpress.android.R
 import org.wordpress.android.WordPress
 import org.wordpress.android.WordPress.Companion.getContext
-import org.wordpress.android.WordPress.Companion.getUserAgent
 import org.wordpress.android.analytics.AnalyticsTracker
 import org.wordpress.android.analytics.AnalyticsTracker.Stat
 import org.wordpress.android.editor.AztecEditorFragment
@@ -94,6 +93,7 @@ import org.wordpress.android.fluxc.model.PostImmutableModel
 import org.wordpress.android.fluxc.model.PostModel
 import org.wordpress.android.fluxc.model.SiteModel
 import org.wordpress.android.fluxc.model.post.PostStatus
+import org.wordpress.android.fluxc.network.UserAgent
 import org.wordpress.android.fluxc.network.rest.wpcom.site.PrivateAtomicCookie
 import org.wordpress.android.fluxc.store.AccountStore
 import org.wordpress.android.fluxc.store.AccountStore.OnAccountChanged
@@ -323,6 +323,8 @@ class EditPostActivity : LocaleAwareActivity(), EditorFragmentActivity, EditorIm
 
     @Inject lateinit var dispatcher: Dispatcher
 
+    @Inject lateinit var userAgent: UserAgent
+
     @Inject lateinit var accountStore: AccountStore
 
     @Inject lateinit var siteStore: SiteStore
@@ -2387,7 +2389,7 @@ class EditPostActivity : LocaleAwareActivity(), EditorFragmentActivity, EditorIm
                             siteModel.password,
                             siteModel.isUsingWpComRestApi,
                             siteModel.webEditor,
-                            getUserAgent(),
+                            userAgent.toString(),
                             isJetpackSsoEnabled
                         )
                     return GutenbergEditorFragment.newInstance(
@@ -2424,7 +2426,7 @@ class EditPostActivity : LocaleAwareActivity(), EditorFragmentActivity, EditorIm
                         editorMediaUploadListener = editorFragment as EditorMediaUploadListener?
 
                         // Set up custom headers for the visual editor's internal WebView
-                        editorFragment?.setCustomHttpHeader("User-Agent", getUserAgent())
+                        editorFragment?.setCustomHttpHeader("User-Agent", userAgent.toString())
                         reattachUploadingMediaForAztec()
                     }
                 }
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/publicize/PublicizeWebViewFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/publicize/PublicizeWebViewFragment.java
index 261e22903f6e..ce439e6c8deb 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/publicize/PublicizeWebViewFragment.java
+++ b/WordPress/src/main/java/org/wordpress/android/ui/publicize/PublicizeWebViewFragment.java
@@ -19,6 +19,7 @@
 import org.wordpress.android.WordPress;
 import org.wordpress.android.datasets.PublicizeTable;
 import org.wordpress.android.fluxc.model.SiteModel;
+import org.wordpress.android.fluxc.network.UserAgent;
 import org.wordpress.android.fluxc.store.AccountStore;
 import org.wordpress.android.models.PublicizeConnection;
 import org.wordpress.android.models.PublicizeService;
@@ -39,6 +40,8 @@ public class PublicizeWebViewFragment extends PublicizeBaseFragment {
     private WebView mWebView;
     private ProgressBar mProgress;
 
+    @Inject UserAgent mUserAgent;
+
     @Inject AccountStore mAccountStore;
 
     /*
@@ -106,7 +109,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa
         mWebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
         mWebView.getSettings().setJavaScriptEnabled(true);
         mWebView.getSettings().setDomStorageEnabled(true);
-        mWebView.getSettings().setUserAgentString(WordPress.getUserAgent());
+        mWebView.getSettings().setUserAgentString(mUserAgent.toString());
 
         return rootView;
     }
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderVideoViewerActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderVideoViewerActivity.java
index fcfde2ea5189..5fe94065af68 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderVideoViewerActivity.java
+++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderVideoViewerActivity.java
@@ -10,10 +10,12 @@
 import androidx.annotation.Nullable;
 
 import org.wordpress.android.R;
-import org.wordpress.android.WordPress;
+import org.wordpress.android.fluxc.network.UserAgent;
 import org.wordpress.android.ui.LocaleAwareActivity;
 import org.wordpress.android.util.helpers.WebChromeClientWithVideoPoster;
 
+import javax.inject.Inject;
+
 /**
  * Full screen landscape video player for the reader
  */
@@ -22,6 +24,8 @@ public class ReaderVideoViewerActivity extends LocaleAwareActivity {
     private WebView mWebView;
     private ProgressBar mProgress;
 
+    @Inject UserAgent mUserAgent;
+
     @Override
     public void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -32,7 +36,7 @@ public void onCreate(@Nullable Bundle savedInstanceState) {
 
         mWebView.setBackgroundColor(Color.TRANSPARENT);
         mWebView.getSettings().setJavaScriptEnabled(true);
-        mWebView.getSettings().setUserAgentString(WordPress.getUserAgent());
+        mWebView.getSettings().setUserAgentString(mUserAgent.toString());
 
         mWebView.setWebChromeClient(new WebChromeClientWithVideoPoster(
                 mWebView,
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/views/ReaderWebView.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/views/ReaderWebView.java
index 736a8883063f..4e071f8c2bd2 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/reader/views/ReaderWebView.java
+++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/views/ReaderWebView.java
@@ -18,6 +18,7 @@
 import androidx.annotation.NonNull;
 
 import org.wordpress.android.WordPress;
+import org.wordpress.android.fluxc.network.UserAgent;
 import org.wordpress.android.fluxc.store.AccountStore;
 import org.wordpress.android.ui.WPWebView;
 import org.wordpress.android.util.AppLog;
@@ -77,6 +78,8 @@ public interface ReaderWebViewPageFinishedListener {
     private static boolean mBlogSchemeIsHttps;
 
     private boolean mIsDestroyed;
+
+    @Inject UserAgent mUserAgent;
     @Inject AccountStore mAccountStore;
 
     public ReaderWebView(Context context) {
@@ -103,8 +106,8 @@ private void init(Context context) {
 
             mReaderChromeClient = new ReaderWebChromeClient(this);
             this.setWebChromeClient(mReaderChromeClient);
-            this.setWebViewClient(new ReaderWebViewClient(this));
-            this.getSettings().setUserAgentString(WordPress.getUserAgent());
+            this.setWebViewClient(new ReaderWebViewClient(this, mUserAgent));
+            this.getSettings().setUserAgentString(mUserAgent.toString());
 
             // Enable third-party cookies since they are disabled by default;
             // we need third-party cookies to support authenticated images
@@ -261,12 +264,14 @@ public boolean onTouchEvent(MotionEvent event) {
 
     private static class ReaderWebViewClient extends WebViewClient {
         private final ReaderWebView mReaderWebView;
+        private final UserAgent mUserAgent;
 
-        ReaderWebViewClient(ReaderWebView readerWebView) {
+        ReaderWebViewClient(ReaderWebView readerWebView, UserAgent userAgent) {
             if (readerWebView == null) {
                 throw new IllegalArgumentException("ReaderWebViewClient requires readerWebView");
             }
             mReaderWebView = readerWebView;
+            mUserAgent = userAgent;
         }
 
 
@@ -309,7 +314,7 @@ public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
                     conn.setRequestProperty("Authorization", "Bearer " + mToken);
                     conn.setReadTimeout(TIMEOUT_MS);
                     conn.setConnectTimeout(TIMEOUT_MS);
-                    conn.setRequestProperty("User-Agent", WordPress.getUserAgent());
+                    conn.setRequestProperty("User-Agent", mUserAgent.toString());
                     conn.setRequestProperty("Connection", "Keep-Alive");
                     return new WebResourceResponse(conn.getContentType(),
                             conn.getContentEncoding(),
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/plans/SiteCreationPlansViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/plans/SiteCreationPlansViewModel.kt
index 473a90bfecf4..1b667cf99bf4 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/plans/SiteCreationPlansViewModel.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/plans/SiteCreationPlansViewModel.kt
@@ -10,8 +10,8 @@ import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.receiveAsFlow
 import kotlinx.coroutines.launch
-import org.wordpress.android.WordPress
 import org.wordpress.android.fluxc.model.SiteModel
+import org.wordpress.android.fluxc.network.UserAgent
 import org.wordpress.android.fluxc.store.AccountStore
 import org.wordpress.android.fluxc.store.SiteStore
 import org.wordpress.android.ui.WPWebViewActivity
@@ -23,6 +23,7 @@ import javax.inject.Inject
 
 @HiltViewModel
 class SiteCreationPlansViewModel @Inject constructor(
+    private val userAgent: UserAgent,
     private val accountStore: AccountStore,
     private val siteStore: SiteStore,
     private val networkUtilsWrapper: NetworkUtilsWrapper
@@ -79,7 +80,7 @@ class SiteCreationPlansViewModel @Inject constructor(
             SiteCreationPlansModel(
                 enableJavascript = true,
                 enableDomStorage = true,
-                userAgent = WordPress.getUserAgent(),
+                userAgent = userAgent.toString(),
                 enableChromeClient = true,
                 url = url,
                 addressToLoad = addressToLoad
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/previews/SiteCreationPreviewFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/previews/SiteCreationPreviewFragment.kt
index 8ab86f82a9d1..e4734fe97935 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/previews/SiteCreationPreviewFragment.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/previews/SiteCreationPreviewFragment.kt
@@ -18,10 +18,10 @@ import androidx.core.view.isVisible
 import androidx.fragment.app.activityViewModels
 import dagger.hilt.android.AndroidEntryPoint
 import org.wordpress.android.R
-import org.wordpress.android.WordPress
 import org.wordpress.android.databinding.SiteCreationFormScreenBinding
 import org.wordpress.android.databinding.SiteCreationPreviewScreenBinding
 import org.wordpress.android.databinding.SiteCreationPreviewScreenDefaultBinding
+import org.wordpress.android.fluxc.network.UserAgent
 import org.wordpress.android.ui.sitecreation.SiteCreationActivity.Companion.ARG_STATE
 import org.wordpress.android.ui.sitecreation.SiteCreationBaseFormFragment
 import org.wordpress.android.ui.sitecreation.SiteCreationState
@@ -39,6 +39,9 @@ private const val SLIDE_IN_ANIMATION_DURATION = 450L
 @AndroidEntryPoint
 class SiteCreationPreviewFragment : SiteCreationBaseFormFragment(),
     ErrorManagedWebViewClientListener {
+    @Inject
+    lateinit var userAgent: UserAgent
+
     @Inject
     internal lateinit var uiHelpers: UiHelpers
 
@@ -106,7 +109,7 @@ class SiteCreationPreviewFragment : SiteCreationBaseFormFragment(),
         viewModel.preloadPreview.observe(this) { url ->
             url?.let { urlString ->
                 webView.webViewClient = URLFilteredWebViewClient(urlString, this)
-                webView.settings.userAgentString = WordPress.getUserAgent()
+                webView.settings.userAgentString = userAgent.toString()
                 webView.loadUrl(urlString)
             }
         }
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/sitemonitor/SiteMonitorUtils.kt b/WordPress/src/main/java/org/wordpress/android/ui/sitemonitor/SiteMonitorUtils.kt
index a64e92029030..6ec20e9dcf4f 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/sitemonitor/SiteMonitorUtils.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/sitemonitor/SiteMonitorUtils.kt
@@ -1,15 +1,16 @@
 package org.wordpress.android.ui.sitemonitor
 
-import org.wordpress.android.WordPress
 import org.wordpress.android.analytics.AnalyticsTracker
+import org.wordpress.android.fluxc.network.UserAgent
 import org.wordpress.android.ui.WPWebViewActivity
 import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper
 import javax.inject.Inject
 
 class SiteMonitorUtils @Inject constructor(
+    private val userAgent: UserAgent,
     private val analyticsTrackerWrapper: AnalyticsTrackerWrapper
 ) {
-    fun getUserAgent() = WordPress.getUserAgent()
+    fun getUserAgent() = userAgent.toString()
 
     fun getAuthenticationPostData(authenticationUrl: String,
                                   urlToLoad: String,


Test patch:
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/UserAgentTest.java b/WordPress/src/androidTest/java/org/wordpress/android/UserAgentTest.java
index 8e93118c2d07..79ec7c5bec52 100644
--- a/WordPress/src/androidTest/java/org/wordpress/android/UserAgentTest.java
+++ b/WordPress/src/androidTest/java/org/wordpress/android/UserAgentTest.java
@@ -1,7 +1,13 @@
 package org.wordpress.android;
 
+import android.webkit.WebSettings;
+
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.wordpress.android.fluxc.network.UserAgent;
+
+import javax.inject.Inject;
 
 import static junit.framework.TestCase.assertFalse;
 import static junit.framework.TestCase.assertNotNull;
@@ -24,14 +30,21 @@ public class UserAgentTest {
     @Rule(order = 1)
     public InitializationRule initRule = new InitializationRule();
 
+    @Inject UserAgent mUserAgent;
+
+    @Before
+    public void setUp() {
+        hiltRule.inject();
+    }
+
     @Test
     public void testGetUserAgentAndGetDefaultUserAgent() {
-        String userAgent = WordPress.getUserAgent();
+        String userAgent = mUserAgent.toString();
         assertNotNull("User-Agent must be set", userAgent);
         assertTrue("User-Agent must not be an empty string", userAgent.length() > 0);
         assertTrue("User-Agent must contain app name substring", userAgent.contains(USER_AGENT_APPNAME));
 
-        String defaultUserAgent = WordPress.getDefaultUserAgent();
+        String defaultUserAgent = WebSettings.getDefaultUserAgent(AppInitializer.Companion.getContext());
         assertNotNull("Default User-Agent must be set", defaultUserAgent);
         assertTrue("Default User-Agent must not be an empty string", defaultUserAgent.length() > 0);
         assertFalse("Default User-Agent must not contain app name", defaultUserAgent.contains(USER_AGENT_APPNAME));
diff --git a/WordPress/src/test/java/org/wordpress/android/ui/sitemonitor/SiteMonitorUtilsTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/sitemonitor/SiteMonitorUtilsTest.kt
index 0bf5076d32d5..77d2051b539d 100644
--- a/WordPress/src/test/java/org/wordpress/android/ui/sitemonitor/SiteMonitorUtilsTest.kt
+++ b/WordPress/src/test/java/org/wordpress/android/ui/sitemonitor/SiteMonitorUtilsTest.kt
@@ -8,10 +8,14 @@ import org.mockito.Mock
 import org.mockito.junit.MockitoJUnitRunner
 import org.mockito.kotlin.verify
 import org.wordpress.android.analytics.AnalyticsTracker
+import org.wordpress.android.fluxc.network.UserAgent
 import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper
 
 @RunWith(MockitoJUnitRunner::class)
 class SiteMonitorUtilsTest {
+    @Mock
+    lateinit var userAgent: UserAgent
+
     @Mock
     lateinit var analyticsTrackerWrapper: AnalyticsTrackerWrapper
 
@@ -19,7 +23,7 @@ class SiteMonitorUtilsTest {
 
     @Before
     fun setup() {
-        siteMonitorUtils = SiteMonitorUtils(analyticsTrackerWrapper)
+        siteMonitorUtils = SiteMonitorUtils(userAgent, analyticsTrackerWrapper)
     }
 
     @Test