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

Unified Diff: chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.cc

Issue 1283603002: Implement langageSettingsPrivate API. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@LanguageSettingsAPIIDLChanges
Patch Set: Fix const error in l10n_util_collator Created 5 years, 4 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/extensions/api/language_settings_private/language_settings_private_delegate.cc
diff --git a/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.cc b/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.cc
index 2f0d4c3c448f0c6bc8fcbd1ba6e36fb95d1bd541..13b8940ad716bfff75a46e88e109ed125b7b4d75 100644
--- a/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.cc
+++ b/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.cc
@@ -4,7 +4,24 @@
#include "chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.h"
+#include <string>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/memory/linked_ptr.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "base/prefs/pref_service.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/spellchecker/spellcheck_factory.h"
+#include "chrome/browser/spellchecker/spellcheck_service.h"
+#include "chrome/common/pref_names.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/notification_source.h"
namespace extensions {
@@ -12,8 +29,10 @@ namespace language_settings_private = api::language_settings_private;
LanguageSettingsPrivateDelegate::LanguageSettingsPrivateDelegate(
content::BrowserContext* context)
- : context_(context),
- listening_spellcheck_(false) {
+ : custom_dictionary_(nullptr),
+ context_(context),
+ listening_spellcheck_(false),
+ profile_added_(false) {
// Register with the event router so we know when renderers are listening to
// our events. We first check and see if there *is* an event router, because
// some unit tests try to create all context services, but don't initialize
@@ -27,11 +46,22 @@ LanguageSettingsPrivateDelegate::LanguageSettingsPrivateDelegate(
event_router->RegisterObserver(this,
language_settings_private::OnCustomDictionaryChanged::kEventName);
+ // SpellcheckService cannot be created until Profile::DoFinalInit() has been
+ // called. http://crbug.com/171406
+ notification_registrar_.Add(this,
+ chrome::NOTIFICATION_PROFILE_ADDED,
+ content::Source<Profile>(Profile::FromBrowserContext(context_)));
+
+ pref_change_registrar_.Init(Profile::FromBrowserContext(context_)->
+ GetPrefs());
+
StartOrStopListeningForSpellcheckChanges();
}
LanguageSettingsPrivateDelegate::~LanguageSettingsPrivateDelegate() {
DCHECK(!listening_spellcheck_);
+ pref_change_registrar_.RemoveAll();
+ notification_registrar_.RemoveAll();
}
LanguageSettingsPrivateDelegate* LanguageSettingsPrivateDelegate::Create(
@@ -39,6 +69,27 @@ LanguageSettingsPrivateDelegate* LanguageSettingsPrivateDelegate::Create(
return new LanguageSettingsPrivateDelegate(context);
}
+ScopedVector<language_settings_private::SpellcheckDictionaryStatus>
+LanguageSettingsPrivateDelegate::GetHunspellDictionaryStatuses() {
+ ScopedVector<language_settings_private::SpellcheckDictionaryStatus> statuses;
+ for (const auto& dictionary : GetHunspellDictionaries()) {
+ if (!dictionary)
+ continue;
+ scoped_ptr<language_settings_private::SpellcheckDictionaryStatus> status(
+ new language_settings_private::SpellcheckDictionaryStatus());
+ status->language_code = dictionary->GetLanguage();
+ status->is_ready = dictionary->IsReady();
+ if (!status->is_ready) {
+ if (dictionary->IsDownloadInProgress())
+ status->is_downloading.reset(new bool(true));
+ if (dictionary->IsDownloadFailure())
+ status->download_failed.reset(new bool(true));
+ }
+ statuses.push_back(status.Pass());
+ }
+ return statuses.Pass();
+}
+
void LanguageSettingsPrivateDelegate::Shutdown() {
// Unregister with the event router. We first check and see if there *is* an
// event router, because some unit tests try to shutdown all context services,
@@ -48,10 +99,9 @@ void LanguageSettingsPrivateDelegate::Shutdown() {
event_router->UnregisterObserver(this);
if (listening_spellcheck_) {
- // TODO(michaelpg): unregister observers.
+ RemoveDictionaryObservers();
+ listening_spellcheck_ = false;
}
-
- listening_spellcheck_ = false;
}
void LanguageSettingsPrivateDelegate::OnListenerAdded(
@@ -71,6 +121,78 @@ void LanguageSettingsPrivateDelegate::OnListenerRemoved(
StartOrStopListeningForSpellcheckChanges();
}
+void LanguageSettingsPrivateDelegate::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ profile_added_ = true;
+ StartOrStopListeningForSpellcheckChanges();
+}
+
+void LanguageSettingsPrivateDelegate::OnHunspellDictionaryInitialized() {
+ BroadcastDictionariesChangedEvent();
+}
+
+void LanguageSettingsPrivateDelegate::OnHunspellDictionaryDownloadBegin() {
+ BroadcastDictionariesChangedEvent();
+}
+
+void LanguageSettingsPrivateDelegate::OnHunspellDictionaryDownloadSuccess() {
+ BroadcastDictionariesChangedEvent();
+}
+
+void LanguageSettingsPrivateDelegate::OnHunspellDictionaryDownloadFailure() {
+ BroadcastDictionariesChangedEvent();
+}
+
+void LanguageSettingsPrivateDelegate::OnCustomDictionaryLoaded() {
+}
+
+void LanguageSettingsPrivateDelegate::OnCustomDictionaryChanged(
+ const SpellcheckCustomDictionary::Change& change) {
+ std::vector<std::string> to_add(change.to_add().begin(),
+ change.to_add().end());
+ std::vector<std::string> to_remove(change.to_remove().begin(),
+ change.to_remove().end());
+ scoped_ptr<base::ListValue> args(
+ language_settings_private::OnCustomDictionaryChanged::Create(
+ to_add, to_remove));
+ scoped_ptr<Event> extension_event(new Event(
+ events::LANGUAGE_SETTINGS_PRIVATE_ON_CUSTOM_DICTIONARY_CHANGED,
+ language_settings_private::OnCustomDictionaryChanged::kEventName,
+ args.Pass()));
+ EventRouter::Get(context_)->BroadcastEvent(extension_event.Pass());
+}
+
+void LanguageSettingsPrivateDelegate::RefreshDictionaries(
+ bool was_listening, bool should_listen) {
+ if (!profile_added_)
+ return;
+ if (was_listening)
+ RemoveDictionaryObservers();
+ hunspell_dictionaries_.clear();
+ SpellcheckService* service = SpellcheckServiceFactory::GetForContext(
+ context_);
+ if (!custom_dictionary_)
+ custom_dictionary_ = service->GetCustomDictionary();
+
+ const ScopedVector<SpellcheckHunspellDictionary>& dictionaries(
+ service->GetHunspellDictionaries());
+ for (const auto& dictionary: dictionaries) {
+ hunspell_dictionaries_.push_back(dictionary->AsWeakPtr());
+ if (should_listen)
+ dictionary->AddObserver(this);
+ }
+}
+
+const LanguageSettingsPrivateDelegate::WeakDictionaries&
+LanguageSettingsPrivateDelegate::GetHunspellDictionaries() {
+ // If there are no hunspell dictionaries, or the first is invalid, refresh.
+ if (!hunspell_dictionaries_.size() || !hunspell_dictionaries_.front())
+ RefreshDictionaries(listening_spellcheck_, listening_spellcheck_);
+ return hunspell_dictionaries_;
+}
+
void LanguageSettingsPrivateDelegate::
StartOrStopListeningForSpellcheckChanges() {
EventRouter* event_router = EventRouter::Get(context_);
@@ -81,12 +203,57 @@ void LanguageSettingsPrivateDelegate::
OnCustomDictionaryChanged::kEventName);
if (should_listen && !listening_spellcheck_) {
- // TODO: register observers.
+ // Update and observe the hunspell dictionaries.
+ RefreshDictionaries(listening_spellcheck_, should_listen);
+ // Observe the dictionaries preference.
+ pref_change_registrar_.Add(prefs::kSpellCheckDictionaries, base::Bind(
+ &LanguageSettingsPrivateDelegate::OnSpellcheckDictionariesChanged,
+ base::Unretained(this)));
+ // Observe the dictionary of custom words.
+ if (custom_dictionary_)
+ custom_dictionary_->AddObserver(this);
} else if (!should_listen && listening_spellcheck_) {
- // TODO(michaelpg): unregister observers.
+ // Stop observing any dictionaries that still exist.
+ RemoveDictionaryObservers();
+ hunspell_dictionaries_.clear();
+ pref_change_registrar_.Remove(prefs::kSpellCheckDictionaries);
+ if (custom_dictionary_)
+ custom_dictionary_->RemoveObserver(this);
}
listening_spellcheck_ = should_listen;
}
+void LanguageSettingsPrivateDelegate::OnSpellcheckDictionariesChanged() {
+ RefreshDictionaries(listening_spellcheck_, listening_spellcheck_);
+ BroadcastDictionariesChangedEvent();
+}
+
+void LanguageSettingsPrivateDelegate::BroadcastDictionariesChangedEvent() {
+ std::vector<linked_ptr<language_settings_private::SpellcheckDictionaryStatus>>
+ broadcast_statuses;
+ ScopedVector<language_settings_private::SpellcheckDictionaryStatus> statuses =
+ GetHunspellDictionaryStatuses();
+
+ for (language_settings_private::SpellcheckDictionaryStatus* status : statuses)
+ broadcast_statuses.push_back(make_linked_ptr(status));
+ statuses.weak_clear();
+
+ scoped_ptr<base::ListValue> args(
+ language_settings_private::OnSpellcheckDictionariesChanged::Create(
+ broadcast_statuses));
+ scoped_ptr<extensions::Event> extension_event(new extensions::Event(
+ events::LANGUAGE_SETTINGS_PRIVATE_ON_SPELLCHECK_DICTIONARIES_CHANGED,
+ language_settings_private::OnSpellcheckDictionariesChanged::kEventName,
+ args.Pass()));
+ EventRouter::Get(context_)->BroadcastEvent(extension_event.Pass());
+}
+
+void LanguageSettingsPrivateDelegate::RemoveDictionaryObservers() {
+ for (const auto& dictionary : hunspell_dictionaries_) {
+ if (dictionary)
+ dictionary->RemoveObserver(this);
+ }
+}
+
} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698