[Live Caption] Pass a LanguageCode to OnSodaInstalled.

CL doing this for OnSodaError: crrev.com/c/3439172
CL doing this for OnSodaProgress: crrev.com/c/3447537
This work is to simplify SodaInstaller observers' language management.
Design doc: https://docs.google.com/document/d/1OphVFqRcFbqgZYRUp_K2bCkiHdsT4EwJLvAzInfp428/edit

The bulk of the change happens in SodaInstaller, SodaInstallerImpl, and
SodaInstallerImplChromeOS. The rest of the files are mainly parameter
and function name changes.

Bug: 1161569
Fix: 1266491
Change-Id: I331f57f97527938503e77c25a1f25246026548e4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3405315
Reviewed-by: Evan Liu <evliu@google.com>
Reviewed-by: Amanda Deacon <amandadeacon@chromium.org>
Reviewed-by: Tommy Steimel <steimel@chromium.org>
Reviewed-by: David Tseng <dtseng@chromium.org>
Reviewed-by: Xiyuan Xia <xiyuan@chromium.org>
Reviewed-by: Akihiro Ota <akihiroota@chromium.org>
Reviewed-by: Zentaro Kavanagh <zentaro@chromium.org>
Commit-Queue: Abigail Klein <abigailbklein@google.com>
Cr-Commit-Position: refs/heads/main@{#976505}
diff --git a/ash/system/accessibility/tray_accessibility.cc b/ash/system/accessibility/tray_accessibility.cc
index e6d6fee5..20e9ad3a 100644
--- a/ash/system/accessibility/tray_accessibility.cc
+++ b/ash/system/accessibility/tray_accessibility.cc
@@ -603,22 +603,6 @@
   }
 }
 
-void AccessibilityDetailedView::OnSodaInstallSucceeded() {
-  speech::SodaInstaller* soda_installer = speech::SodaInstaller::GetInstance();
-  if (!soda_installer->IsSodaInstalled(GetDictationLocale()))
-    return;
-
-  // Only show the success message if both the SODA binary and the language pack
-  // matching the Dictation locale have been downloaded.
-  soda_installer->RemoveObserver(this);
-  AccessibilityControllerImpl* controller =
-      Shell::Get()->accessibility_controller();
-  if (dictation_view_ && controller->IsDictationSettingVisibleInTray()) {
-    dictation_view_->SetSubText(l10n_util::GetStringUTF16(
-        IDS_ASH_ACCESSIBILITY_DICTATION_SETTING_SUBTITLE_SODA_DOWNLOAD_COMPLETE));
-  }
-}
-
 void AccessibilityDetailedView::OnSodaInstallProgress(
     int progress,
     speech::LanguageCode language_code) {
@@ -655,13 +639,20 @@
 }
 
 // SodaInstaller::Observer:
-void AccessibilityDetailedView::OnSodaInstalled() {
-  OnSodaInstallSucceeded();
-}
-
-void AccessibilityDetailedView::OnSodaLanguagePackInstalled(
+void AccessibilityDetailedView::OnSodaInstalled(
     speech::LanguageCode language_code) {
-  OnSodaInstallSucceeded();
+  if (language_code != GetDictationLocale())
+    return;
+
+  // Show the success message if both the SODA binary and the language pack
+  // matching the Dictation locale have been downloaded.
+  speech::SodaInstaller::GetInstance()->RemoveObserver(this);
+  AccessibilityControllerImpl* controller =
+      Shell::Get()->accessibility_controller();
+  if (dictation_view_ && controller->IsDictationSettingVisibleInTray()) {
+    dictation_view_->SetSubText(l10n_util::GetStringUTF16(
+        IDS_ASH_ACCESSIBILITY_DICTATION_SETTING_SUBTITLE_SODA_DOWNLOAD_COMPLETE));
+  }
 }
 
 void AccessibilityDetailedView::OnSodaError() {
diff --git a/ash/system/accessibility/tray_accessibility.h b/ash/system/accessibility/tray_accessibility.h
index f5f4cb8e..c3cafb3 100644
--- a/ash/system/accessibility/tray_accessibility.h
+++ b/ash/system/accessibility/tray_accessibility.h
@@ -75,13 +75,11 @@
   void AppendAccessibilityList();
 
   void UpdateSodaInstallerObserverStatus();
-  void OnSodaInstallSucceeded();
   void OnSodaInstallProgress(int progress, speech::LanguageCode language_code);
   void OnSodaInstallFailed(speech::LanguageCode language_code);
 
   // SodaInstaller::Observer:
-  void OnSodaInstalled() override;
-  void OnSodaLanguagePackInstalled(speech::LanguageCode language_code) override;
+  void OnSodaInstalled(speech::LanguageCode language_code) override;
   void OnSodaError() override;
   void OnSodaLanguagePackError(speech::LanguageCode language_code) override;
   void OnSodaProgress(int combined_progress) override {}
diff --git a/ash/system/accessibility/tray_accessibility_unittest.cc b/ash/system/accessibility/tray_accessibility_unittest.cc
index 3fcdd27..80c3b97 100644
--- a/ash/system/accessibility/tray_accessibility_unittest.cc
+++ b/ash/system/accessibility/tray_accessibility_unittest.cc
@@ -738,10 +738,9 @@
   // correct language pack before doing anything.
   soda_installer()->NotifySodaInstalledForTesting();
   EXPECT_EQ(kInitialDictationViewSubtitleText, GetDictationViewSubtitleText());
-  soda_installer()->NotifyOnSodaLanguagePackInstalledForTesting(en_us());
+  soda_installer()->NotifySodaInstalledForTesting(en_us());
   EXPECT_EQ(kInitialDictationViewSubtitleText, GetDictationViewSubtitleText());
-  soda_installer()->NotifyOnSodaLanguagePackInstalledForTesting(
-      speech::LanguageCode::kFrFr);
+  soda_installer()->NotifySodaInstalledForTesting(speech::LanguageCode::kFrFr);
   EXPECT_EQ(kSodaDownloaded, GetDictationViewSubtitleText());
 }
 
diff --git a/chrome/browser/accessibility/live_caption_controller_browsertest.cc b/chrome/browser/accessibility/live_caption_controller_browsertest.cc
index 2d166dc9..121db42 100644
--- a/chrome/browser/accessibility/live_caption_controller_browsertest.cc
+++ b/chrome/browser/accessibility/live_caption_controller_browsertest.cc
@@ -83,14 +83,20 @@
   void SetLiveCaptionEnabled(bool enabled) {
     browser()->profile()->GetPrefs()->SetBoolean(prefs::kLiveCaptionEnabled,
                                                  enabled);
-    if (enabled)
+    if (enabled) {
+      speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting(
+          en_us());
       speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting();
+    }
   }
 
   void SetLiveCaptionEnabledOnProfile(bool enabled, Profile* profile) {
     profile->GetPrefs()->SetBoolean(prefs::kLiveCaptionEnabled, enabled);
-    if (enabled)
+    if (enabled) {
+      speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting(
+          en_us());
       speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting();
+    }
   }
 
   LiveCaptionController* GetController() {
@@ -181,6 +187,8 @@
 #endif
   }
 
+  speech::LanguageCode en_us() { return speech::LanguageCode::kEnUs; }
+
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
   std::unique_ptr<CaptionBubbleContextBrowser> caption_bubble_context_;
@@ -263,6 +271,7 @@
   EXPECT_FALSE(HasBubbleController());
 
   // The UI is only created after SODA is installed.
+  speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting(en_us());
   speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting();
   EXPECT_TRUE(HasBubbleController());
 }
