Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(106)

Unified Diff: chrome/browser/search/hotword_service.cc

Issue 330193005: [Hotword] Uninstall and reinstall the extension upon language change. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: responding to comments Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/search/hotword_service.cc
diff --git a/chrome/browser/search/hotword_service.cc b/chrome/browser/search/hotword_service.cc
index 7e67c647ad8d040c6e2421367063ef9a757136e7..5fc305061aba0056b3571b1c158935bfef90e388 100644
--- a/chrome/browser/search/hotword_service.cc
+++ b/chrome/browser/search/hotword_service.cc
@@ -12,6 +12,9 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/pending_extension_manager.h"
+#include "chrome/browser/extensions/updater/extension_updater.h"
+#include "chrome/browser/extensions/webstore_startup_installer.h"
#include "chrome/browser/plugins/plugin_prefs.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search/hotword_service_factory.h"
@@ -24,6 +27,7 @@
#include "content/public/common/webplugininfo.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/extension.h"
+#include "extensions/common/one_shot_event.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
@@ -145,6 +149,17 @@ ExtensionService* GetExtensionService(Profile* profile) {
return NULL;
}
+std::string GetCurrentLocale(Profile* profile) {
+ std::string locale =
+#if defined(OS_CHROMEOS)
+ // On ChromeOS locale is per-profile.
+ profile->GetPrefs()->GetString(prefs::kApplicationLocale);
+#else
+ g_browser_process->GetApplicationLocale();
+#endif
+ return locale;
+}
+
} // namespace
namespace hotword_internal {
@@ -157,14 +172,8 @@ const char kHotwordUnusablePrefName[] = "hotword.search_enabled";
// static
bool HotwordService::DoesHotwordSupportLanguage(Profile* profile) {
- std::string locale =
-#if defined(OS_CHROMEOS)
- // On ChromeOS locale is per-profile.
- profile->GetPrefs()->GetString(prefs::kApplicationLocale);
-#else
- g_browser_process->GetApplicationLocale();
-#endif
- std::string normalized_locale = l10n_util::NormalizeLocale(locale);
+ std::string normalized_locale =
+ l10n_util::NormalizeLocale(GetCurrentLocale(profile));
StringToLowerASCII(&normalized_locale);
for (size_t i = 0; i < arraysize(kSupportedLocales); i++) {
@@ -176,8 +185,12 @@ bool HotwordService::DoesHotwordSupportLanguage(Profile* profile) {
HotwordService::HotwordService(Profile* profile)
: profile_(profile),
+ extension_registry_observer_(this),
client_(NULL),
- error_message_(0) {
+ error_message_(0),
+ reinstall_pending_(false),
+ weak_factory_(this) {
+ extension_registry_observer_.Add(extensions::ExtensionRegistry::Get(profile));
// This will be called during profile initialization which is a good time
// to check the user's hotword state.
HotwordEnabled enabled_state = UNSET;
@@ -203,12 +216,15 @@ HotwordService::HotwordService(Profile* profile)
base::Unretained(this)));
registrar_.Add(this,
- chrome::NOTIFICATION_EXTENSION_INSTALLED_DEPRECATED,
- content::Source<Profile>(profile_));
- registrar_.Add(this,
chrome::NOTIFICATION_BROWSER_WINDOW_READY,
content::NotificationService::AllSources());
+ extensions::ExtensionSystem::Get(profile_)->ready().Post(
+ FROM_HERE,
+ base::Bind(base::IgnoreResult(
+ &HotwordService::MaybeReinstallHotwordExtension),
+ weak_factory_.GetWeakPtr()));
+
// Clear the old user pref because it became unusable.
// TODO(rlp): Remove this code per crbug.com/358789.
if (profile_->GetPrefs()->HasPrefPath(
@@ -223,25 +239,7 @@ HotwordService::~HotwordService() {
void HotwordService::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
- if (type == chrome::NOTIFICATION_EXTENSION_INSTALLED_DEPRECATED) {
- const extensions::Extension* extension =
- content::Details<const extensions::InstalledExtensionInfo>(details)
- ->extension;
- // Disabling the extension automatically on install should only occur
- // if the user is in the field trial for auto-install which is gated
- // by the IsHotwordAllowed check.
- if (IsHotwordAllowed() &&
- extension->id() == extension_misc::kHotwordExtensionId &&
- !profile_->GetPrefs()->GetBoolean(prefs::kHotwordSearchEnabled)) {
- DisableHotwordExtension(GetExtensionService(profile_));
- // Once the extension is disabled, it will not be enabled until the
- // user opts in at which point the pref registrar will take over
- // enabling and disabling.
- registrar_.Remove(this,
- chrome::NOTIFICATION_EXTENSION_INSTALLED_DEPRECATED,
- content::Source<Profile>(profile_));
- }
- } else if (type == chrome::NOTIFICATION_BROWSER_WINDOW_READY) {
+ if (type == chrome::NOTIFICATION_BROWSER_WINDOW_READY) {
// The microphone monitor must be initialized as the page is loading
// so that the state of the microphone is available when the page
// loads. The Ok Google Hotword setting will display an error if there
@@ -257,6 +255,123 @@ void HotwordService::Observe(int type,
}
}
+void HotwordService::OnExtensionUninstalled(
+ content::BrowserContext* browser_context,
+ const extensions::Extension* extension) {
+ CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+ if (extension->id() != extension_misc::kHotwordExtensionId ||
+ profile_ != Profile::FromBrowserContext(browser_context) ||
+ !GetExtensionService(profile_))
+ return;
+
+ // If the extension wasn't uninstalled due to language change, don't try to
+ // reinstall it.
+ if (!reinstall_pending_)
+ return;
+
+ InstallHotwordExtensionFromWebstore();
+ SetPreviousLanguagePref();
+}
+
+void HotwordService::InstallHotwordExtensionFromWebstore() {
+ installer_ = new extensions::WebstoreStartupInstaller(
+ extension_misc::kHotwordExtensionId,
+ profile_,
+ false,
+ extensions::WebstoreStandaloneInstaller::Callback());
+ installer_->BeginInstall();
+}
+
+void HotwordService::OnExtensionInstalled(
+ content::BrowserContext* browser_context,
+ const extensions::Extension* extension) {
+
+ if (extension->id() != extension_misc::kHotwordExtensionId ||
+ profile_ != Profile::FromBrowserContext(browser_context))
+ return;
+
+ // If the previous locale pref has never been set, set it now since
+ // the extension has been installed.
+ if (!profile_->GetPrefs()->HasPrefPath(prefs::kHotwordPreviousLanguage))
+ SetPreviousLanguagePref();
+
+ // If MaybeReinstallHotwordExtension already triggered an uninstall, we
+ // don't want to loop and trigger another uninstall-install cycle.
+ // However, if we arrived here via an uninstall-triggered-install (and in
+ // that case |reinstall_pending_| will be true) then we know install
+ // has completed and we can reset |reinstall_pending_|.
+ if (!reinstall_pending_)
+ MaybeReinstallHotwordExtension();
+ else
+ reinstall_pending_ = false;
+
+ // Now that the extension is installed, if the user has not selected
+ // the preference on, make sure it is turned off.
+ //
+ // Disabling the extension automatically on install should only occur
+ // if the user is in the field trial for auto-install which is gated
+ // by the IsHotwordAllowed check. The check for IsHotwordAllowed() here
+ // can be removed once it's known that few people have manually
+ // installed extension.
+ if (IsHotwordAllowed() &&
+ !profile_->GetPrefs()->GetBoolean(prefs::kHotwordSearchEnabled)) {
+ DisableHotwordExtension(GetExtensionService(profile_));
+ }
+}
+
+bool HotwordService::MaybeReinstallHotwordExtension() {
+ CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+ ExtensionService* extension_service = GetExtensionService(profile_);
+ if (!extension_service)
+ return false;
+
+ const extensions::Extension* extension = extension_service->GetExtensionById(
+ extension_misc::kHotwordExtensionId, true);
+ if (!extension)
+ return false;
+
+ // If the extension is currently pending, return and we'll check again
+ // after the install is finished.
+ extensions::PendingExtensionManager* pending_manager =
+ extension_service->pending_extension_manager();
+ if (pending_manager->IsIdPending(extension->id()))
+ return false;
+
+ // If there is already a pending request from HotwordService, don't try
+ // to uninstall either.
+ if (reinstall_pending_)
+ return false;
+
+ // Check if the current locale matches the previous. If they don't match,
+ // uninstall the extension.
+ if (!ShouldReinstallHotwordExtension())
+ return false;
+
+ // Ensure the call to OnExtensionUninstalled was triggered by a language
+ // change so it's okay to reinstall.
+ reinstall_pending_ = true;
+
+ // This works because the call path MaybeReinstallHotwordExtension->
+ // UninstallHotwordExtension->OnExtensionUninstalled is all on the UI
+ // thread.
+ return reinstall_pending_ = UninstallHotwordExtension(extension_service);
Jered 2014/06/18 21:06:04 nit: Can we write this in a less clever way? e.g.
rpetterson 2014/06/18 23:05:57 So this doesn't actually work. Which is pretty int
Jered 2014/06/18 23:12:17 I was concerned that if UninstallHotwordExtension(
rpetterson 2014/06/18 23:45:35 A valid concern. This looks like a good solution t
+}
+
+bool HotwordService::UninstallHotwordExtension(
+ ExtensionService* extension_service) {
+ base::string16 error;
+ if (!extension_service->UninstallExtension(
+ extension_misc::kHotwordExtensionId, true, &error)) {
+ LOG(WARNING) << "Cannot uninstall extension with id "
+ << extension_misc::kHotwordExtensionId
+ << ": " << error;
+ return false;
+ }
+ return true;
+}
+
bool HotwordService::IsServiceAvailable() {
error_message_ = 0;
@@ -371,3 +486,23 @@ void HotwordService::StopHotwordSession(HotwordClient* client) {
event_service->OnHotwordSessionStopped();
#endif
}
+
+void HotwordService::SetPreviousLanguagePref() {
+ profile_->GetPrefs()->SetString(prefs::kHotwordPreviousLanguage,
+ GetCurrentLocale(profile_));
+}
+
+bool HotwordService::ShouldReinstallHotwordExtension() {
+ // If there is no previous locale pref, then this is the first install
+ // so no need to uninstall first.
+ if (!profile_->GetPrefs()->HasPrefPath(prefs::kHotwordPreviousLanguage))
+ return false;
+
+ std::string previous_locale =
+ profile_->GetPrefs()->GetString(prefs::kHotwordPreviousLanguage);
+ std::string locale = GetCurrentLocale(profile_);
+
+ // If it's a new locale, then the old extension should be uninstalled.
+ return locale != previous_locale &&
+ HotwordService::DoesHotwordSupportLanguage(profile_);
+}

Powered by Google App Engine
This is Rietveld 408576698