diff --git a/chrome/browser/accessibility/live_caption_speech_recognition_host_browsertest.cc b/chrome/browser/accessibility/live_caption_speech_recognition_host_browsertest.cc
index 5ea48bc..d4f977f 100644
--- a/chrome/browser/accessibility/live_caption_speech_recognition_host_browsertest.cc
+++ b/chrome/browser/accessibility/live_caption_speech_recognition_host_browsertest.cc
@@ -125,8 +125,11 @@
   void SetLiveCaptionEnabled(bool enabled) {
     browser()->profile()->GetPrefs()->SetBoolean(prefs::kLiveCaptionEnabled,
                                                  enabled);
-    if (enabled)
+    if (enabled) {
+      speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting(
+          speech::LanguageCode::kEnUs);
       speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting();
+    }
   }
 
   bool HasBubbleController() {
diff --git a/chrome/browser/accessibility/soda_installer_impl.cc b/chrome/browser/accessibility/soda_installer_impl.cc
index aa9a2868..80196a2a 100644
--- a/chrome/browser/accessibility/soda_installer_impl.cc
+++ b/chrome/browser/accessibility/soda_installer_impl.cc
@@ -169,7 +169,6 @@
           NotifyOnSodaLanguagePackProgress(language_progress, language_code);
         }
       }
-
     } break;
     case Events::COMPONENT_UPDATE_ERROR:
       is_soda_downloading_ = false;
@@ -185,7 +184,6 @@
 
         base::UmaHistogramBoolean(
             GetInstallationResultMetricForLanguagePack(language_code), false);
-
       } else {
         base::UmaHistogramTimes(
             kSodaBinaryInstallationFailureTimeTaken,
@@ -207,8 +205,8 @@
 void SodaInstallerImpl::OnSodaBinaryInstalled() {
   soda_binary_installed_ = true;
   is_soda_downloading_ = false;
-  if (IsAnyLanguagePackInstalled()) {
-    NotifyOnSodaInstalled();
+  for (LanguageCode language : installed_languages_) {
+    NotifyOnSodaInstalled(language);
   }
 
   base::UmaHistogramTimes(kSodaBinaryInstallationSuccessTimeTaken,
@@ -220,10 +218,9 @@
     speech::LanguageCode language_code) {
   installed_languages_.insert(language_code);
   language_pack_progress_.erase(language_code);
-  NotifyOnSodaLanguagePackInstalled(language_code);
 
   if (soda_binary_installed_) {
-    NotifyOnSodaInstalled();
+    NotifyOnSodaInstalled(language_code);
   }
 
   base::UmaHistogramTimes(
diff --git a/chrome/browser/ash/accessibility/accessibility_manager.cc b/chrome/browser/ash/accessibility/accessibility_manager.cc
index 573f9a8d85..5d00ab60 100644
--- a/chrome/browser/ash/accessibility/accessibility_manager.cc
+++ b/chrome/browser/ash/accessibility/accessibility_manager.cc
@@ -946,7 +946,7 @@
     // nudge hasn't yet been shown to the user.
     if (!offline_nudge || !offline_nudge.value()) {
       if (speech::SodaInstaller::GetInstance()->IsSodaInstalled(
-              speech::GetLanguageCode(dictation_locale))) {
+              GetDictationLanguageCode())) {
         // The locale is already installed on device, show the nudge
         // immediately.
         ShowDictationLanguageUpgradedNudge(dictation_locale);
@@ -2027,16 +2027,11 @@
   if (!::features::IsDictationOfflineAvailable())
     return true;
 
+  // Show the dialog for languages not supported by SODA.
   speech::SodaInstaller* soda_installer = speech::SodaInstaller::GetInstance();
   std::vector<std::string> supported_languages =
       soda_installer->GetAvailableLanguages();
-  if (std::find(supported_languages.begin(), supported_languages.end(),
-                locale) == supported_languages.end()) {
-    // Show the dialog for languages not supported by SODA.
-    return true;
-  }
-
-  return false;
+  return !base::Contains(supported_languages, locale);
 }
 
 void AccessibilityManager::ShowNetworkDictationDialog() {
@@ -2098,12 +2093,6 @@
   soda_failed_notification_shown_ = false;
 }
 
-void AccessibilityManager::OnSodaInstallSucceeded() {
-  if (ShouldShowSodaSucceededNotificationForDictation())
-    ShowSodaDownloadNotificationForDictation(true);
-  OnSodaInstallUpdated(100);
-}
-
 void AccessibilityManager::OnSodaInstallError(
     speech::LanguageCode language_code) {
   if (ShouldShowSodaFailedNotificationForDictation(language_code))
@@ -2118,15 +2107,13 @@
   speech::SodaInstaller* soda_installer = speech::SodaInstaller::GetInstance();
   const std::string dictation_locale =
       profile_->GetPrefs()->GetString(prefs::kAccessibilityDictationLocale);
-  speech::LanguageCode dictation_language_code =
-      speech::GetLanguageCode(dictation_locale);
   // Update the Dictation button tray.
   // TODO(https://crbug.com/1266491): Ensure we use combined progress instead
   // of just the language pack progress.
   AccessibilityController::Get()
       ->UpdateDictationButtonOnSpeechRecognitionDownloadChanged(progress);
 
-  if (soda_installer->IsSodaDownloading(dictation_language_code))
+  if (soda_installer->IsSodaDownloading(GetDictationLanguageCode()))
     return;
 
   const absl::optional<bool> offline_nudge =
@@ -2135,33 +2122,29 @@
   // shown to the user (the key is in kAccessibilityDictationLocale but the
   // value is false).
   if (offline_nudge && !offline_nudge.value() &&
-      soda_installer->IsSodaInstalled(
-          speech::GetLanguageCode(dictation_locale))) {
+      soda_installer->IsSodaInstalled(GetDictationLanguageCode())) {
     ShowDictationLanguageUpgradedNudge(dictation_locale);
   }
 }
 
 // SodaInstaller::Observer:
-void AccessibilityManager::OnSodaInstalled() {
-  OnSodaInstallSucceeded();
+void AccessibilityManager::OnSodaInstalled(speech::LanguageCode language_code) {
+  if (language_code != GetDictationLanguageCode())
+    return;
+
+  if (ShouldShowSodaSucceededNotificationForDictation())
+    ShowSodaDownloadNotificationForDictation(true);
+  OnSodaInstallUpdated(100);
 }
 
 void AccessibilityManager::OnSodaError() {
   OnSodaInstallError(speech::LanguageCode::kNone);
 }
 
-void AccessibilityManager::OnSodaLanguagePackInstalled(
-    speech::LanguageCode language_code) {
-  OnSodaInstallSucceeded();
-}
-
 void AccessibilityManager::OnSodaLanguagePackProgress(
     int language_progress,
     speech::LanguageCode language_code) {
-  const std::string locale =
-      profile_->GetPrefs()->GetString(prefs::kAccessibilityDictationLocale);
-
-  if (language_code != speech::GetLanguageCode(locale))
+  if (language_code != GetDictationLanguageCode())
     return;
 
   OnSodaInstallUpdated(language_progress);
@@ -2182,14 +2165,8 @@
   // download, either for the SODA binary or a language pack.
   // Both the SODA binary and the language pack matching the Dictation locale
   // need to be downloaded to return true.
-  const std::string locale =
-      profile_->GetPrefs()->GetString(prefs::kAccessibilityDictationLocale);
-  if (speech::SodaInstaller::GetInstance()->IsSodaInstalled(
-          speech::GetLanguageCode(locale))) {
-    return true;
-  }
-
-  return false;
+  return speech::SodaInstaller::GetInstance()->IsSodaInstalled(
+      GetDictationLanguageCode());
 }
 
 bool AccessibilityManager::ShouldShowSodaFailedNotificationForDictation(
@@ -2207,13 +2184,8 @@
   // 1. |language_code| == kNone (encodes that this was an error for the SODA
   // binary), or
   // 2. |language_code| matches the Dictation locale.
-  const std::string locale =
-      profile_->GetPrefs()->GetString(prefs::kAccessibilityDictationLocale);
-  if (language_code == speech::LanguageCode::kNone ||
-      language_code == speech::GetLanguageCode(locale))
-    return true;
-
-  return false;
+  return language_code == speech::LanguageCode::kNone ||
+         language_code == GetDictationLanguageCode();
 }
 
 void AccessibilityManager::ShowSodaDownloadNotificationForDictation(
@@ -2236,4 +2208,10 @@
     soda_failed_notification_shown_ = true;
 }
 
+speech::LanguageCode AccessibilityManager::GetDictationLanguageCode() {
+  DCHECK(profile_);
+  return speech::GetLanguageCode(
+      profile_->GetPrefs()->GetString(prefs::kAccessibilityDictationLocale));
+}
+
 }  // namespace ash
diff --git a/chrome/browser/ash/accessibility/accessibility_manager.h b/chrome/browser/ash/accessibility/accessibility_manager.h
index 0376a59..65176cc 100644
--- a/chrome/browser/ash/accessibility/accessibility_manager.h
+++ b/chrome/browser/ash/accessibility/accessibility_manager.h
@@ -365,8 +365,7 @@
                                   double value);
 
   // SodaInstaller::Observer:
-  void OnSodaInstalled() override;
-  void OnSodaLanguagePackInstalled(speech::LanguageCode language_code) override;
+  void OnSodaInstalled(speech::LanguageCode language_code) override;
   void OnSodaError() override;
   void OnSodaLanguagePackError(speech::LanguageCode language_code) override;
   void OnSodaProgress(int combined_progress) override {}
@@ -494,7 +493,6 @@
 
   // SODA-related methods.
   void MaybeInstallSoda(const std::string& locale);
-  void OnSodaInstallSucceeded();
   void OnSodaInstallError(speech::LanguageCode language_code);
   void OnSodaInstallUpdated(int progress);
   bool ShouldShowSodaSucceededNotificationForDictation();
@@ -503,6 +501,7 @@
   void ShowSodaDownloadNotificationForDictation(bool succeeded);
 
   void ShowDictationLanguageUpgradedNudge(const std::string& locale);
+  speech::LanguageCode GetDictationLanguageCode();
 
   void CreateChromeVoxPanel();
 
diff --git a/chrome/browser/ash/accessibility/accessibility_manager_browsertest.cc b/chrome/browser/ash/accessibility/accessibility_manager_browsertest.cc
index b787a60..1bd24c7 100644
--- a/chrome/browser/ash/accessibility/accessibility_manager_browsertest.cc
+++ b/chrome/browser/ash/accessibility/accessibility_manager_browsertest.cc
@@ -821,7 +821,8 @@
   // The nudge should not be requested to be shown because this was a
   // user-initiated change.
   EXPECT_FALSE(GetDictationOfflineNudgePref("en-US"));
-  speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting();
+  soda_installer()->NotifySodaInstalledForTesting();
+  soda_installer()->NotifySodaInstalledForTesting(en_us());
   EXPECT_FALSE(IsSodaDownloading());
   // The nudge was never shown.
   EXPECT_FALSE(GetDictationOfflineNudgePref("en-US"));
@@ -841,9 +842,7 @@
   // The nudge should be shown when SODA download finishes.
   EXPECT_FALSE(GetDictationOfflineNudgePref("en-US").value());
   speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting();
-  speech::SodaInstaller::GetInstance()
-      ->NotifyOnSodaLanguagePackInstalledForTesting(
-          speech::LanguageCode::kEnUs);
+  speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting(en_us());
   EXPECT_FALSE(IsSodaDownloading());
   EXPECT_TRUE(GetDictationOfflineNudgePref("en-US").value());
   // No notifications were shown.
@@ -876,7 +875,8 @@
   ClearDictationOfflineNudgePref("en-US");
   EnableDictationTriggeredByUser(/*soda_uninstalled_first=*/true);
   EXPECT_TRUE(IsSodaDownloading());
-  speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting();
+  soda_installer()->NotifySodaInstalledForTesting();
+  soda_installer()->NotifySodaInstalledForTesting(en_us());
   EXPECT_FALSE(IsSodaDownloading());
   EXPECT_TRUE(GetDictationOfflineNudgePref("en-US").value());
   UninstallSodaForTesting();
@@ -885,7 +885,8 @@
   // The second time the same language downloads, the nudge is not shown again.
   EnableDictationTriggeredByUser(/*soda_uninstalled_first=*/false);
   EXPECT_TRUE(IsSodaDownloading());
-  speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting();
+  soda_installer()->NotifySodaInstalledForTesting();
+  soda_installer()->NotifySodaInstalledForTesting(en_us());
   EXPECT_FALSE(IsSodaDownloading());
   // Unchanged.
   EXPECT_TRUE(GetDictationOfflineNudgePref("en-US").value());
@@ -893,7 +894,8 @@
 
 IN_PROC_BROWSER_TEST_F(AccessibilityManagerSodaTest,
                        SodaInstalledBeforeDictationEnabled) {
-  speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting();
+  soda_installer()->NotifySodaInstalledForTesting();
+  soda_installer()->NotifySodaInstalledForTesting(en_us());
   ClearDictationOfflineNudgePref("en-US");
   EnableDictationTriggeredByUser(/*soda_uninstalled_first=*/false);
 
@@ -920,7 +922,8 @@
   // enabled. This mocks selecting a new locale from settings.
   SetDictationLocale("en-US");
   EXPECT_TRUE(IsSodaDownloading());
-  speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting();
+  soda_installer()->NotifySodaInstalledForTesting();
+  soda_installer()->NotifySodaInstalledForTesting(en_us());
   EXPECT_FALSE(IsSodaDownloading());
   // The nudge was never shown because this was a user-initiated change.
   EXPECT_FALSE(GetDictationOfflineNudgePref("en-US"));
@@ -939,8 +942,9 @@
   speech::LanguageCode fr_fr = speech::LanguageCode::kFrFr;
   SetDictationEnabled(true);
   soda_installer()->NotifySodaInstalledForTesting();
+  soda_installer()->NotifySodaInstalledForTesting(en_us());
   AssertMessageCenterEmpty();
-  soda_installer()->NotifyOnSodaLanguagePackInstalledForTesting(fr_fr);
+  soda_installer()->NotifySodaInstalledForTesting(fr_fr);
   AssertSodaNotificationShownForDictation(u"français (France)",
                                           /*success=*/true);
 }
@@ -950,7 +954,7 @@
 IN_PROC_BROWSER_TEST_F(AccessibilityManagerSodaTest,
                        SucceededNotificationCase2) {
   SetDictationEnabled(true);
-  soda_installer()->NotifyOnSodaLanguagePackInstalledForTesting(en_us());
+  soda_installer()->NotifySodaInstalledForTesting(en_us());
   AssertMessageCenterEmpty();
   soda_installer()->NotifySodaInstalledForTesting();
   AssertSodaNotificationShownForDictation(en_us_display_name(),
@@ -982,7 +986,7 @@
 IN_PROC_BROWSER_TEST_F(AccessibilityManagerSodaTest,
                        LanguageInstalledBinaryFails) {
   SetDictationEnabled(true);
-  soda_installer()->NotifyOnSodaLanguagePackInstalledForTesting(en_us());
+  soda_installer()->NotifySodaInstalledForTesting(en_us());
   AssertMessageCenterEmpty();
   soda_installer()->NotifySodaErrorForTesting();
   AssertSodaNotificationShownForDictation(en_us_display_name(),
@@ -998,6 +1002,7 @@
   speech::LanguageCode fr_fr = speech::LanguageCode::kFrFr;
   SetDictationEnabled(true);
   soda_installer()->NotifySodaInstalledForTesting();
+  soda_installer()->NotifySodaInstalledForTesting(en_us());
   AssertMessageCenterEmpty();
   soda_installer()->NotifyOnSodaLanguagePackErrorForTesting(fr_fr);
   AssertSodaNotificationShownForDictation(u"français (France)",
@@ -1047,7 +1052,7 @@
 IN_PROC_BROWSER_TEST_F(AccessibilityManagerSodaTest, NotTriggeredByUser) {
   EnableDictationTriggeredByUser(/*soda_uninstalled_first=*/false);
   soda_installer()->NotifySodaInstalledForTesting();
-  soda_installer()->NotifyOnSodaLanguagePackInstalledForTesting(en_us());
+  soda_installer()->NotifySodaInstalledForTesting(en_us());
   AssertMessageCenterEmpty();
 }
 
@@ -1059,7 +1064,7 @@
   SetDictationEnabled(true);
   soda_installer()->NotifySodaInstalledForTesting();
   AssertMessageCenterEmpty();
-  soda_installer()->NotifyOnSodaLanguagePackInstalledForTesting(en_us());
+  soda_installer()->NotifySodaInstalledForTesting(en_us());
   AssertMessageCenterEmpty();
 }
 
@@ -1074,7 +1079,7 @@
   // enabled. This mocks selecting a new locale from settings.
   SetDictationLocale("en-US");
   soda_installer()->NotifySodaInstalledForTesting();
-  soda_installer()->NotifyOnSodaLanguagePackInstalledForTesting(en_us());
+  soda_installer()->NotifySodaInstalledForTesting(en_us());
 
   // The notification should have been shown.
   AssertSodaNotificationShownForDictation(en_us_display_name(),
@@ -1111,6 +1116,7 @@
   EXPECT_EQ(70, test_api->GetDictationSodaDownloadProgress());
   // If SODA download succeeds, the API will be called with a value of 100.
   soda_installer()->NotifySodaInstalledForTesting();
+  soda_installer()->NotifySodaInstalledForTesting(en_us());
   EXPECT_EQ(100, test_api->GetDictationSodaDownloadProgress());
 }
 
diff --git a/chrome/browser/speech/on_device_speech_recognizer_browsertest.cc b/chrome/browser/speech/on_device_speech_recognizer_browsertest.cc
index 70f6188..3c57417 100644
--- a/chrome/browser/speech/on_device_speech_recognizer_browsertest.cc
+++ b/chrome/browser/speech/on_device_speech_recognizer_browsertest.cc
@@ -116,6 +116,8 @@
     mock_speech_delegate_ =
         std::make_unique<testing::StrictMock<MockSpeechRecognizerDelegate>>();
     // Fake that SODA is installed.
+    speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting(
+        speech::LanguageCode::kEnUs);
     speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting();
   }
 
diff --git a/chrome/browser/speech/speech_recognition_client_browser_interface.cc b/chrome/browser/speech/speech_recognition_client_browser_interface.cc
index ad3c368..510ade71 100644
--- a/chrome/browser/speech/speech_recognition_client_browser_interface.cc
+++ b/chrome/browser/speech/speech_recognition_client_browser_interface.cc
@@ -58,7 +58,10 @@
   OnSpeechRecognitionAvailabilityChanged();
 }
 
-void SpeechRecognitionClientBrowserInterface::OnSodaInstalled() {
+void SpeechRecognitionClientBrowserInterface::OnSodaInstalled(
+    speech::LanguageCode language_code) {
+  if (!prefs::IsLanguageCodeForLiveCaption(language_code, profile_prefs_))
+    return;
   NotifyObservers(profile_prefs_->GetBoolean(prefs::kLiveCaptionEnabled));
 }
 
diff --git a/chrome/browser/speech/speech_recognition_client_browser_interface.h b/chrome/browser/speech/speech_recognition_client_browser_interface.h
index 6bb65ee..d0286c2 100644
--- a/chrome/browser/speech/speech_recognition_client_browser_interface.h
+++ b/chrome/browser/speech/speech_recognition_client_browser_interface.h
@@ -45,7 +45,7 @@
           pending_remote) override;
 
   // SodaInstaller::Observer:
-  void OnSodaInstalled() override;
+  void OnSodaInstalled(speech::LanguageCode language_code) override;
   void OnSodaProgress(int combined_progress) override {}
   void OnSodaError() override {}
 
diff --git a/chrome/browser/speech/speech_recognition_test_helper.cc b/chrome/browser/speech/speech_recognition_test_helper.cc
index ec3e67aa..5e56dd2a 100644
--- a/chrome/browser/speech/speech_recognition_test_helper.cc
+++ b/chrome/browser/speech/speech_recognition_test_helper.cc
@@ -39,6 +39,8 @@
 void SpeechRecognitionTestHelper::SetUpOnDeviceRecognition(Profile* profile) {
   // Fake that SODA is installed so SpeechRecognitionPrivate uses
   // OnDeviceSpeechRecognizer.
+  speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting(
+      speech::LanguageCode::kEnUs);
   speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting();
   CrosSpeechRecognitionServiceFactory::GetInstanceForTest()
       ->SetTestingFactoryAndUse(
diff --git a/chrome/browser/ui/ash/projector/projector_client_impl_unittest.cc b/chrome/browser/ui/ash/projector/projector_client_impl_unittest.cc
index 1842607..97be4722 100644
--- a/chrome/browser/ui/ash/projector/projector_client_impl_unittest.cc
+++ b/chrome/browser/ui/ash/projector/projector_client_impl_unittest.cc
@@ -95,6 +95,7 @@
     SetLocale(kEnglishLocale);
     soda_installer_ = std::make_unique<MockSodaInstaller>();
     soda_installer_->NotifySodaInstalledForTesting();
+    soda_installer_->NotifySodaInstalledForTesting(speech::LanguageCode::kEnUs);
     projector_client_ =
         std::make_unique<ProjectorClientImpl>(&projector_controller_);
   }
diff --git a/chrome/browser/ui/ash/projector/projector_soda_installation_controller.cc b/chrome/browser/ui/ash/projector/projector_soda_installation_controller.cc
index 081ea989..4cdf689 100644
--- a/chrome/browser/ui/ash/projector/projector_soda_installation_controller.cc
+++ b/chrome/browser/ui/ash/projector/projector_soda_installation_controller.cc
@@ -89,13 +89,11 @@
   return speech::SodaInstaller::GetInstance()->IsSodaInstalled(language_code);
 }
 
-void ProjectorSodaInstallationController::OnSodaInstalled() {
-  auto* soda_installer = speech::SodaInstaller::GetInstance();
-  // Make sure that both SODA binary and the locale language are available
-  // before notifying that on device speech recognition is available.
-  if (!soda_installer->IsSodaInstalled(speech::GetLanguageCode(GetLocale())))
+void ProjectorSodaInstallationController::OnSodaInstalled(
+    speech::LanguageCode language_code) {
+  // Check that language code matches the selected language for projector.
+  if (language_code != speech::GetLanguageCode(GetLocale()))
     return;
-
   projector_controller_->OnSpeechRecognitionAvailabilityChanged(
       ash::SpeechRecognitionAvailability::kAvailable);
   app_client_->OnSodaInstalled();
diff --git a/chrome/browser/ui/ash/projector/projector_soda_installation_controller.h b/chrome/browser/ui/ash/projector/projector_soda_installation_controller.h
index 4fe6a8b9..257d19a 100644
--- a/chrome/browser/ui/ash/projector/projector_soda_installation_controller.h
+++ b/chrome/browser/ui/ash/projector/projector_soda_installation_controller.h
@@ -46,9 +46,7 @@
 
  protected:
   // speech::SodaInstaller::Observer:
-  void OnSodaInstalled() override;
-  void OnSodaLanguagePackInstalled(
-      speech::LanguageCode language_code) override {}
+  void OnSodaInstalled(speech::LanguageCode language_code) override;
   void OnSodaError() override;
   void OnSodaLanguagePackError(speech::LanguageCode language_code) override {}
   void OnSodaProgress(int combined_progress) override;
diff --git a/chrome/browser/ui/ash/projector/projector_soda_installation_controller_unittest.cc b/chrome/browser/ui/ash/projector/projector_soda_installation_controller_unittest.cc
index e984ab5..606532a 100644
--- a/chrome/browser/ui/ash/projector/projector_soda_installation_controller_unittest.cc
+++ b/chrome/browser/ui/ash/projector/projector_soda_installation_controller_unittest.cc
@@ -100,6 +100,8 @@
   }
 
   MockSodaInstaller* soda_installer() { return soda_installer_.get(); }
+  speech::LanguageCode en_us() { return speech::LanguageCode::kEnUs; }
+  speech::LanguageCode fr_fr() { return speech::LanguageCode::kFrFr; }
 
  private:
   content::BrowserTaskEnvironment task_environment_;
@@ -122,25 +124,21 @@
       .WillByDefault(
           testing::Return(std::vector<std::string>({kEnglishLocale})));
 
-  EXPECT_TRUE(soda_installation_controller()->ShouldDownloadSoda(
-      speech::LanguageCode::kEnUs));
+  EXPECT_TRUE(soda_installation_controller()->ShouldDownloadSoda(en_us()));
 
   // Other languages other than English are not currently supported.
-  EXPECT_FALSE(soda_installation_controller()->ShouldDownloadSoda(
-      speech::LanguageCode::kFrFr));
+  EXPECT_FALSE(soda_installation_controller()->ShouldDownloadSoda(fr_fr()));
 }
 
 TEST_F(ProjectorSodaInstallationControllerTest, IsSpeechRecognitionAvailable) {
   SetLocale(kEnglishLocale);
-  EXPECT_FALSE(soda_installation_controller()->IsSodaAvailable(
-      speech::LanguageCode::kEnUs));
+  EXPECT_FALSE(soda_installation_controller()->IsSodaAvailable(en_us()));
 
   EXPECT_CALL(app_client(), OnSodaInstalled()).Times(1);
   speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting();
-  EXPECT_TRUE(soda_installation_controller()->IsSodaAvailable(
-      speech::LanguageCode::kEnUs));
-  EXPECT_FALSE(soda_installation_controller()->IsSodaAvailable(
-      speech::LanguageCode::kFrFr));
+  speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting(en_us());
+  EXPECT_TRUE(soda_installation_controller()->IsSodaAvailable(en_us()));
+  EXPECT_FALSE(soda_installation_controller()->IsSodaAvailable(fr_fr()));
 }
 
 TEST_F(ProjectorSodaInstallationControllerTest, InstallSoda) {
@@ -153,6 +151,7 @@
 
   EXPECT_CALL(app_client(), OnSodaInstalled()).Times(1);
   speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting();
+  speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting(en_us());
 }
 
 TEST_F(ProjectorSodaInstallationControllerTest, OnSodaInstallProgress) {
diff --git a/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc b/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc
index 45d4926..d3be805 100644
--- a/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc
+++ b/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc
@@ -373,7 +373,9 @@
   live_caption_button_->SetIsOn(enabled);
 }
 
-void MediaDialogView::OnSodaInstalled() {
+void MediaDialogView::OnSodaInstalled(speech::LanguageCode language_code) {
+  if (!prefs::IsLanguageCodeForLiveCaption(language_code, profile_->GetPrefs()))
+    return;
   speech::SodaInstaller::GetInstance()->RemoveObserver(this);
   live_caption_title_->SetText(GetLiveCaptionTitle(profile_->GetPrefs()));
 }
diff --git a/chrome/browser/ui/views/global_media_controls/media_dialog_view.h b/chrome/browser/ui/views/global_media_controls/media_dialog_view.h
index a46b09a..b7a0282 100644
--- a/chrome/browser/ui/views/global_media_controls/media_dialog_view.h
+++ b/chrome/browser/ui/views/global_media_controls/media_dialog_view.h
@@ -127,7 +127,7 @@
   void UpdateBubbleSize();
 
   // SodaInstaller::Observer overrides:
-  void OnSodaInstalled() override;
+  void OnSodaInstalled(speech::LanguageCode language_code) override;
   void OnSodaError() override;
   void OnSodaProgress(int combined_progress) override;
 
diff --git a/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc b/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc
index c995529..3fcb9163 100644
--- a/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc
+++ b/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc
@@ -547,9 +547,8 @@
   }
 
   void OnSodaLanguagePackInstalled() {
-    speech::SodaInstaller::GetInstance()
-        ->NotifyOnSodaLanguagePackInstalledForTesting(
-            speech::LanguageCode::kEnUs);
+    speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting(
+        speech::LanguageCode::kEnUs);
   }
 
  protected:
diff --git a/chrome/browser/ui/webui/settings/captions_handler.cc b/chrome/browser/ui/webui/settings/captions_handler.cc
index d4d40db..6e696bd 100644
--- a/chrome/browser/ui/webui/settings/captions_handler.cc
+++ b/chrome/browser/ui/webui/settings/captions_handler.cc
@@ -73,24 +73,22 @@
 #endif
 }
 
-void CaptionsHandler::OnSodaInstalled() {
+void CaptionsHandler::OnSodaInstalled(speech::LanguageCode language_code) {
   if (!base::FeatureList::IsEnabled(media::kLiveCaptionMultiLanguage) &&
       soda_available_) {
+    // If multi-language is disabled and the language code received is not for
+    // Live Caption (perhaps it is downloading because another feature, such as
+    // dictation on ChromeOS, has a different language selected), then return
+    // early. We do not check for a matching language if multi-language is
+    // enabled because we show all of the languages' download status in the UI,
+    // even ones that are not currently selected.
+    if (!prefs::IsLanguageCodeForLiveCaption(language_code, prefs_))
+      return;
     speech::SodaInstaller::GetInstance()->RemoveObserver(this);
   }
 
   FireWebUIListener("soda-download-progress-changed",
                     base::Value(l10n_util::GetStringUTF16(
-                        IDS_SETTINGS_CAPTIONS_LIVE_CAPTION_DOWNLOAD_COMPLETE)));
-}
-
-void CaptionsHandler::OnSodaLanguagePackInstalled(
-    speech::LanguageCode language_code) {
-  if (!base::FeatureList::IsEnabled(media::kLiveCaptionMultiLanguage))
-    return;
-
-  FireWebUIListener("soda-download-progress-changed",
-                    base::Value(l10n_util::GetStringUTF16(
                         IDS_SETTINGS_CAPTIONS_LIVE_CAPTION_DOWNLOAD_COMPLETE)),
                     base::Value(speech::GetLanguageName(language_code)));
 }
diff --git a/chrome/browser/ui/webui/settings/captions_handler.h b/chrome/browser/ui/webui/settings/captions_handler.h
index e353336d..88324471 100644
--- a/chrome/browser/ui/webui/settings/captions_handler.h
+++ b/chrome/browser/ui/webui/settings/captions_handler.h
@@ -33,8 +33,7 @@
   void HandleOpenSystemCaptionsDialog(const base::Value::List& args);
 
   // SodaInstaller::Observer overrides:
-  void OnSodaInstalled() override;
-  void OnSodaLanguagePackInstalled(speech::LanguageCode language_code) override;
+  void OnSodaInstalled(speech::LanguageCode language_code) override;
   void OnSodaError() override;
   void OnSodaLanguagePackError(speech::LanguageCode language_code) override;
   void OnSodaProgress(int combined_progress) override;
diff --git a/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc b/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc
index 8753b90..84dbfa4 100644
--- a/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc
@@ -162,21 +162,6 @@
   }
 }
 
-void AccessibilityHandler::OnSodaInstallSucceeded() {
-  if (!speech::SodaInstaller::GetInstance()->IsSodaInstalled(
-          GetDictationLocale())) {
-    return;
-  }
-
-  // Only show the success message if both the SODA binary and the language pack
-  // matching the Dictation locale have been downloaded.
-  FireWebUIListener(
-      "dictation-locale-menu-subtitle-changed",
-      base::Value(l10n_util::GetStringFUTF16(
-          IDS_SETTINGS_ACCESSIBILITY_DICTATION_LOCALE_SUB_LABEL_OFFLINE,
-          GetDictationLocaleDisplayName())));
-}
-
 void AccessibilityHandler::OnSodaInstallProgress(
     int progress,
     speech::LanguageCode language_code) {
@@ -209,13 +194,17 @@
 }
 
 // SodaInstaller::Observer:
-void AccessibilityHandler::OnSodaInstalled() {
-  OnSodaInstallSucceeded();
-}
+void AccessibilityHandler::OnSodaInstalled(speech::LanguageCode language_code) {
+  if (language_code != GetDictationLocale())
+    return;
 
-void AccessibilityHandler::OnSodaLanguagePackInstalled(
-    speech::LanguageCode language_code) {
-  OnSodaInstallSucceeded();
+  // Only show the success message if both the SODA binary and the language pack
+  // matching the Dictation locale have been downloaded.
+  FireWebUIListener(
+      "dictation-locale-menu-subtitle-changed",
+      base::Value(l10n_util::GetStringFUTF16(
+          IDS_SETTINGS_ACCESSIBILITY_DICTATION_LOCALE_SUB_LABEL_OFFLINE,
+          GetDictationLocaleDisplayName())));
 }
 
 void AccessibilityHandler::OnSodaLanguagePackProgress(
diff --git a/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h b/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h
index abaeb2b..659e294 100644
--- a/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h
@@ -48,13 +48,11 @@
   void OpenExtensionOptionsPage(const char extension_id[]);
 
   void MaybeAddSodaInstallerObserver();
-  void OnSodaInstallSucceeded();
   void OnSodaInstallProgress(int progress, speech::LanguageCode language_code);
   void OnSodaInstallFailed(speech::LanguageCode language_code);
 
   // SodaInstaller::Observer:
-  void OnSodaInstalled() override;
-  void OnSodaLanguagePackInstalled(speech::LanguageCode language_code) override;
+  void OnSodaInstalled(speech::LanguageCode language_code) override;
   void OnSodaProgress(int progress) override {}
   void OnSodaLanguagePackProgress(int language_progress,
                                   speech::LanguageCode language_code) override;
diff --git a/chrome/browser/ui/webui/settings/chromeos/accessibility_handler_browsertest.cc b/chrome/browser/ui/webui/settings/chromeos/accessibility_handler_browsertest.cc
index 9377193..e8433fb 100644
--- a/chrome/browser/ui/webui/settings/chromeos/accessibility_handler_browsertest.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/accessibility_handler_browsertest.cc
@@ -151,9 +151,9 @@
   // correct language pack before doing anything.
   soda_installer()->NotifySodaInstalledForTesting();
   AssertWebUICalls(num_calls);
-  soda_installer()->NotifyOnSodaLanguagePackInstalledForTesting(en_us());
+  soda_installer()->NotifySodaInstalledForTesting(en_us());
   AssertWebUICalls(num_calls);
-  soda_installer()->NotifyOnSodaLanguagePackInstalledForTesting(fr_fr());
+  soda_installer()->NotifySodaInstalledForTesting(fr_fr());
   AssertWebUICalls(num_calls + 1);
   ASSERT_TRUE(WasWebUIListenerCalledWithStringArgument(
       "dictation-locale-menu-subtitle-changed",
@@ -285,6 +285,7 @@
 IN_PROC_BROWSER_TEST_F(AccessibilityHandlerTest,
                        DictationLocalesOfflineAndInstalled) {
   speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting();
+  speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting(en_us());
   MaybeAddDictationLocales();
   base::Value::ConstListView argument;
   ASSERT_TRUE(
diff --git a/components/live_caption/live_caption_controller.cc b/components/live_caption/live_caption_controller.cc
index 100ff82e..7f1ffc01 100644
--- a/components/live_caption/live_caption_controller.cc
+++ b/components/live_caption/live_caption_controller.cc
@@ -142,7 +142,10 @@
   DestroyUI();
 }
 
-void LiveCaptionController::OnSodaInstalled() {
+void LiveCaptionController::OnSodaInstalled(
+    speech::LanguageCode language_code) {
+  if (!prefs::IsLanguageCodeForLiveCaption(language_code, profile_prefs_))
+    return;
   // Live Caption should always be enabled when this is called. If Live Caption
   // has been disabled, then this should not be observing the SodaInstaller
   // anymore.
diff --git a/components/live_caption/live_caption_controller.h b/components/live_caption/live_caption_controller.h
index 3d54187f..cefd1b9 100644
--- a/components/live_caption/live_caption_controller.h
+++ b/components/live_caption/live_caption_controller.h
@@ -83,7 +83,7 @@
   friend class LiveCaptionSpeechRecognitionHostTest;
 
   // SodaInstaller::Observer:
-  void OnSodaInstalled() override;
+  void OnSodaInstalled(speech::LanguageCode language_code) override;
   void OnSodaProgress(int combined_progress) override {}
   void OnSodaError() override {}
 
diff --git a/components/live_caption/pref_names.cc b/components/live_caption/pref_names.cc
index 79adaac..cf4bb31 100644
--- a/components/live_caption/pref_names.cc
+++ b/components/live_caption/pref_names.cc
@@ -34,6 +34,12 @@
   return speech::kUsEnglishLocale;
 }
 
+bool IsLanguageCodeForLiveCaption(speech::LanguageCode language_code,
+                                  PrefService* profile_prefs) {
+  return language_code ==
+         speech::GetLanguageCode(GetLiveCaptionLanguageCode(profile_prefs));
+}
+
 #endif  // !defined(ANDROID)
 
 // String indicating the size of the captions text as a percentage.
diff --git a/components/live_caption/pref_names.h b/components/live_caption/pref_names.h
index 7c137cd..d7b4270f 100644
--- a/components/live_caption/pref_names.h
+++ b/components/live_caption/pref_names.h
@@ -7,6 +7,12 @@
 
 #include <string>
 
+#include "build/build_config.h"
+
+#if !BUILDFLAG(IS_ANDROID)
+#include "components/soda/constants.h"
+#endif
+
 class PrefService;
 
 namespace prefs {
@@ -18,6 +24,9 @@
 extern const char kLiveCaptionLanguageCode[];
 
 const std::string GetLiveCaptionLanguageCode(PrefService* profile_prefs);
+bool IsLanguageCodeForLiveCaption(speech::LanguageCode language_code,
+                                  PrefService* profile_prefs);
+
 #endif  // !defined(ANDROID)
 
 // These kAccessibilityCaptions* caption style prefs are used on Android
diff --git a/components/soda/soda_installer.cc b/components/soda/soda_installer.cc
index 113582e3..651bc7d0 100644
--- a/components/soda/soda_installer.cc
+++ b/components/soda/soda_installer.cc
@@ -143,12 +143,8 @@
   return (soda_binary_installed_ && IsLanguageInstalled(language_code));
 }
 
-bool SodaInstaller::IsAnyLanguagePackInstalled() const {
-  return !installed_languages_.empty();
-}
-
 bool SodaInstaller::IsLanguageInstalled(LanguageCode language_code) const {
-  return installed_languages_.find(language_code) != installed_languages_.end();
+  return base::Contains(installed_languages_, language_code);
 }
 
 void SodaInstaller::AddObserver(Observer* observer) {
@@ -159,12 +155,27 @@
   observers_.RemoveObserver(observer);
 }
 
-void SodaInstaller::NotifySodaInstalledForTesting() {
-  soda_binary_installed_ = true;
-  is_soda_downloading_ = false;
-  installed_languages_.insert(LanguageCode::kEnUs);
-  language_pack_progress_.clear();
-  NotifyOnSodaInstalled();
+void SodaInstaller::NotifySodaInstalledForTesting(LanguageCode language_code) {
+  // TODO: Call the actual functions in SodaInstallerImpl and
+  // SodaInstallerImpleChromeOS that do this logic
+  // (e.g. SodaInstallerImpl::OnSodaBinaryInstalled) rather than faking it.
+
+  // If language code is none, this signifies that the SODA binary installed.
+  if (language_code == LanguageCode::kNone) {
+    soda_binary_installed_ = true;
+    is_soda_downloading_ = false;
+    for (LanguageCode installed_language : installed_languages_) {
+      NotifyOnSodaInstalled(installed_language);
+    }
+    return;
+  }
+
+  // Otherwise, this means a language pack installed.
+  installed_languages_.insert(language_code);
+  if (base::Contains(language_pack_progress_, language_code))
+    language_pack_progress_.erase(language_code);
+  if (soda_binary_installed_)
+    NotifyOnSodaInstalled(language_code);
 }
 
 void SodaInstaller::NotifySodaErrorForTesting() {
@@ -190,15 +201,6 @@
   NotifyOnSodaProgress(progress);
 }
 
-void SodaInstaller::NotifyOnSodaLanguagePackInstalledForTesting(
-    LanguageCode language_code) {
-  installed_languages_.insert(language_code);
-  auto it = language_pack_progress_.find(language_code);
-  if (it != language_pack_progress_.end())
-    language_pack_progress_.erase(language_code);
-  NotifyOnSodaLanguagePackInstalled(language_code);
-}
-
 void SodaInstaller::NotifyOnSodaLanguagePackProgressForTesting(
     int progress,
     LanguageCode language_code) {
@@ -218,6 +220,10 @@
   NotifyOnSodaLanguagePackError(language_code);
 }
 
+bool SodaInstaller::IsAnyLanguagePackInstalledForTesting() const {
+  return !installed_languages_.empty();
+}
+
 void SodaInstaller::RegisterRegisteredLanguagePackPref(
     PrefRegistrySimple* registry) {
   // TODO: Default to one of the user's languages.
@@ -227,15 +233,9 @@
                              base::Value(std::move(default_languages)));
 }
 
-void SodaInstaller::NotifyOnSodaInstalled() {
+void SodaInstaller::NotifyOnSodaInstalled(LanguageCode language_code) {
   for (Observer& observer : observers_)
-    observer.OnSodaInstalled();
-}
-
-void SodaInstaller::NotifyOnSodaLanguagePackInstalled(
-    LanguageCode language_code) {
-  for (Observer& observer : observers_)
-    observer.OnSodaLanguagePackInstalled(language_code);
+    observer.OnSodaInstalled(language_code);
 }
 
 void SodaInstaller::NotifyOnSodaError() {
@@ -274,8 +274,8 @@
 }
 
 bool SodaInstaller::IsSodaDownloading(LanguageCode language_code) const {
-  return is_soda_downloading_ || language_pack_progress_.find(language_code) !=
-                                     language_pack_progress_.end();
+  return is_soda_downloading_ ||
+         base::Contains(language_pack_progress_, language_code);
 }
 
 bool SodaInstaller::IsAnyFeatureUsingSodaEnabled(PrefService* prefs) {
diff --git a/components/soda/soda_installer.h b/components/soda/soda_installer.h
index 89b118cf..425c78e 100644
--- a/components/soda/soda_installer.h
+++ b/components/soda/soda_installer.h
@@ -35,9 +35,9 @@
     // be used to display download progress next to the feature name in
     // settings.
 
-    // Called when the SODA binary component and at least one language pack is
-    // installed.
-    virtual void OnSodaInstalled() = 0;
+    // Called when the SODA binary component and the language pack for this
+    // language code are installed.
+    virtual void OnSodaInstalled(LanguageCode language_code) = 0;
 
     // Called if there is an error in the SODA binary or language pack
     // installation.
@@ -54,9 +54,6 @@
     // might be used to display download progress of a particular language next
     // to the language list item.
 
-    // Called when a SODA language pack component is installed.
-    virtual void OnSodaLanguagePackInstalled(LanguageCode language_code) {}
-
     // Called if there is an error in a SODA language pack installation.
     virtual void OnSodaLanguagePackError(LanguageCode language_code) {}
 
@@ -131,14 +128,17 @@
   void NeverDownloadSodaForTesting() {
     never_download_soda_for_testing_ = true;
   }
-  void NotifySodaInstalledForTesting();
+
+  // The soda binary is encoded as LanguageCode::kNone.
+  void NotifySodaInstalledForTesting(
+      LanguageCode language_code = LanguageCode::kNone);
   void NotifySodaErrorForTesting();
   void UninstallSodaForTesting();
   void NotifySodaDownloadProgressForTesting(int percentage);
-  void NotifyOnSodaLanguagePackInstalledForTesting(LanguageCode language_code);
   void NotifyOnSodaLanguagePackProgressForTesting(int progress,
                                                   LanguageCode language_code);
   void NotifyOnSodaLanguagePackErrorForTesting(LanguageCode language_code);
+  bool IsAnyLanguagePackInstalledForTesting() const;
 
  protected:
   // Registers the preference tracking the installed SODA language packs.
@@ -152,13 +152,9 @@
   // space may not be freed immediately.
   virtual void UninstallSoda(PrefService* global_prefs) = 0;
 
-  // Notifies the observers that the installation of the SODA binary and at
-  // least one language pack has completed.
-  void NotifyOnSodaInstalled();
-
-  // Notifies the observers that a SODA language pack installation has
-  // completed.
-  void NotifyOnSodaLanguagePackInstalled(LanguageCode language_code);
+  // Notifies the observers that the installation of the SODA binary and the
+  // language pack for this language code has completed.
+  void NotifyOnSodaInstalled(LanguageCode language_code);
 
   // Notifies the observers that there is an error in the SODA binary
   // installation.
@@ -190,8 +186,6 @@
   // installed. The language should be localized in BCP-47, e.g. "en-US".
   bool IsLanguageInstalled(LanguageCode language_code) const;
 
-  bool IsAnyLanguagePackInstalled() const;
-
   base::ObserverList<Observer> observers_;
   bool soda_binary_installed_ = false;
   bool soda_installer_initialized_ = false;
diff --git a/components/soda/soda_installer_impl_chromeos.cc b/components/soda/soda_installer_impl_chromeos.cc
index 7582987c..7180378 100644
--- a/components/soda/soda_installer_impl_chromeos.cc
+++ b/components/soda/soda_installer_impl_chromeos.cc
@@ -126,9 +126,10 @@
   if (install_result.error == dlcservice::kErrorNone) {
     soda_binary_installed_ = true;
     SetSodaBinaryPath(base::FilePath(install_result.root_path));
-    if (IsLanguageInstalled(LanguageCode::kEnUs)) {
-      NotifyOnSodaInstalled();
-    }
+    // TODO(crbug.com/1161569): SODA is only available for English right now.
+    // Update this to notify on all installed languages.
+    if (IsLanguageInstalled(LanguageCode::kEnUs))
+      NotifyOnSodaInstalled(LanguageCode::kEnUs);
 
     base::UmaHistogramTimes(kSodaBinaryInstallationSuccessTimeTaken,
                             base::Time::Now() - start_time);
@@ -153,7 +154,7 @@
     installed_languages_.insert(language_code);
     SetLanguagePath(base::FilePath(install_result.root_path));
     if (soda_binary_installed_) {
-      NotifyOnSodaInstalled();
+      NotifyOnSodaInstalled(language_code);
     }
     base::UmaHistogramTimes(
         GetInstallationSuccessTimeMetricForLanguagePack(language_code),
diff --git a/components/soda/soda_installer_impl_chromeos_unittest.cc b/components/soda/soda_installer_impl_chromeos_unittest.cc
index 97cfd78..58615e15 100644
--- a/components/soda/soda_installer_impl_chromeos_unittest.cc
+++ b/components/soda/soda_installer_impl_chromeos_unittest.cc
@@ -74,7 +74,7 @@
   }
 
   bool IsAnyLanguagePackInstalled() {
-    return soda_installer_impl_->IsAnyLanguagePackInstalled();
+    return soda_installer_impl_->IsAnyLanguagePackInstalledForTesting();
   }
 
   bool IsSodaDownloading() {
@@ -197,7 +197,13 @@
   ASSERT_FALSE(IsSodaDownloading());
   ASSERT_FALSE(IsLanguageInstalled(kEnglishLocale));
   ASSERT_FALSE(IsSodaDownloading());
+
+  // Install just the binary.
   GetInstance()->NotifySodaInstalledForTesting();
+  ASSERT_FALSE(IsSodaDownloading());
+
+  // Now install the language pack.
+  GetInstance()->NotifySodaInstalledForTesting(kEnglishLocale);
   ASSERT_TRUE(IsSodaInstalled());
   ASSERT_FALSE(IsSodaDownloading());
   ASSERT_TRUE(IsLanguageInstalled(kEnglishLocale));
@@ -235,7 +241,7 @@
   GetInstance()->NotifyOnSodaLanguagePackProgressForTesting(50, fr_fr);
   ASSERT_TRUE(GetInstance()->IsSodaDownloading(fr_fr));
   ASSERT_FALSE(IsLanguageInstalled(fr_fr));
-  GetInstance()->NotifyOnSodaLanguagePackInstalledForTesting(fr_fr);
+  GetInstance()->NotifySodaInstalledForTesting(fr_fr);
   ASSERT_TRUE(IsLanguageInstalled(fr_fr));
 }