summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-19 22:44:29 +0000
committerestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-19 22:44:29 +0000
commitc27324bdb7b9ee448a0c73d5c005c709282c8cbc (patch)
treed7ec31ab43e6493ef3f00eb81faeca0c79a793c3 /chrome
parent5ef3748a651d073bf12928e880a042bf450e1aa8 (diff)
downloadchromium_src-c27324bdb7b9ee448a0c73d5c005c709282c8cbc.zip
chromium_src-c27324bdb7b9ee448a0c73d5c005c709282c8cbc.tar.gz
chromium_src-c27324bdb7b9ee448a0c73d5c005c709282c8cbc.tar.bz2
Move Mac to using renderer spellchecker.
BUG=25677 Review URL: http://codereview.chromium.org/395007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@32561 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/gtk/browser_actions_toolbar_gtk.cc2
-rw-r--r--chrome/browser/gtk/options/languages_page_gtk.cc6
-rw-r--r--chrome/browser/profile.cc127
-rw-r--r--chrome/browser/profile.h44
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.cc60
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.h3
-rw-r--r--chrome/browser/renderer_host/render_process_host.h3
-rw-r--r--chrome/browser/renderer_host/render_view_host.cc4
-rw-r--r--chrome/browser/renderer_host/render_view_host.h1
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc80
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.h11
-rw-r--r--chrome/browser/spellcheck_host.cc165
-rw-r--r--chrome/browser/spellcheck_host.h15
-rw-r--r--chrome/browser/spellcheck_worditerator.cc274
-rw-r--r--chrome/browser/spellcheck_worditerator.h183
-rw-r--r--chrome/browser/spellchecker.cc814
-rw-r--r--chrome/browser/spellchecker.h247
-rw-r--r--chrome/browser/spellchecker_common.h19
-rw-r--r--chrome/browser/spellchecker_linux.cc7
-rw-r--r--chrome/browser/spellchecker_mac.mm7
-rw-r--r--chrome/browser/spellchecker_platform_engine.h1
-rw-r--r--chrome/browser/spellchecker_platform_engine_unittest.cc393
-rw-r--r--chrome/browser/spellchecker_win.cc2
-rw-r--r--chrome/browser/tab_contents/render_view_context_menu.cc16
-rw-r--r--chrome/browser/views/options/languages_page_view.cc7
-rwxr-xr-xchrome/chrome.gyp18
-rw-r--r--chrome/common/notification_type.h12
-rw-r--r--chrome/common/render_messages_internal.h19
-rw-r--r--chrome/common/spellcheck_common.cc174
-rw-r--r--chrome/common/spellcheck_common.h36
-rw-r--r--chrome/renderer/render_thread.cc16
-rw-r--r--chrome/renderer/render_thread.h11
-rw-r--r--chrome/renderer/render_view.cc32
-rw-r--r--chrome/renderer/spellchecker/spellcheck.cc39
-rw-r--r--chrome/renderer/spellchecker/spellcheck.h3
-rw-r--r--chrome/renderer/spellchecker/spellcheck_unittest.cc (renamed from chrome/browser/spellcheck_unittest.cc)622
-rw-r--r--chrome/test/testing_profile.h5
37 files changed, 845 insertions, 2633 deletions
diff --git a/chrome/browser/gtk/browser_actions_toolbar_gtk.cc b/chrome/browser/gtk/browser_actions_toolbar_gtk.cc
index b166f1c..4399923 100644
--- a/chrome/browser/gtk/browser_actions_toolbar_gtk.cc
+++ b/chrome/browser/gtk/browser_actions_toolbar_gtk.cc
@@ -196,6 +196,8 @@ class BrowserActionButton : public NotificationObserver,
GdkPixbuf* default_icon_;
NotificationRegistrar registrar_;
+
+ friend class BrowserActionsToolbarGtk;
};
BrowserActionsToolbarGtk::BrowserActionsToolbarGtk(Browser* browser)
diff --git a/chrome/browser/gtk/options/languages_page_gtk.cc b/chrome/browser/gtk/options/languages_page_gtk.cc
index 0cd30d0..3af1834 100644
--- a/chrome/browser/gtk/options/languages_page_gtk.cc
+++ b/chrome/browser/gtk/options/languages_page_gtk.cc
@@ -13,10 +13,10 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/language_combobox_model.h"
#include "chrome/browser/language_order_table_model.h"
-#include "chrome/browser/spellchecker.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/gtk_util.h"
#include "chrome/common/pref_names.h"
+#include "chrome/common/spellcheck_common.h"
#include "grit/generated_resources.h"
namespace {
@@ -246,7 +246,7 @@ void LanguagesPageGtk::Init() {
}
std::vector<std::string> spell_check_languages;
- SpellChecker::SpellCheckLanguages(&spell_check_languages);
+ SpellCheckCommon::SpellCheckLanguages(&spell_check_languages);
dictionary_language_model_.reset(new LanguageComboboxModel(profile(),
spell_check_languages));
dictionary_language_combobox_ = NewComboboxFromModel(
@@ -330,7 +330,7 @@ void LanguagesPageGtk::NotifyPrefChanged(const std::wstring* pref_name) {
const std::string& lang_region = WideToASCII(
dictionary_language_.GetValue());
dictionary_language_.SetValue(ASCIIToWide(
- SpellChecker::GetLanguageFromLanguageRegion(lang_region)));
+ SpellCheckCommon::GetLanguageFromLanguageRegion(lang_region)));
index = dictionary_language_model_->GetSelectedLanguageIndex(
prefs::kSpellCheckDictionary);
}
diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc
index eb998ba..fea876b 100644
--- a/chrome/browser/profile.cc
+++ b/chrome/browser/profile.cc
@@ -39,7 +39,6 @@
#include "chrome/browser/search_engines/template_url_model.h"
#include "chrome/browser/sessions/session_service.h"
#include "chrome/browser/sessions/tab_restore_service.h"
-#include "chrome/browser/spellchecker.h"
#include "chrome/browser/ssl/ssl_host_state.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/thumbnail_store.h"
@@ -472,19 +471,6 @@ class OffTheRecordProfileImpl : public Profile,
virtual void ResetTabRestoreService() {
}
- virtual void ReinitializeSpellChecker() {
- profile_->ReinitializeSpellChecker();
- }
-
- virtual SpellChecker* GetSpellChecker() {
- return profile_->GetSpellChecker();
- }
-
- virtual void DeleteSpellChecker() {
- profile_->DeleteSpellChecker();
- }
-
-#if defined(SPELLCHECKER_IN_RENDERER)
virtual SpellCheckHost* GetSpellCheckHost() {
return profile_->GetSpellCheckHost();
}
@@ -492,14 +478,13 @@ class OffTheRecordProfileImpl : public Profile,
virtual void ReinitializeSpellCheckHost(bool force) {
profile_->ReinitializeSpellCheckHost(force);
}
-#endif
virtual WebKitContext* GetWebKitContext() {
- if (!webkit_context_.get())
- webkit_context_ = new WebKitContext(GetPath(), true);
- DCHECK(webkit_context_.get());
- return webkit_context_.get();
-}
+ if (!webkit_context_.get())
+ webkit_context_ = new WebKitContext(GetPath(), true);
+ DCHECK(webkit_context_.get());
+ return webkit_context_.get();
+ }
virtual ThumbnailStore* GetThumbnailStore() {
return NULL;
@@ -593,7 +578,6 @@ ProfileImpl::ProfileImpl(const FilePath& path)
created_download_manager_(false),
created_theme_provider_(false),
start_time_(Time::Now()),
- spellchecker_(NULL),
#if defined(OS_LINUX)
spellcheck_host_(NULL),
spellcheck_host_ready_(false),
@@ -778,11 +762,8 @@ ProfileImpl::~ProfileImpl() {
if (history_service_.get())
history_service_->Cleanup();
-#if defined(SPELLCHECKER_IN_RENDERER)
if (spellcheck_host_.get())
spellcheck_host_->UnsetObserver();
-#endif
- DeleteSpellCheckerImpl(false);
if (default_request_context_ == request_context_)
default_request_context_ = NULL;
@@ -1258,57 +1239,6 @@ void ProfileImpl::ResetTabRestoreService() {
tab_restore_service_ = NULL;
}
-// To be run in the IO thread to notify all resource message filters that the
-// spellchecker has changed.
-class NotifySpellcheckerChangeTask : public Task {
- public:
- NotifySpellcheckerChangeTask(
- Profile* profile,
- const SpellcheckerReinitializedDetails& spellchecker)
- : profile_(profile),
- spellchecker_(spellchecker) {
- }
-
- private:
- void Run(void) {
- NotificationService::current()->Notify(
- NotificationType::SPELLCHECKER_REINITIALIZED,
- Source<Profile>(profile_),
- Details<SpellcheckerReinitializedDetails>(&spellchecker_));
- }
-
- Profile* profile_;
- SpellcheckerReinitializedDetails spellchecker_;
-};
-
-void ProfileImpl::ReinitializeSpellChecker() {
- PrefService* prefs = GetPrefs();
- if (prefs->GetBoolean(prefs::kEnableSpellCheck)) {
- DeleteSpellCheckerImpl(false);
-
- // Retrieve the (perhaps updated recently) dictionary name from preferences.
- FilePath dict_dir;
- PathService::Get(chrome::DIR_APP_DICTIONARIES, &dict_dir);
- // Note that, as the object pointed to by previously by spellchecker_
- // is being deleted in the io thread, the spellchecker_ can be made to point
- // to a new object (RE-initialized) in parallel in this UI thread.
- spellchecker_ = new SpellChecker(dict_dir,
- WideToASCII(prefs->GetString(prefs::kSpellCheckDictionary)),
- GetRequestContext(),
- FilePath());
- spellchecker_->AddRef(); // Manual refcounting.
-
- // Set auto spell correct status for spellchecker.
- spellchecker_->EnableAutoSpellCorrect(
- prefs->GetBoolean(prefs::kEnableAutoSpellCorrect));
-
- NotifySpellCheckerChanged();
- } else {
- DeleteSpellCheckerImpl(true);
- }
-}
-
-#if defined(SPELLCHECKER_IN_RENDERER)
SpellCheckHost* ProfileImpl::GetSpellCheckHost() {
return spellcheck_host_ready_ ? spellcheck_host_.get() : NULL;
}
@@ -1343,45 +1273,12 @@ void ProfileImpl::ReinitializeSpellCheckHost(bool force) {
void ProfileImpl::SpellCheckHostInitialized() {
spellcheck_host_ready_ = spellcheck_host_ &&
- spellcheck_host_->bdict_file() != base::kInvalidPlatformFileValue;
+ (spellcheck_host_->bdict_file() != base::kInvalidPlatformFileValue ||
+ spellcheck_host_->use_platform_spellchecker());
NotificationService::current()->Notify(
NotificationType::SPELLCHECK_HOST_REINITIALIZED,
Source<Profile>(this), NotificationService::NoDetails());
}
-#endif
-
-void ProfileImpl::NotifySpellCheckerChanged() {
- SpellcheckerReinitializedDetails scoped_spellchecker;
- scoped_spellchecker.spellchecker = spellchecker_;
- ChromeThread::PostTask(
- ChromeThread::IO, FROM_HERE,
- new NotifySpellcheckerChangeTask(this, scoped_spellchecker));
-}
-
-void ProfileImpl::DeleteSpellCheckerImpl(bool notify) {
- if (!spellchecker_)
- return;
-
- // The spellchecker must be deleted on the I/O thread.
- ChromeThread::ReleaseSoon(ChromeThread::IO, FROM_HERE, spellchecker_);
- spellchecker_ = NULL;
-
- if (notify)
- NotifySpellCheckerChanged();
-}
-
-SpellChecker* ProfileImpl::GetSpellChecker() {
- if (!spellchecker_) {
- // This is where spellchecker gets initialized. Note that this is being
- // initialized in the ui_thread. However, this is not a problem as long as
- // it is *used* in the io thread.
- // TODO(sidchat): One day, change everything so that spellchecker gets
- // initialized in the IO thread itself.
- ReinitializeSpellChecker();
- }
-
- return spellchecker_;
-}
WebKitContext* ProfileImpl::GetWebKitContext() {
if (!webkit_context_.get())
@@ -1418,14 +1315,12 @@ void ProfileImpl::Observe(NotificationType type,
PrefService* prefs = Source<PrefService>(source).ptr();
DCHECK(pref_name_in && prefs);
if (*pref_name_in == prefs::kSpellCheckDictionary ||
-#if !defined(SPELLCHECKER_IN_RENDERER)
- *pref_name_in == prefs::kEnableAutoSpellCorrect ||
-#endif
*pref_name_in == prefs::kEnableSpellCheck) {
- ReinitializeSpellChecker();
-#if defined(SPELLCHECKER_IN_RENDERER)
ReinitializeSpellCheckHost(true);
-#endif
+ } else if (*pref_name_in == prefs::kEnableAutoSpellCorrect) {
+ NotificationService::current()->Notify(
+ NotificationType::SPELLCHECK_AUTOSPELL_TOGGLED,
+ Source<Profile>(this), NotificationService::NoDetails());
}
} else if (NotificationType::THEME_INSTALLED == type) {
Extension* extension = Details<Extension>(details).ptr();
diff --git a/chrome/browser/profile.h b/chrome/browser/profile.h
index b8cec92..c931f31 100644
--- a/chrome/browser/profile.h
+++ b/chrome/browser/profile.h
@@ -14,9 +14,7 @@
#include "base/file_path.h"
#include "base/scoped_ptr.h"
#include "base/timer.h"
-#if defined(SPELLCHECKER_IN_RENDERER)
#include "chrome/browser/spellcheck_host.h"
-#endif
#include "chrome/browser/web_resource/web_resource_service.h"
#include "chrome/common/notification_registrar.h"
@@ -54,7 +52,6 @@ class PrefService;
class ProfileSyncService;
class SearchVersusNavigateClassifier;
class SessionService;
-class SpellChecker;
class SSLConfigServiceManager;
class SSLHostState;
class StrictTransportSecurityPersister;
@@ -342,21 +339,6 @@ class Profile {
virtual void ResetTabRestoreService() = 0;
- // This reinitializes the spellchecker according to the current dictionary
- // language, and enable spell check option, in the prefs. Then a
- // SPELLCHECKER_REINITIALIZED notification is sent on the IO thread.
- virtual void ReinitializeSpellChecker() = 0;
-
- // Returns the spell checker object for this profile. THIS OBJECT MUST ONLY
- // BE USED ON THE I/O THREAD! This pointer is retrieved from the profile and
- // sent to the I/O thread where it is actually used.
- virtual SpellChecker* GetSpellChecker() = 0;
-
- // Deletes the spellchecker. This is only really useful when we need to purge
- // memory.
- virtual void DeleteSpellChecker() = 0;
-
-#if defined(SPELLCHECKER_IN_RENDERER)
// May return NULL.
virtual SpellCheckHost* GetSpellCheckHost() = 0;
@@ -364,7 +346,6 @@ class Profile {
// the process of initializing), then do nothing. Otherwise clobber the
// current spellchecker and replace it with a new one.
virtual void ReinitializeSpellCheckHost(bool force) = 0;
-#endif
// Returns the WebKitContext assigned to this profile.
virtual WebKitContext* GetWebKitContext() = 0;
@@ -412,9 +393,7 @@ class OffTheRecordProfileImpl;
// The default profile implementation.
class ProfileImpl : public Profile,
-#if defined(SPELLCHECKER_IN_RENDERER)
public SpellCheckHost::Observer,
-#endif
public NotificationObserver {
public:
virtual ~ProfileImpl();
@@ -473,13 +452,8 @@ class ProfileImpl : public Profile,
virtual base::Time GetStartTime() const;
virtual TabRestoreService* GetTabRestoreService();
virtual void ResetTabRestoreService();
- virtual void ReinitializeSpellChecker();
- virtual SpellChecker* GetSpellChecker();
- virtual void DeleteSpellChecker() { DeleteSpellCheckerImpl(true); }
-#if defined(SPELLCHECKER_IN_RENDERER)
virtual SpellCheckHost* GetSpellCheckHost();
virtual void ReinitializeSpellCheckHost(bool force);
-#endif
virtual WebKitContext* GetWebKitContext();
virtual DesktopNotificationService* GetDesktopNotificationService();
virtual void MarkAsCleanShutdown();
@@ -494,10 +468,8 @@ class ProfileImpl : public Profile,
const NotificationSource& source,
const NotificationDetails& details);
-#if defined(SPELLCHECKER_IN_RENDERER)
// SpellCheckHost::Observer implementation.
virtual void SpellCheckHostInitialized();
-#endif
private:
friend class Profile;
@@ -519,9 +491,6 @@ class ProfileImpl : public Profile,
GetSessionService();
}
- void NotifySpellCheckerChanged();
- void DeleteSpellCheckerImpl(bool notify);
-
NotificationRegistrar registrar_;
FilePath path_;
@@ -587,17 +556,11 @@ class ProfileImpl : public Profile,
scoped_refptr<TabRestoreService> tab_restore_service_;
- // This can not be a scoped_refptr because we must release it on the I/O
- // thread.
- SpellChecker* spellchecker_;
-
-#if defined(SPELLCHECKER_IN_RENDERER)
scoped_refptr<SpellCheckHost> spellcheck_host_;
// Indicates whether |spellcheck_host_| has told us initialization is
// finished.
bool spellcheck_host_ready_;
-#endif
// Set to true when ShutdownSessionService is invoked. If true
// GetSessionService won't recreate the SessionService.
@@ -614,11 +577,4 @@ class ProfileImpl : public Profile,
DISALLOW_COPY_AND_ASSIGN(ProfileImpl);
};
-// This struct is used to pass the spellchecker object through the notification
-// SPELLCHECKER_REINITIALIZED. This is used as the details for the notification
-// service.
-struct SpellcheckerReinitializedDetails {
- scoped_refptr<SpellChecker> spellchecker;
-};
-
#endif // CHROME_BROWSER_PROFILE_H_
diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc
index 1f630af..e9bfedb 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.cc
+++ b/chrome/browser/renderer_host/browser_render_process_host.cc
@@ -40,16 +40,15 @@
#include "chrome/browser/renderer_host/render_widget_host.h"
#include "chrome/browser/renderer_host/resource_message_filter.h"
#include "chrome/browser/renderer_host/web_cache_manager.h"
-#if defined(SPELLCHECKER_IN_RENDERER)
#include "chrome/browser/spellcheck_host.h"
-#endif
-#include "chrome/browser/spellchecker.h"
#include "chrome/browser/visitedlink_master.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/child_process_info.h"
#include "chrome/common/child_process_host.h"
#include "chrome/common/logging_chrome.h"
#include "chrome/common/notification_service.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/process_watcher.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/result_codes.h"
#include "chrome/renderer/render_process.h"
@@ -199,15 +198,12 @@ BrowserRenderProcessHost::BrowserRenderProcessHost(Profile* profile)
registrar_.Add(this, NotificationType::USER_SCRIPTS_UPDATED,
NotificationService::AllSources());
-#if defined(SPELLCHECKER_IN_RENDERER)
registrar_.Add(this, NotificationType::SPELLCHECK_HOST_REINITIALIZED,
NotificationService::AllSources());
registrar_.Add(this, NotificationType::SPELLCHECK_WORD_ADDED,
NotificationService::AllSources());
-
- PrefService* prefs = profile->GetPrefs();
- prefs->AddPrefObserver(prefs::kEnableAutoSpellCorrect, this);
-#endif
+ registrar_.Add(this, NotificationType::SPELLCHECK_AUTOSPELL_TOGGLED,
+ NotificationService::AllSources());
visited_link_updater_.reset(new VisitedLinkUpdater());
@@ -221,11 +217,6 @@ BrowserRenderProcessHost::BrowserRenderProcessHost(Profile* profile)
}
BrowserRenderProcessHost::~BrowserRenderProcessHost() {
-#if defined(SPELLCHECKER_IN_RENDERER)
- PrefService* prefs = profile()->GetPrefs();
- prefs->RemovePrefObserver(prefs::kEnableAutoSpellCorrect, this);
-#endif
-
WebCacheManager::GetInstance()->Remove(id());
ChildProcessSecurityPolicy::GetInstance()->Remove(id());
@@ -277,7 +268,6 @@ bool BrowserRenderProcessHost::Init(bool is_extensions_process,
g_browser_process->print_job_manager(),
profile(),
widget_helper_,
- profile()->GetSpellChecker(),
request_context);
// Find the renderer before creating the channel so if this fails early we
@@ -394,15 +384,6 @@ void BrowserRenderProcessHost::WidgetHidden() {
}
}
-void BrowserRenderProcessHost::AddWord(const string16& word) {
- SpellChecker* spellchecker = profile()->GetSpellChecker();
- if (spellchecker) {
- ChromeThread::PostTask(
- ChromeThread::IO, FROM_HERE,
- NewRunnableMethod(spellchecker, &SpellChecker::AddWord, word));
- }
-}
-
void BrowserRenderProcessHost::SendVisitedLinkTable(
base::SharedMemory* table_memory) {
// Check if the process is still starting and we don't have a handle for it
@@ -762,10 +743,8 @@ void BrowserRenderProcessHost::OnMessageReceived(const IPC::Message& msg) {
OnExtensionRemoveListener)
IPC_MESSAGE_HANDLER(ViewHostMsg_ExtensionCloseChannel,
OnExtensionCloseChannel)
-#if defined(SPELLCHECKER_IN_RENDERER)
IPC_MESSAGE_HANDLER(ViewHostMsg_SpellChecker_RequestDictionary,
OnSpellCheckerRequestDictionary)
-#endif
IPC_MESSAGE_UNHANDLED_ERROR()
IPC_END_MESSAGE_MAP_EX()
@@ -900,7 +879,6 @@ void BrowserRenderProcessHost::Observe(NotificationType type,
}
break;
}
-#if defined(SPELLCHECKER_IN_RENDERER)
case NotificationType::SPELLCHECK_HOST_REINITIALIZED: {
InitSpellChecker();
break;
@@ -911,18 +889,12 @@ void BrowserRenderProcessHost::Observe(NotificationType type,
ptr()->last_added_word());
break;
}
- case NotificationType::PREF_CHANGED: {
- std::wstring* pref_name_in = Details<std::wstring>(details).ptr();
- PrefService* prefs = Source<PrefService>(source).ptr();
- DCHECK(pref_name_in && prefs);
- if (*pref_name_in == prefs::kEnableAutoSpellCorrect) {
- EnableAutoSpellCorrect(
- prefs->GetBoolean(prefs::kEnableAutoSpellCorrect));
- break;
- }
- // Fall through.
+ case NotificationType::SPELLCHECK_AUTOSPELL_TOGGLED: {
+ PrefService* prefs = profile()->GetPrefs();
+ EnableAutoSpellCorrect(
+ prefs->GetBoolean(prefs::kEnableAutoSpellCorrect));
+ break;
}
-#endif
default: {
NOTREACHED();
break;
@@ -937,14 +909,12 @@ void BrowserRenderProcessHost::OnProcessLaunched() {
InitVisitedLinks();
InitUserScripts();
InitExtensions();
-#if defined(SPELLCHECKER_IN_RENDERER)
// We don't want to initialize the spellchecker unless SpellCheckHost has been
// created. In InitSpellChecker(), we know if GetSpellCheckHost() is NULL
// then the spellchecker has been turned off, but here, we don't know if
// it's been turned off or just not loaded yet.
if (profile()->GetSpellCheckHost())
InitSpellChecker();
-#endif
if (max_page_id_ != -1)
Send(new ViewMsg_SetNextPageID(max_page_id_ + 1));
@@ -981,7 +951,6 @@ void BrowserRenderProcessHost::OnExtensionCloseChannel(int port_id) {
}
}
-#if defined(SPELLCHECKER_IN_RENDERER)
void BrowserRenderProcessHost::OnSpellCheckerRequestDictionary() {
// We may have gotten multiple requests from different renderers. We don't
// want to initialize multiple times in this case, so we set |force| to false.
@@ -997,12 +966,16 @@ void BrowserRenderProcessHost::InitSpellChecker() {
if (spellcheck_host) {
PrefService* prefs = profile()->GetPrefs();
IPC::PlatformFileForTransit file;
+
+ if (spellcheck_host->bdict_file() != base::kInvalidPlatformFileValue) {
#if defined(OS_POSIX)
- file = base::FileDescriptor(spellcheck_host->bdict_file(), false);
+ file = base::FileDescriptor(spellcheck_host->bdict_file(), false);
#elif defined(OS_WIN)
- ::DuplicateHandle(::GetCurrentProcess(), spellcheck_host->bdict_file(),
- GetHandle(), &file, 0, false, DUPLICATE_SAME_ACCESS);
+ ::DuplicateHandle(::GetCurrentProcess(), spellcheck_host->bdict_file(),
+ GetHandle(), &file, 0, false, DUPLICATE_SAME_ACCESS);
#endif
+ }
+
Send(new ViewMsg_SpellChecker_Init(
file,
spellcheck_host->custom_words(),
@@ -1020,4 +993,3 @@ void BrowserRenderProcessHost::InitSpellChecker() {
void BrowserRenderProcessHost::EnableAutoSpellCorrect(bool enable) {
Send(new ViewMsg_SpellChecker_EnableAutoSpellCorrect(enable));
}
-#endif
diff --git a/chrome/browser/renderer_host/browser_render_process_host.h b/chrome/browser/renderer_host/browser_render_process_host.h
index 4ab6c73..fae3145 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.h
+++ b/chrome/browser/renderer_host/browser_render_process_host.h
@@ -70,7 +70,6 @@ class BrowserRenderProcessHost : public RenderProcessHost,
virtual void WidgetRestored();
virtual void WidgetHidden();
virtual void ViewCreated();
- virtual void AddWord(const string16& word);
virtual void SendVisitedLinkTable(base::SharedMemory* table_memory);
virtual void AddVisitedLinks(const VisitedLinkCommon::Fingerprints& links);
virtual void ResetVisitedLinks();
@@ -142,7 +141,6 @@ class BrowserRenderProcessHost : public RenderProcessHost,
// Returns true if the priority is backgrounded; false otherwise.
void SetBackgrounded(bool boost);
-#if defined(SPELLCHECKER_IN_RENDERER)
// The renderer has requested that we initialize its spellchecker. This should
// generally only be called once per session, as after the first call, all
// future renderers will be passed the initialization information on startup
@@ -159,7 +157,6 @@ class BrowserRenderProcessHost : public RenderProcessHost,
// Tell the renderer that auto spell correction has been enabled/disabled.
void EnableAutoSpellCorrect(bool enable);
-#endif
NotificationRegistrar registrar_;
diff --git a/chrome/browser/renderer_host/render_process_host.h b/chrome/browser/renderer_host/render_process_host.h
index 0914a52..0edf46c 100644
--- a/chrome/browser/renderer_host/render_process_host.h
+++ b/chrome/browser/renderer_host/render_process_host.h
@@ -173,9 +173,6 @@ class RenderProcessHost : public IPC::Channel::Sender,
// Called when RenderView is created by a listener.
virtual void ViewCreated() = 0;
- // Add a word in the spellchecker.
- virtual void AddWord(const string16& word) = 0;
-
// Informs the renderer about a new visited link table.
virtual void SendVisitedLinkTable(base::SharedMemory* table_memory) = 0;
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc
index 6b3307c..b414aea 100644
--- a/chrome/browser/renderer_host/render_view_host.cc
+++ b/chrome/browser/renderer_host/render_view_host.cc
@@ -542,10 +542,6 @@ void RenderViewHost::ToggleSpellCheck() {
Send(new ViewMsg_ToggleSpellCheck(routing_id()));
}
-void RenderViewHost::AddToDictionary(const string16& word) {
- process()->AddWord(word);
-}
-
void RenderViewHost::Delete() {
Send(new ViewMsg_Delete(routing_id()));
}
diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h
index 4b03af0..4aae99b 100644
--- a/chrome/browser/renderer_host/render_view_host.h
+++ b/chrome/browser/renderer_host/render_view_host.h
@@ -277,7 +277,6 @@ class RenderViewHost : public RenderWidgetHost,
void CopyToFindPboard();
void Paste();
void ToggleSpellCheck();
- void AddToDictionary(const string16& word);
void Delete();
void SelectAll();
void ToggleSpellPanel(bool is_currently_visible);
diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc
index 93ee409..b03118d 100644
--- a/chrome/browser/renderer_host/resource_message_filter.cc
+++ b/chrome/browser/renderer_host/resource_message_filter.cc
@@ -31,7 +31,6 @@
#include "chrome/browser/renderer_host/database_dispatcher_host.h"
#include "chrome/browser/renderer_host/render_widget_helper.h"
#include "chrome/browser/renderer_host/socket_stream_dispatcher_host.h"
-#include "chrome/browser/spellchecker.h"
#include "chrome/browser/spellchecker_platform_engine.h"
#include "chrome/browser/task_manager.h"
#include "chrome/browser/worker_host/message_port_dispatcher.h"
@@ -150,14 +149,12 @@ ResourceMessageFilter::ResourceMessageFilter(
printing::PrintJobManager* print_job_manager,
Profile* profile,
RenderWidgetHelper* render_widget_helper,
- SpellChecker* spellchecker,
URLRequestContextGetter* request_context)
: Receiver(RENDER_PROCESS, child_id),
channel_(NULL),
resource_dispatcher_host_(resource_dispatcher_host),
plugin_service_(plugin_service),
print_job_manager_(print_job_manager),
- spellchecker_(spellchecker),
ALLOW_THIS_IN_INITIALIZER_LIST(resolve_proxy_msg_helper_(this, NULL)),
request_context_(request_context),
media_request_context_(profile->GetRequestContextForMedia()),
@@ -214,8 +211,6 @@ void ResourceMessageFilter::OnFilterAdded(IPC::Channel* channel) {
channel_ = channel;
// Add the observers to intercept.
- registrar_.Add(this, NotificationType::SPELLCHECKER_REINITIALIZED,
- Source<Profile>(static_cast<Profile*>(profile_)));
registrar_.Add(this, NotificationType::BLACKLIST_BLOCKED_RESOURCE,
NotificationService::AllSources());
}
@@ -317,13 +312,14 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& msg) {
OnCancelCreateDedicatedWorker)
IPC_MESSAGE_HANDLER(ViewHostMsg_ForwardToWorker,
OnForwardToWorker)
- IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_SpellCheck, OnSpellCheck)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_SpellChecker_PlatformCheckSpelling,
+ OnPlatformCheckSpelling)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_SpellChecker_PlatformFillSuggestionList,
+ OnPlatformFillSuggestionList)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetDocumentTag,
OnGetDocumentTag)
IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentWithTagClosed,
OnDocumentWithTagClosed)
- IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetAutoCorrectWord,
- OnGetAutoCorrectWord)
IPC_MESSAGE_HANDLER(ViewHostMsg_ShowSpellingPanel, OnShowSpellingPanel)
IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateSpellingPanelWithMisspelledWord,
OnUpdateSpellingPanelWithMisspelledWord)
@@ -420,21 +416,6 @@ void ResourceMessageFilter::OnReceiveContextMenuMsg(const IPC::Message& msg) {
if (!IPC::ParamTraits<ContextMenuParams>::Read(&msg, &iter, &params))
return;
- // Fill in the dictionary suggestions if required.
- if (!params.misspelled_word.empty() &&
- spellchecker_ != NULL && params.spellcheck_enabled) {
- int misspell_location, misspell_length;
- bool is_misspelled = !spellchecker_->SpellCheckWord(
- params.misspelled_word.c_str(),
- static_cast<int>(params.misspelled_word.length()), 0,
- &misspell_location, &misspell_length,
- &params.dictionary_suggestions);
-
- // If not misspelled, make the misspelled_word param empty.
- if (!is_misspelled)
- params.misspelled_word.clear();
- }
-
// Create a new ViewHostMsg_ContextMenu message.
const ViewHostMsg_ContextMenu context_menu_message(msg.routing_id(), params);
ChromeThread::PostTask(
@@ -1010,33 +991,16 @@ ResourceMessageFilter::GetRequestContextForURL(
context_getter->GetURLRequestContext());
}
-// Notes about SpellCheck.
-//
-// Spellchecking generally uses a fair amount of RAM. For this reason, we load
-// the spellcheck dictionaries into the browser process, and all renderers ask
-// the browsers to do SpellChecking.
-//
-// This filter should not try to initialize the spellchecker. It is up to the
-// profile to initialize it when required, and send it here. If |spellchecker_|
-// is made NULL, it corresponds to spellchecker turned off - i.e., all
-// spellings are correct.
-//
-// Note: This is called in the IO thread.
-void ResourceMessageFilter::OnSpellCheck(const string16& word, int tag,
- IPC::Message* reply_msg) {
- int misspell_location = 0;
- int misspell_length = 0;
-
- if (spellchecker_ != NULL) {
- spellchecker_->SpellCheckWord(word.c_str(),
- static_cast<int>(word.length()), tag,
- &misspell_location, &misspell_length, NULL);
- }
+void ResourceMessageFilter::OnPlatformCheckSpelling(const string16& word,
+ int tag,
+ bool* correct) {
+ *correct = SpellCheckerPlatform::CheckSpelling(word, tag);
+}
- ViewHostMsg_SpellCheck::WriteReplyParams(reply_msg, misspell_location,
- misspell_length);
- Send(reply_msg);
- return;
+void ResourceMessageFilter::OnPlatformFillSuggestionList(
+ const string16& word,
+ std::vector<string16>* suggestions) {
+ SpellCheckerPlatform::FillSuggestionList(word, suggestions);
}
void ResourceMessageFilter::OnGetDocumentTag(IPC::Message* reply_msg) {
@@ -1050,19 +1014,6 @@ void ResourceMessageFilter::OnDocumentWithTagClosed(int tag) {
SpellCheckerPlatform::CloseDocumentWithTag(tag);
}
-void ResourceMessageFilter::OnGetAutoCorrectWord(const string16& word,
- int tag,
- IPC::Message* reply_msg) {
- string16 autocorrect_word;
- if (spellchecker_ != NULL)
- autocorrect_word = spellchecker_->GetAutoCorrectionWord(word, tag);
-
- ViewHostMsg_GetAutoCorrectWord::WriteReplyParams(reply_msg,
- autocorrect_word);
- Send(reply_msg);
- return;
-}
-
void ResourceMessageFilter::OnShowSpellingPanel(bool show) {
SpellCheckerPlatform::ShowSpellingPanel(show);
}
@@ -1075,10 +1026,7 @@ void ResourceMessageFilter::OnUpdateSpellingPanelWithMisspelledWord(
void ResourceMessageFilter::Observe(NotificationType type,
const NotificationSource &source,
const NotificationDetails &details) {
- if (type == NotificationType::SPELLCHECKER_REINITIALIZED) {
- spellchecker_ = Details<SpellcheckerReinitializedDetails>
- (details).ptr()->spellchecker;
- } else if (type == NotificationType::BLACKLIST_BLOCKED_RESOURCE) {
+ if (type == NotificationType::BLACKLIST_BLOCKED_RESOURCE) {
BlacklistObserver::ContentBlocked(Details<const URLRequest>(details).ptr());
}
}
diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h
index 50507db..f2cb2df 100644
--- a/chrome/browser/renderer_host/resource_message_filter.h
+++ b/chrome/browser/renderer_host/resource_message_filter.h
@@ -87,7 +87,6 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
printing::PrintJobManager* print_job_manager,
Profile* profile,
RenderWidgetHelper* render_widget_helper,
- SpellChecker* spellchecker,
URLRequestContextGetter* request_context);
// IPC::ChannelProxy::MessageFilter methods:
@@ -104,7 +103,6 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
uint32 request_id,
const ViewHostMsg_Resource_Request& request_data);
- SpellChecker* spellchecker() { return spellchecker_.get(); }
ResourceDispatcherHost* resource_dispatcher_host() {
return resource_dispatcher_host_;
}
@@ -185,11 +183,11 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
void OnDownloadUrl(const IPC::Message& message,
const GURL& url,
const GURL& referrer);
- void OnSpellCheck(const string16& word, int tag, IPC::Message* reply_msg);
+ void OnPlatformCheckSpelling(const string16& word, int tag, bool* correct);
+ void OnPlatformFillSuggestionList(const string16& word,
+ std::vector<string16>* suggestions);
void OnGetDocumentTag(IPC::Message* reply_msg);
void OnDocumentWithTagClosed(int tag);
- void OnGetAutoCorrectWord(const string16& word, int tag,
- IPC::Message* reply_msg);
void OnShowSpellingPanel(bool show);
void OnUpdateSpellingPanelWithMisspelledWord(const string16& word);
void OnDnsPrefetch(const std::vector<std::string>& hostnames);
@@ -349,9 +347,6 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
// before this object, we only hold an ID for lookup.
int child_id_;
- // Our spellchecker object.
- scoped_refptr<SpellChecker> spellchecker_;
-
// Helper class for handling PluginProcessHost_ResolveProxy messages (manages
// the requests to the proxy service).
ResolveProxyMsgHelper resolve_proxy_msg_helper_;
diff --git a/chrome/browser/spellcheck_host.cc b/chrome/browser/spellcheck_host.cc
index 446d19d..f716e7a 100644
--- a/chrome/browser/spellcheck_host.cc
+++ b/chrome/browser/spellcheck_host.cc
@@ -11,120 +11,22 @@
#include "base/logging.h"
#include "base/path_service.h"
#include "base/string_util.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/spellchecker_platform_engine.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/notification_service.h"
+#include "chrome/common/pref_member.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/spellcheck_common.h"
#include "googleurl/src/gurl.h"
namespace {
-static const struct {
- // The language.
- const char* language;
-
- // The corresponding language and region, used by the dictionaries.
- const char* language_region;
-} g_supported_spellchecker_languages[] = {
- // Several languages are not to be included in the spellchecker list:
- // th-TH, hu-HU, bg-BG, uk-UA
- {"ca", "ca-ES"},
- {"cs", "cs-CZ"},
- {"da", "da-DK"},
- {"de", "de-DE"},
- {"el", "el-GR"},
- {"en-AU", "en-AU"},
- {"en-GB", "en-GB"},
- {"en-US", "en-US"},
- {"es", "es-ES"},
- {"et", "et-EE"},
- {"fr", "fr-FR"},
- {"he", "he-IL"},
- {"hi", "hi-IN"},
- {"hr", "hr-HR"},
- {"id", "id-ID"},
- {"it", "it-IT"},
- {"lt", "lt-LT"},
- {"lv", "lv-LV"},
- {"nb", "nb-NO"},
- {"nl", "nl-NL"},
- {"pl", "pl-PL"},
- {"pt-BR", "pt-BR"},
- {"pt-PT", "pt-PT"},
- {"ro", "ro-RO"},
- {"ru", "ru-RU"},
- {"sk", "sk-SK"},
- {"sl", "sl-SI"},
- {"sv", "sv-SE"},
- {"tr", "tr-TR"},
- {"vi", "vi-VN"},
-};
-
-// This function returns the language-region version of language name.
-// e.g. returns hi-IN for hi.
-std::string GetSpellCheckLanguageRegion(const std::string& input_language) {
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(g_supported_spellchecker_languages);
- ++i) {
- if (g_supported_spellchecker_languages[i].language == input_language) {
- return std::string(
- g_supported_spellchecker_languages[i].language_region);
- }
- }
-
- return input_language;
-}
-
-FilePath GetVersionedFileName(const std::string& input_language,
- const FilePath& dict_dir) {
- // The default dictionary version is 1-2. These versions have been augmented
- // with additional words found by the translation team.
- static const char kDefaultVersionString[] = "-1-2";
-
- // The following dictionaries have either not been augmented with additional
- // words (version 1-1) or have new words, as well as an upgraded dictionary
- // as of Feb 2009 (version 1-3).
- static const struct {
- // The language input.
- const char* language;
-
- // The corresponding version.
- const char* version;
- } special_version_string[] = {
- {"en-AU", "-1-1"},
- {"en-GB", "-1-1"},
- {"es-ES", "-1-1"},
- {"nl-NL", "-1-1"},
- {"ru-RU", "-1-1"},
- {"sv-SE", "-1-1"},
- {"he-IL", "-1-1"},
- {"el-GR", "-1-1"},
- {"hi-IN", "-1-1"},
- {"tr-TR", "-1-1"},
- {"et-EE", "-1-1"},
- {"fr-FR", "-1-4"}, // To fix a crash, fr dictionary was updated to 1.4.
- {"lt-LT", "-1-3"},
- {"pl-PL", "-1-3"}
- };
-
- // Generate the bdict file name using default version string or special
- // version string, depending on the language.
- std::string language = GetSpellCheckLanguageRegion(input_language);
- std::string versioned_bdict_file_name(language + kDefaultVersionString +
- ".bdic");
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(special_version_string); ++i) {
- if (language == special_version_string[i].language) {
- versioned_bdict_file_name =
- language + special_version_string[i].version + ".bdic";
- break;
- }
- }
-
- return dict_dir.AppendASCII(versioned_bdict_file_name);
-}
-
FilePath GetFirstChoiceFilePath(const std::string& language) {
FilePath dict_dir;
PathService::Get(chrome::DIR_APP_DICTIONARIES, &dict_dir);
- return GetVersionedFileName(language, dict_dir);
+ return SpellCheckCommon::GetVersionedFileName(language, dict_dir);
}
FilePath GetFallbackFilePath(const FilePath& first_choice) {
@@ -143,6 +45,7 @@ SpellCheckHost::SpellCheckHost(Observer* observer,
language_(language),
file_(base::kInvalidPlatformFileValue),
tried_to_download_(false),
+ use_platform_spellchecker_(false),
request_context_getter_(request_context_getter) {
DCHECK(observer_);
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
@@ -161,6 +64,16 @@ SpellCheckHost::~SpellCheckHost() {
}
void SpellCheckHost::Initialize() {
+ if (SpellCheckerPlatform::SpellCheckerAvailable() &&
+ SpellCheckerPlatform::PlatformSupportsLanguage(language_)) {
+ use_platform_spellchecker_ = true;
+ SpellCheckerPlatform::SetLanguage(language_);
+ MessageLoop::current()->PostTask(FROM_HERE,
+ NewRunnableMethod(this,
+ &SpellCheckHost::InformObserverOfInitialization));
+ return;
+ }
+
ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE,
NewRunnableMethod(this, &SpellCheckHost::InitializeDictionaryLocation));
}
@@ -185,6 +98,50 @@ void SpellCheckHost::AddWord(const std::string& word) {
Source<SpellCheckHost>(this), NotificationService::NoDetails());
}
+// static
+int SpellCheckHost::GetSpellCheckLanguages(
+ Profile* profile,
+ std::vector<std::string>* languages) {
+ StringPrefMember accept_languages_pref;
+ StringPrefMember dictionary_language_pref;
+ accept_languages_pref.Init(prefs::kAcceptLanguages, profile->GetPrefs(),
+ NULL);
+ dictionary_language_pref.Init(prefs::kSpellCheckDictionary,
+ profile->GetPrefs(), NULL);
+ std::string dictionary_language =
+ WideToASCII(dictionary_language_pref.GetValue());
+
+ // The current dictionary language should be there.
+ languages->push_back(dictionary_language);
+
+ // Now scan through the list of accept languages, and find possible mappings
+ // from this list to the existing list of spell check languages.
+ std::vector<std::string> accept_languages;
+
+ if (SpellCheckerPlatform::SpellCheckerAvailable()) {
+ SpellCheckerPlatform::GetAvailableLanguages(&accept_languages);
+ } else {
+ SplitString(WideToASCII(accept_languages_pref.GetValue()), ',',
+ &accept_languages);
+ }
+ for (std::vector<std::string>::const_iterator i = accept_languages.begin();
+ i != accept_languages.end(); ++i) {
+ std::string language =
+ SpellCheckCommon::GetCorrespondingSpellCheckLanguage(*i);
+ if (!language.empty() &&
+ std::find(languages->begin(), languages->end(), language) ==
+ languages->end()) {
+ languages->push_back(language);
+ }
+ }
+
+ for (size_t i = 0; i < languages->size(); ++i) {
+ if ((*languages)[i] == dictionary_language)
+ return i;
+ }
+ return -1;
+}
+
void SpellCheckHost::InitializeDictionaryLocation() {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
diff --git a/chrome/browser/spellcheck_host.h b/chrome/browser/spellcheck_host.h
index 6b25cd0..325921a 100644
--- a/chrome/browser/spellcheck_host.h
+++ b/chrome/browser/spellcheck_host.h
@@ -15,6 +15,8 @@
#include "chrome/browser/net/url_fetcher.h"
#include "chrome/browser/net/url_request_context_getter.h"
+class Profile;
+
class SpellCheckHost : public base::RefCountedThreadSafe<SpellCheckHost,
ChromeThread::DeleteOnFileThread>,
public URLFetcher::Delegate {
@@ -37,6 +39,14 @@ class SpellCheckHost : public base::RefCountedThreadSafe<SpellCheckHost,
// update.
void AddWord(const std::string& word);
+ // This function computes a vector of strings which are to be displayed in
+ // the context menu over a text area for changing spell check languages. It
+ // returns the index of the current spell check language in the vector.
+ // TODO(port): this should take a vector of string16, but the implementation
+ // has some dependencies in l10n util that need porting first.
+ static int GetSpellCheckLanguages(Profile* profile,
+ std::vector<std::string>* languages);
+
const base::PlatformFile& bdict_file() const { return file_; }
const std::vector<std::string>& custom_words() const { return custom_words_; }
@@ -45,6 +55,8 @@ class SpellCheckHost : public base::RefCountedThreadSafe<SpellCheckHost,
const std::string& language() const { return language_; }
+ bool use_platform_spellchecker() const { return use_platform_spellchecker_; }
+
private:
// These two classes can destruct us.
friend class ChromeThread;
@@ -109,6 +121,9 @@ class SpellCheckHost : public base::RefCountedThreadSafe<SpellCheckHost,
// once.
bool tried_to_download_;
+ // Whether we should use the platform spellchecker instead of Hunspell.
+ bool use_platform_spellchecker_;
+
// Data received from the dictionary download.
std::string data_;
diff --git a/chrome/browser/spellcheck_worditerator.cc b/chrome/browser/spellcheck_worditerator.cc
deleted file mode 100644
index 34f2330..0000000
--- a/chrome/browser/spellcheck_worditerator.cc
+++ /dev/null
@@ -1,274 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/spellcheck_worditerator.h"
-
-#include <map>
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/string_util.h"
-#include "chrome/browser/spellchecker.h"
-
-#include "third_party/icu/public/common/unicode/normlzr.h"
-#include "third_party/icu/public/common/unicode/schriter.h"
-#include "third_party/icu/public/common/unicode/uchar.h"
-#include "third_party/icu/public/common/unicode/uscript.h"
-#include "third_party/icu/public/common/unicode/uset.h"
-#include "third_party/icu/public/i18n/unicode/ulocdata.h"
-
-SpellcheckCharAttribute::SpellcheckCharAttribute() {
- InitializeScriptTable();
-
- // Even though many dictionaries treats numbers and contractions as words and
- // treats USCRIPT_COMMON characters as word characters, the
- // SpellcheckWordIterator class treats USCRIPT_COMMON characters as non-word
- // characters to strictly-distinguish contraction characters from word
- // characters.
- SetWordScript(USCRIPT_COMMON, false);
-
- // Initialize the table of characters used for contractions.
- // This array consists of the 'Midletter' and 'MidNumLet' characters of the
- // word-break property list provided by Unicode, Inc.:
- // http://www.unicode.org/Public/UNIDATA/auxiliary/WordBreakProperty.txt
- static const UChar32 kMidLetters[] = {
- L'\x003A', // MidLetter # COLON
- L'\x00B7', // MidLetter # MIDDLE DOT
- L'\x0387', // MidLetter # GREEK ANO TELEIA
- L'\x05F4', // MidLetter # HEBREW PUNCTUATION GERSHAYIM
- L'\x2027', // MidLetter # HYPHENATION POINT
- L'\xFE13', // MidLetter # PRESENTATION FORM FOR VERTICAL COLON
- L'\xFE55', // MidLetter # SMALL COLON
- L'\xFF1A', // MidLetter # FULLWIDTH COLON
- L'\x0027', // MidNumLet # APOSTROPHE
- L'\x002E', // MidNumLet # FULL STOP
- L'\x2018', // MidNumLet # LEFT SINGLE QUOTATION MARK
- L'\x2019', // MidNumLet # RIGHT SINGLE QUOTATION MARK
- L'\x2024', // MidNumLet # ONE DOT LEADER
- L'\xFE52', // MidNumLet # SMALL FULL STOP
- L'\xFF07', // MidNumLet # FULLWIDTH APOSTROPHE
- L'\xFF0E', // MidNumLet # FULLWIDTH FULL STOP
- };
- for (size_t i = 0; i < arraysize(kMidLetters); ++i)
- middle_letters_[kMidLetters[i]] = true;
-}
-
-SpellcheckCharAttribute::~SpellcheckCharAttribute() {
-}
-
-// Sets the default language for this object.
-// This function retrieves the exemplar set to set up the default character
-// attributes.
-void SpellcheckCharAttribute::SetDefaultLanguage(const std::string& language) {
- UErrorCode status = U_ZERO_ERROR;
- ULocaleData* locale_data = ulocdata_open(language.c_str(), &status);
- if (U_FAILURE(status))
- return;
-
- // Retrieves the exemplar set of the given language and update the
- // character-attribute table to treat its characters as word characters.
- USet* exemplar_set = uset_open(1, 0);
- ulocdata_getExemplarSet(locale_data, exemplar_set, 0, ULOCDATA_ES_STANDARD,
- &status);
- ulocdata_close(locale_data);
- if (U_SUCCESS(status)) {
- int length = uset_size(exemplar_set);
- for (int i = 0; i < length; ++i) {
- UChar32 character = uset_charAt(exemplar_set, i);
- SetWordScript(GetScriptCode(character), true);
- }
-
- // Many languages use combining characters to input their characters from
- // keyboards. On the other hand, this exemplar set does not always include
- // combining characters for such languages.
- // To treat such combining characters as word characters, we decompose
- // this exemplar set and treat the decomposed characters as word characters.
- icu::UnicodeString composed;
- for (int i = 0; i < length; ++i)
- composed.append(uset_charAt(exemplar_set, i));
-
- icu::UnicodeString decomposed;
- icu::Normalizer::decompose(composed, FALSE, 0, decomposed, status);
- if (U_SUCCESS(status)) {
- icu::StringCharacterIterator iterator(decomposed);
- UChar32 character = iterator.first32();
- while (character != icu::CharacterIterator::DONE) {
- SetWordScript(GetScriptCode(character), true);
- character = iterator.next32();
- }
- }
- }
- uset_close(exemplar_set);
-}
-
-// Returns whether or not the given character is a character used by the
-// selected dictionary.
-bool SpellcheckCharAttribute::IsWordChar(UChar32 character) const {
- return IsWordScript(GetScriptCode(character)) && !u_isdigit(character);
-}
-
-// Returns whether or not the given character is a character used by
-// contractions.
-bool SpellcheckCharAttribute::IsContractionChar(UChar32 character) const {
- std::map<UChar32, bool>::const_iterator iterator;
- iterator = middle_letters_.find(character);
- if (iterator == middle_letters_.end())
- return false;
- return iterator->second;
-}
-
-// Initializes the mapping table.
-void SpellcheckCharAttribute::InitializeScriptTable() {
- for (size_t i = 0; i < arraysize(script_attributes_); ++i)
- script_attributes_[i] = false;
-}
-
-// Retrieves the ICU script code.
-UScriptCode SpellcheckCharAttribute::GetScriptCode(UChar32 character) const {
- UErrorCode status = U_ZERO_ERROR;
- UScriptCode script_code = uscript_getScript(character, &status);
- return U_SUCCESS(status) ? script_code : USCRIPT_INVALID_CODE;
-}
-
-// Updates the mapping table from an ICU script code to its attribute, i.e.
-// whether not a script is used by the selected dictionary.
-void SpellcheckCharAttribute::SetWordScript(const int script_code,
- bool in_use) {
- if (script_code < 0 ||
- static_cast<size_t>(script_code) >= arraysize(script_attributes_))
- return;
- script_attributes_[script_code] = in_use;
-}
-
-// Returns whether or not the given script is used by the selected
-// dictionary.
-bool SpellcheckCharAttribute::IsWordScript(
- const UScriptCode script_code) const {
- if (script_code < 0 ||
- static_cast<size_t>(script_code) >= arraysize(script_attributes_))
- return false;
- return script_attributes_[script_code];
-}
-
-SpellcheckWordIterator::SpellcheckWordIterator()
- : word_(NULL),
- length_(0),
- position_(0),
- allow_contraction_(false),
- attribute_(NULL) {
-}
-
-SpellcheckWordIterator::~SpellcheckWordIterator() {
-}
-
-// Initialize a word-iterator object.
-void SpellcheckWordIterator::Initialize(
- const SpellcheckCharAttribute* attribute,
- const char16* word,
- size_t length,
- bool allow_contraction) {
- word_ = word;
- position_ = 0;
- length_ = static_cast<int>(length);
- allow_contraction_ = allow_contraction;
- attribute_ = attribute;
-}
-
-// Retrieves a word (or a contraction).
-// When a contraction is enclosed with contraction characters (e.g. 'isn't',
-// 'rock'n'roll'), we should discard the beginning and the end of the
-// contraction but we should never split the contraction.
-// To handle this case easily, we should firstly extract a segment consisting
-// of word characters and contraction characters, and discard contraction
-// characters at the beginning and the end of the extracted segment.
-bool SpellcheckWordIterator::GetNextWord(string16* word_string,
- int* word_start,
- int* word_length) {
- word_string->clear();
- *word_start = 0;
- *word_length = 0;
- while (position_ < length_) {
- int segment_start = 0;
- int segment_end = 0;
- GetSegment(&segment_start, &segment_end);
- TrimSegment(segment_start, segment_end, word_start, word_length);
- if (*word_length > 0)
- return Normalize(*word_start, *word_length, word_string);
- }
-
- return false;
-}
-
-// Retrieves a segment consisting of word characters (and contraction
-// characters if the |allow_contraction_| value is true).
-// When the current position refers to a non-word character, this function
-// returns a non-empty segment consisting of the character itself. In this
-// case, the TrimSegment() function discards the character and returns an
-// empty word (i.e. |word_length| == 0).
-void SpellcheckWordIterator::GetSegment(int* segment_start,
- int* segment_end) {
- int position = position_;
- while (position < length_) {
- UChar32 character;
- U16_NEXT(word_, position, length_, character);
- if (!attribute_->IsWordChar(character)) {
- if (!allow_contraction_ || !attribute_->IsContractionChar(character))
- break;
- }
- }
- *segment_start = position_;
- *segment_end = position;
- position_ = position;
-}
-
-// Discards non-word characters at the beginning and the end of the given
-// segment.
-void SpellcheckWordIterator::TrimSegment(int segment_start,
- int segment_end,
- int* word_start,
- int* word_length) const {
- while (segment_start < segment_end) {
- UChar32 character;
- int segment_next = segment_start;
- U16_NEXT(word_, segment_next, segment_end, character);
- if (attribute_->IsWordChar(character)) {
- *word_start = segment_start;
- break;
- }
- segment_start = segment_next;
- }
- while (segment_end >= segment_start) {
- UChar32 character;
- int segment_prev = segment_end;
- U16_PREV(word_, segment_start, segment_prev, character);
- if (attribute_->IsWordChar(character)) {
- *word_length = segment_end - segment_start;
- break;
- }
- segment_end = segment_prev;
- }
-}
-
-// Normalizes a non-terminated string into its canonical form so that
-// a spellchecker object can check spellings of words which contain ligatures,
-// full-width letters, etc.
-// USCRIPT_LATIN does not only consists of US-ASCII and ISO/IEC 8859-1, but
-// also consists of ISO/IEC 8859-{2,3,4,9,10}, ligatures, fullwidth latin,
-// etc. For its details, please read the script table in
-// "http://www.unicode.org/Public/UNIDATA/Scripts.txt".
-bool SpellcheckWordIterator::Normalize(int input_start,
- int input_length,
- string16* output_string) const {
- // Unicode Standard Annex #15 "http://www.unicode.org/unicode/reports/tr15/"
- // does not only write NFKD and NFKC can compose ligatures into their ASCII
- // alternatives, but also write NFKC keeps accents of characters.
- // Therefore, NFKC seems to be the best option for hunspell.
- icu::UnicodeString input(FALSE, &word_[input_start], input_length);
- UErrorCode status = U_ZERO_ERROR;
- icu::UnicodeString output;
- icu::Normalizer::normalize(input, UNORM_NFKC, 0, output, status);
- if (U_SUCCESS(status))
- output_string->assign(output.getTerminatedBuffer());
- return status == U_ZERO_ERROR || status == U_STRING_NOT_TERMINATED_WARNING;
-}
diff --git a/chrome/browser/spellcheck_worditerator.h b/chrome/browser/spellcheck_worditerator.h
deleted file mode 100644
index c0fb8e1..0000000
--- a/chrome/browser/spellcheck_worditerator.h
+++ /dev/null
@@ -1,183 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_SPELLCHECK_WORDITERATOR_H_
-#define CHROME_BROWSER_SPELLCHECK_WORDITERATOR_H_
-
-#include <map>
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/string16.h"
-
-#include "unicode/uscript.h"
-
-// A class which handles character attributes dependent on a spellchecker and
-// its dictionary.
-// This class is used by the SpellcheckWordIterator class to determine whether
-// or not a character is one used by the spellchecker and its dictinary.
-class SpellcheckCharAttribute {
- public:
- SpellcheckCharAttribute();
-
- ~SpellcheckCharAttribute();
-
- // Sets the default language of the spell checker. This controls which
- // characters are considered parts of words of the given language.
- void SetDefaultLanguage(const std::string& language);
-
- // Returns whether or not the given character is a character used by the
- // selected dictionary.
- // Parameters
- // * character [in] (UChar32)
- // Represents a Unicode character to be checked.
- // Return values
- // * true
- // The given character is a word character.
- // * false
- // The given character is not a word character.
- bool IsWordChar(UChar32 character) const;
-
- // Returns whether or not the given character is a character used by
- // contractions.
- // Parameters
- // * character [in] (UChar32)
- // Represents a Unicode character to be checked.
- // Return values
- // * true
- // The given character is a character used by contractions.
- // * false
- // The given character is not a character used by contractions.
- bool IsContractionChar(UChar32 character) const;
-
- private:
- // Initializes the mapping table.
- void InitializeScriptTable();
-
- // Retrieves the ICU script code.
- UScriptCode GetScriptCode(UChar32 character) const;
-
- // Updates an entry in the mapping table.
- void SetWordScript(const int script_code, bool in_use);
-
- // Returns whether or not the given script is used by the selected
- // dictionary.
- bool IsWordScript(const UScriptCode script_code) const;
-
- private:
- // Represents a mapping table from a script code to a boolean value
- // representing whether or not the script is used by the selected dictionary.
- bool script_attributes_[USCRIPT_CODE_LIMIT];
-
- // Represents a table of characters used by contractions.
- std::map<UChar32, bool> middle_letters_;
-
- DISALLOW_COPY_AND_ASSIGN(SpellcheckCharAttribute);
-};
-
-// A class which implements methods for finding the location of word boundaries
-// used by the Spellchecker class.
-// This class is implemented on the following assumptions:
-// * An input string is encoded in UTF-16 (i.e. it may contain surrogate
-// pairs), and;
-// * The length of a string is the number of UTF-16 characters in the string
-// (i.e. the length of a non-BMP character becomes two).
-class SpellcheckWordIterator {
- public:
- SpellcheckWordIterator();
-
- ~SpellcheckWordIterator();
-
- // Initializes a word-iterator object.
- // Parameters
- // * attribute [in] (const SpellcheckCharAttribute*)
- // Represents a set of character attributes used for filtering out
- // non-word characters.
- // * word [in] (const char16*)
- // Represents a string from which this object extracts words.
- // (This string does not have to be NUL-terminated.)
- // * length [in] (size_t)
- // Represents the length of the given string, in UTF-16 characters.
- // This value should not include terminating NUL characters.
- // * allow_contraction [in] (bool)
- // Represents a flag to control whether or not this object should split a
- // possible contraction (e.g. "isn't", "in'n'out", etc.)
- // Return values
- // * true
- // This word-iterator object is initialized successfully.
- // * false
- // An error occured while initializing this object.
- void Initialize(const SpellcheckCharAttribute* attribute,
- const char16* word,
- size_t length,
- bool allow_contraction);
-
- // Retrieves a word (or a contraction).
- // Parameters
- // * word_string [out] (string16*)
- // Represents a word (or a contraction) to be checked its spelling.
- // This |word_string| has been already normalized to its canonical form
- // (i.e. decomposed ligatures, replaced full-width latin characters to
- // its ASCII alternatives, etc.) so that a SpellChecker object can check
- // its spelling without any additional operations.
- // On the other hand, a substring of the input string
- // string16 str(&word[word_start], word_length);
- // represents the non-normalized version of this extracted word.
- // * word_start [out] (int*)
- // Represents the offset of this word from the beginning of the input
- // string, in UTF-16 characters.
- // * word_length [out] (int*)
- // Represents the length of an extracted word before normalization, in
- // UTF-16 characters.
- // When the input string contains ligatures, this value may not be equal
- // to the length of the |word_string|.
- // Return values
- // * true
- // Found a word (or a contraction) to be checked its spelling.
- // * false
- // Not found any more words or contractions to be checked their spellings.
- bool GetNextWord(string16* word_string,
- int* word_start,
- int* word_length);
-
- private:
- // Retrieves a segment consisting of word characters (and contraction
- // characters if the |allow_contraction| value is true).
- void GetSegment(int* segment_start,
- int* segment_end);
-
- // Discards non-word characters at the beginning and the end of the given
- // segment.
- void TrimSegment(int segment_start,
- int segment_end,
- int* word_start,
- int* word_length) const;
-
- // Normalizes the given segment of the |word_| variable and write its
- // canonical form to the |output_string|.
- bool Normalize(int input_start,
- int input_length,
- string16* output_string) const;
-
- private:
- // The pointer to the input string from which we are extracting words.
- const char16* word_;
-
- // The length of the original string.
- int length_;
-
- // The current position in the original string.
- int position_;
-
- // The flag to control whether or not this object should extract possible
- // contractions.
- bool allow_contraction_;
-
- // The character attributes used for filtering out non-word characters.
- const SpellcheckCharAttribute* attribute_;
-
- DISALLOW_COPY_AND_ASSIGN(SpellcheckWordIterator);
-};
-
-#endif // CHROME_BROWSER_SPELLCHECK_WORDITERATOR_H_
diff --git a/chrome/browser/spellchecker.cc b/chrome/browser/spellchecker.cc
deleted file mode 100644
index 903cdb9..0000000
--- a/chrome/browser/spellchecker.cc
+++ /dev/null
@@ -1,814 +0,0 @@
-// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/spellchecker.h"
-
-#include "app/l10n_util.h"
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/file_util.h"
-#include "base/histogram.h"
-#include "base/logging.h"
-#include "base/path_service.h"
-#include "base/stats_counters.h"
-#include "base/string_util.h"
-#include "chrome/browser/net/url_fetcher.h"
-#include "chrome/browser/profile.h"
-#include "chrome/browser/spellchecker_common.h"
-#include "chrome/browser/spellchecker_platform_engine.h"
-#include "chrome/common/chrome_constants.h"
-#include "chrome/common/chrome_counters.h"
-#include "chrome/common/chrome_paths.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/common/pref_service.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-#include "net/url_request/url_request.h"
-#include "third_party/hunspell/src/hunspell/hunspell.hxx"
-
-using base::TimeTicks;
-
-namespace {
-
-static const struct {
- // The language.
- const char* language;
-
- // The corresponding language and region, used by the dictionaries.
- const char* language_region;
-} g_supported_spellchecker_languages[] = {
- {"en-US", "en-US"},
- {"en-GB", "en-GB"},
- {"en-AU", "en-AU"},
- {"fr", "fr-FR"},
- {"it", "it-IT"},
- {"de", "de-DE"},
- {"es", "es-ES"},
- {"nl", "nl-NL"},
- {"pt-BR", "pt-BR"},
- {"ru", "ru-RU"},
- {"pl", "pl-PL"},
- // {"th", "th-TH"}, // Not to be included in Spellchecker as per B=1277824
- {"sv", "sv-SE"},
- {"da", "da-DK"},
- {"pt-PT", "pt-PT"},
- {"ro", "ro-RO"},
- // {"hu", "hu-HU"}, // Not to be included in Spellchecker as per B=1277824
- {"he", "he-IL"},
- {"id", "id-ID"},
- {"cs", "cs-CZ"},
- {"el", "el-GR"},
- {"nb", "nb-NO"},
- {"vi", "vi-VN"},
- // {"bg", "bg-BG"}, // Not to be included in Spellchecker as per B=1277824
- {"hr", "hr-HR"},
- {"lt", "lt-LT"},
- {"sk", "sk-SK"},
- {"sl", "sl-SI"},
- {"ca", "ca-ES"},
- {"lv", "lv-LV"},
- // {"uk", "uk-UA"}, // Not to be included in Spellchecker as per B=1277824
- {"hi", "hi-IN"},
- {"et", "et-EE"},
- {"tr", "tr-TR"},
-};
-
-// Get the fallback folder (currently chrome::DIR_USER_DATA) where the
-// dictionary is downloaded in case of system-wide installations.
-FilePath GetFallbackDictionaryDownloadDirectory() {
- FilePath dict_dir_userdata;
- PathService::Get(chrome::DIR_USER_DATA, &dict_dir_userdata);
- dict_dir_userdata = dict_dir_userdata.AppendASCII("Dictionaries");
- return dict_dir_userdata;
-}
-
-bool SaveBufferToFile(const std::string& data,
- FilePath file_to_write) {
- int num_bytes = data.length();
- return file_util::WriteFile(file_to_write, data.data(), num_bytes) ==
- num_bytes;
-}
-
-} // namespace
-
-// Design: The spellchecker initializes hunspell_ in the Initialize() method.
-// This is done using the dictionary file on disk, e.g. "en-US_1_1.bdic".
-// Initialization of hunspell_ is held off during this process. If the
-// dictionary is not available, we first attempt to download and save it. After
-// the dictionary is downloaded and saved to disk (or the attempt to do so
-// fails)), corresponding flags are set in spellchecker - in the IO thread.
-// After the flags are cleared, a (final) attempt is made to initialize
-// hunspell_. If it fails even then (dictionary could not download), no more
-// attempts are made to initialize it.
-class SaveDictionaryTask : public Task {
- public:
- SaveDictionaryTask(Task* on_dictionary_save_complete_callback_task,
- const FilePath& first_attempt_file_name,
- const FilePath& fallback_file_name,
- const std::string& data)
- : on_dictionary_save_complete_callback_task_(
- on_dictionary_save_complete_callback_task),
- first_attempt_file_name_(first_attempt_file_name),
- fallback_file_name_(fallback_file_name),
- data_(data) {
- }
-
- private:
- void Run();
-
- bool SaveBufferToFile(const std::string& data,
- FilePath file_to_write) {
- int num_bytes = data.length();
- return file_util::WriteFile(file_to_write, data.data(), num_bytes) ==
- num_bytes;
- }
-
- // factory object to invokelater back to spellchecker in io thread on
- // download completion to change appropriate flags.
- Task* on_dictionary_save_complete_callback_task_;
-
- // The file which will be stored in the first attempt.
- FilePath first_attempt_file_name_;
-
- // The file which will be stored as a fallback.
- FilePath fallback_file_name_;
-
- // The buffer which has to be stored to disk.
- std::string data_;
-
- // This invokes back to io loop when downloading is over.
- DISALLOW_COPY_AND_ASSIGN(SaveDictionaryTask);
-};
-
-void SaveDictionaryTask::Run() {
- if (!SaveBufferToFile(data_, first_attempt_file_name_)) {
- // Try saving it to |fallback_file_name_|, which almost surely has
- // write permission. If even this fails, there is nothing to be done.
- FilePath fallback_dir = fallback_file_name_.DirName();
- // Create the directory if it does not exist.
- if (!file_util::PathExists(fallback_dir))
- file_util::CreateDirectory(fallback_dir);
- SaveBufferToFile(data_, fallback_file_name_);
- } // Unsuccessful save is taken care of in SpellChecker::Initialize().
-
- // Set Flag that dictionary is not downloading anymore.
- ChromeThread::PostTask(
- ChromeThread::IO, FROM_HERE, on_dictionary_save_complete_callback_task_);
-}
-
-// Design: this task tries to read the dictionary from disk and load it into
-// memory. It is executed on the file thread, and posts the results back to
-// the IO thread.
-// The task first checks for the existence of the dictionary in one of the two
-// given locations. If it does not exist, the task informs the SpellChecker,
-// which will try to download the directory and run a new ReadDictionaryTask.
-class ReadDictionaryTask : public Task {
- public:
- ReadDictionaryTask(SpellChecker* spellchecker,
- const FilePath& dict_file_name_app,
- const FilePath& dict_file_name_usr)
- : spellchecker_(spellchecker),
- hunspell_(NULL),
- bdict_file_(NULL),
- custom_dictionary_file_name_(
- spellchecker->custom_dictionary_file_name_),
- dict_file_name_app_(dict_file_name_app),
- dict_file_name_usr_(dict_file_name_usr) {
- }
-
- virtual void Run() {
- FilePath bdict_file_path;
- if (file_util::PathExists(dict_file_name_app_)) {
- bdict_file_path = dict_file_name_app_;
- } else if (file_util::PathExists(dict_file_name_usr_)) {
- bdict_file_path = dict_file_name_usr_;
- } else {
- Finish(false);
- return;
- }
-
- bdict_file_ = new file_util::MemoryMappedFile;
- if (bdict_file_->Initialize(bdict_file_path)) {
- TimeTicks start_time = TimeTicks::Now();
-
- hunspell_ =
- new Hunspell(bdict_file_->data(), bdict_file_->length());
-
- // Add custom words to Hunspell.
- std::string contents;
- file_util::ReadFileToString(custom_dictionary_file_name_, &contents);
- std::vector<std::string> list_of_words;
- SplitString(contents, '\n', &list_of_words);
- for (std::vector<std::string>::iterator it = list_of_words.begin();
- it != list_of_words.end(); ++it) {
- hunspell_->add(it->c_str());
- }
-
- DHISTOGRAM_TIMES("Spellcheck.InitTime",
- TimeTicks::Now() - start_time);
- } else {
- delete bdict_file_;
- bdict_file_ = NULL;
- }
-
- Finish(true);
- }
-
- private:
- void Finish(bool file_existed) {
- ChromeThread::PostTask(
- ChromeThread::IO, FROM_HERE,
- NewRunnableMethod(
- spellchecker_.get(), &SpellChecker::HunspellInited, hunspell_,
- bdict_file_, file_existed));
- }
-
- // The SpellChecker we are working for.
- scoped_refptr<SpellChecker> spellchecker_;
- Hunspell* hunspell_;
- file_util::MemoryMappedFile* bdict_file_;
-
- FilePath custom_dictionary_file_name_;
- FilePath dict_file_name_app_;
- FilePath dict_file_name_usr_;
-
- DISALLOW_COPY_AND_ASSIGN(ReadDictionaryTask);
-};
-
-void SpellChecker::SpellCheckLanguages(std::vector<std::string>* languages) {
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(g_supported_spellchecker_languages);
- ++i) {
- languages->push_back(g_supported_spellchecker_languages[i].language);
- }
-}
-
-// This function returns the language-region version of language name.
-// e.g. returns hi-IN for hi.
-std::string SpellChecker::GetSpellCheckLanguageRegion(
- std::string input_language) {
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(g_supported_spellchecker_languages);
- ++i) {
- std::string language(
- g_supported_spellchecker_languages[i].language);
- if (language == input_language)
- return std::string(
- g_supported_spellchecker_languages[i].language_region);
- }
-
- return input_language;
-}
-
-
-std::string SpellChecker::GetLanguageFromLanguageRegion(
- std::string input_language) {
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(g_supported_spellchecker_languages);
- ++i) {
- std::string language(
- g_supported_spellchecker_languages[i].language_region);
- if (language == input_language)
- return std::string(g_supported_spellchecker_languages[i].language);
- }
-
- return input_language;
-}
-
-std::string SpellChecker::GetCorrespondingSpellCheckLanguage(
- const std::string& language) {
- // Look for exact match in the Spell Check language list.
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(g_supported_spellchecker_languages);
- ++i) {
- // First look for exact match in the language region of the list.
- std::string spellcheck_language(
- g_supported_spellchecker_languages[i].language);
- if (spellcheck_language == language)
- return language;
-
- // Next, look for exact match in the language_region part of the list.
- std::string spellcheck_language_region(
- g_supported_spellchecker_languages[i].language_region);
- if (spellcheck_language_region == language)
- return g_supported_spellchecker_languages[i].language;
- }
-
- // Look for a match by comparing only language parts. All the 'en-RR'
- // except for 'en-GB' exactly matched in the above loop, will match
- // 'en-US'. This is not ideal because 'en-ZA', 'en-NZ' had
- // better be matched with 'en-GB'. This does not handle cases like
- // 'az-Latn-AZ' vs 'az-Arab-AZ', either, but we don't use 3-part
- // locale ids with a script code in the middle, yet.
- // TODO(jungshik): Add a better fallback.
- std::string language_part(language, 0, language.find('-'));
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(g_supported_spellchecker_languages);
- ++i) {
- std::string spellcheck_language(
- g_supported_spellchecker_languages[i].language_region);
- if (spellcheck_language.substr(0, spellcheck_language.find('-')) ==
- language_part)
- return spellcheck_language;
- }
-
- // No match found - return blank.
- return std::string();
-}
-
-// static
-int SpellChecker::GetSpellCheckLanguages(
- Profile* profile,
- std::vector<std::string>* languages) {
- StringPrefMember accept_languages_pref;
- StringPrefMember dictionary_language_pref;
- accept_languages_pref.Init(prefs::kAcceptLanguages, profile->GetPrefs(),
- NULL);
- dictionary_language_pref.Init(prefs::kSpellCheckDictionary,
- profile->GetPrefs(), NULL);
- std::string dictionary_language =
- WideToASCII(dictionary_language_pref.GetValue());
-
- // The current dictionary language should be there.
- languages->push_back(dictionary_language);
-
- // Now scan through the list of accept languages, and find possible mappings
- // from this list to the existing list of spell check languages.
- std::vector<std::string> accept_languages;
-
- if (SpellCheckerPlatform::SpellCheckerAvailable()) {
- SpellCheckerPlatform::GetAvailableLanguages(&accept_languages);
- } else {
- SplitString(WideToASCII(accept_languages_pref.GetValue()), ',',
- &accept_languages);
- }
- for (std::vector<std::string>::const_iterator i = accept_languages.begin();
- i != accept_languages.end(); ++i) {
- std::string language = GetCorrespondingSpellCheckLanguage(*i);
- if (!language.empty() &&
- std::find(languages->begin(), languages->end(), language) ==
- languages->end())
- languages->push_back(language);
- }
-
- for (size_t i = 0; i < languages->size(); ++i) {
- if ((*languages)[i] == dictionary_language)
- return i;
- }
- return -1;
-}
-
-FilePath SpellChecker::GetVersionedFileName(const std::string& input_language,
- const FilePath& dict_dir) {
- // The default dictionary version is 1-2. These versions have been augmented
- // with additional words found by the translation team.
- static const char kDefaultVersionString[] = "-1-2";
-
- // The following dictionaries have either not been augmented with additional
- // words (version 1-1) or have new words, as well as an upgraded dictionary
- // as of Feb 2009 (version 1-3).
- static const struct {
- // The language input.
- const char* language;
-
- // The corresponding version.
- const char* version;
- } special_version_string[] = {
- {"en-AU", "-1-1"},
- {"en-GB", "-1-1"},
- {"es-ES", "-1-1"},
- {"nl-NL", "-1-1"},
- {"ru-RU", "-1-1"},
- {"sv-SE", "-1-1"},
- {"he-IL", "-1-1"},
- {"el-GR", "-1-1"},
- {"hi-IN", "-1-1"},
- {"tr-TR", "-1-1"},
- {"et-EE", "-1-1"},
- {"fr-FR", "-1-4"}, // to fix crash, fr dictionary was updated to 1.4
- {"lt-LT", "-1-3"},
- {"pl-PL", "-1-3"}
- };
-
- // Generate the bdict file name using default version string or special
- // version string, depending on the language.
- std::string language = GetSpellCheckLanguageRegion(input_language);
- std::string versioned_bdict_file_name(language + kDefaultVersionString +
- ".bdic");
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(special_version_string); ++i) {
- if (language == special_version_string[i].language) {
- versioned_bdict_file_name =
- language + special_version_string[i].version + ".bdic";
- break;
- }
- }
-
- return dict_dir.AppendASCII(versioned_bdict_file_name);
-}
-
-SpellChecker::SpellChecker(const FilePath& dict_dir,
- const std::string& language,
- URLRequestContextGetter* request_context_getter,
- const FilePath& custom_dictionary_file_name)
- : given_dictionary_directory_(dict_dir),
- custom_dictionary_file_name_(custom_dictionary_file_name),
- tried_to_init_(false),
- language_(language),
- tried_to_download_dictionary_file_(false),
- request_context_getter_(request_context_getter),
- obtaining_dictionary_(false),
- auto_spell_correct_turned_on_(false),
- is_using_platform_spelling_engine_(false),
- fetcher_(NULL),
- ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
- if (SpellCheckerPlatform::SpellCheckerAvailable()) {
- SpellCheckerPlatform::Init();
- if (SpellCheckerPlatform::PlatformSupportsLanguage(language)) {
- // If we have reached here, then we know that the current platform
- // supports the given language and we will use it instead of hunspell.
- SpellCheckerPlatform::SetLanguage(language);
- is_using_platform_spelling_engine_ = true;
- }
- }
-
- // Get the corresponding BDIC file name.
- bdic_file_name_ = GetVersionedFileName(language, dict_dir).BaseName();
-
- // Get the path to the custom dictionary file.
- if (custom_dictionary_file_name_.empty()) {
- FilePath personal_file_directory;
- PathService::Get(chrome::DIR_USER_DATA, &personal_file_directory);
- custom_dictionary_file_name_ =
- personal_file_directory.Append(chrome::kCustomDictionaryFileName);
- }
-
- // Use this dictionary language as the default one of the
- // SpellcheckCharAttribute object.
- character_attributes_.SetDefaultLanguage(language);
-}
-
-SpellChecker::~SpellChecker() {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
-}
-
-void SpellChecker::StartDictionaryDownload(const FilePath& file_name) {
- // Determine URL of file to download.
- static const char kDownloadServerUrl[] =
- "http://cache.pack.google.com/edgedl/chrome/dict/";
- GURL url = GURL(std::string(kDownloadServerUrl) + WideToUTF8(
- l10n_util::ToLower(bdic_file_name_.ToWStringHack())));
- fetcher_.reset(new URLFetcher(url, URLFetcher::GET, this));
- fetcher_->set_request_context(request_context_getter_);
- obtaining_dictionary_ = true;
- fetcher_->Start();
-}
-
-void SpellChecker::OnURLFetchComplete(const URLFetcher* source,
- const GURL& url,
- const URLRequestStatus& status,
- int response_code,
- const ResponseCookies& cookies,
- const std::string& data) {
- DCHECK(source);
- if ((response_code / 100) != 2) {
- obtaining_dictionary_ = false;
- return;
- }
-
- // Basic sanity check on the dictionary.
- // There's the small chance that we might see a 200 status code for a body
- // that represents some form of failure.
- if (data.size() < 4 || data[0] != 'B' || data[1] != 'D' || data[2] != 'i' ||
- data[3] != 'c') {
- obtaining_dictionary_ = false;
- return;
- }
-
- // Save the file in the file thread, and not here, the IO thread.
- FilePath first_attempt_file_name = given_dictionary_directory_.Append(
- bdic_file_name_);
- FilePath user_data_dir = GetFallbackDictionaryDownloadDirectory();
- FilePath fallback_file_name = user_data_dir.Append(bdic_file_name_);
- Task* dic_task = method_factory_.
- NewRunnableMethod(&SpellChecker::OnDictionarySaveComplete);
- ChromeThread::PostTask(
- ChromeThread::FILE, FROM_HERE,
- new SaveDictionaryTask(
- dic_task, first_attempt_file_name, fallback_file_name, data));
-}
-
-void SpellChecker::OnDictionarySaveComplete() {
- obtaining_dictionary_ = false;
- // Now that the dictionary is downloaded, continue trying to download.
- Initialize();
-}
-
-// Initialize SpellChecker. In this method, if the dictionary is not present
-// in the local disk, it is fetched asynchronously.
-bool SpellChecker::Initialize() {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
-
- // Return false if the dictionary files are downloading.
- if (obtaining_dictionary_)
- return false;
-
- // Return false if tried to init and failed - don't try multiple times in
- // this session.
- if (tried_to_init_)
- return hunspell_.get() != NULL;
-
- StatsScope<StatsCounterTimer> timer(chrome::Counters::spellcheck_init());
-
- // The default place whether the spellcheck dictionary can reside is
- // chrome::DIR_APP_DICTIONARIES. However, for systemwide installations,
- // this directory may not have permissions for download. In that case, the
- // alternate directory for download is chrome::DIR_USER_DATA. We have to check
- // for the spellcheck dictionaries in both the directories. If not found in
- // either one, it has to be downloaded in either of the two.
- // TODO(sidchat): Some sort of UI to warn users that spellchecker is not
- // working at all (due to failed dictionary download)?
-
- // File name for downloading in DIR_APP_DICTIONARIES.
- FilePath dictionary_file_name_app = GetVersionedFileName(language_,
- given_dictionary_directory_);
-
- // Filename for downloading in the fallback dictionary download directory,
- // DIR_USER_DATA.
- FilePath dict_dir_userdata = GetFallbackDictionaryDownloadDirectory();
- FilePath dictionary_file_name_usr = GetVersionedFileName(language_,
- dict_dir_userdata);
-
- ChromeThread::PostTask(
- ChromeThread::FILE, FROM_HERE,
- new ReadDictionaryTask(
- this, dictionary_file_name_app, dictionary_file_name_usr));
-
- return hunspell_.get() != NULL;
-}
-
-void SpellChecker::HunspellInited(Hunspell* hunspell,
- file_util::MemoryMappedFile* bdict_file,
- bool file_existed) {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
-
- if (file_existed)
- tried_to_init_ = true;
-
- if (!hunspell) {
- if (!file_existed) {
- // File didn't exist. We need to download a dictionary.
- DoDictionaryDownload();
- }
- return;
- }
-
-
- bdict_file_.reset(bdict_file);
- hunspell_.reset(hunspell);
- // Add all the custom words we've gotten while Hunspell was loading.
- while (!custom_words_.empty()) {
- hunspell_->add(custom_words_.front().c_str());
- custom_words_.pop();
- }
-}
-
-void SpellChecker::DoDictionaryDownload() {
- // Download the dictionary file.
- if (request_context_getter_) {
- if (!tried_to_download_dictionary_file_) {
- FilePath dictionary_file_name_app = GetVersionedFileName(language_,
- given_dictionary_directory_);
- StartDictionaryDownload(dictionary_file_name_app);
- tried_to_download_dictionary_file_ = true;
- } else {
- // Don't try to download a dictionary more than once.
- tried_to_init_ = true;
- }
- } else {
- NOTREACHED();
- }
-}
-
-string16 SpellChecker::GetAutoCorrectionWord(const string16& word, int tag) {
- string16 autocorrect_word;
- if (!auto_spell_correct_turned_on_)
- return autocorrect_word; // Return the empty string.
-
- int word_length = static_cast<int>(word.size());
- if (word_length < 2 || word_length > kMaxAutoCorrectWordSize)
- return autocorrect_word;
-
- char16 misspelled_word[kMaxAutoCorrectWordSize + 1];
- const char16* word_char = word.c_str();
- for (int i = 0; i <= kMaxAutoCorrectWordSize; i++) {
- if (i >= word_length)
- misspelled_word[i] = NULL;
- else
- misspelled_word[i] = word_char[i];
- }
-
- // Swap adjacent characters and spellcheck.
- int misspelling_start, misspelling_len;
- for (int i = 0; i < word_length - 1; i++) {
- // Swap.
- std::swap(misspelled_word[i], misspelled_word[i + 1]);
-
- // Check spelling.
- misspelling_start = misspelling_len = 0;
- SpellCheckWord(misspelled_word, word_length, tag, &misspelling_start,
- &misspelling_len, NULL);
-
- // Make decision: if only one swap produced a valid word, then we want to
- // return it. If we found two or more, we don't do autocorrection.
- if (misspelling_len == 0) {
- if (autocorrect_word.empty()) {
- autocorrect_word.assign(misspelled_word);
- } else {
- autocorrect_word.clear();
- break;
- }
- }
-
- // Restore the swapped characters.
- std::swap(misspelled_word[i], misspelled_word[i + 1]);
- }
- return autocorrect_word;
-}
-
-void SpellChecker::EnableAutoSpellCorrect(bool turn_on) {
- auto_spell_correct_turned_on_ = turn_on;
-}
-
-// Returns whether or not the given string is a valid contraction.
-// This function is a fall-back when the SpellcheckWordIterator class
-// returns a concatenated word which is not in the selected dictionary
-// (e.g. "in'n'out") but each word is valid.
-bool SpellChecker::IsValidContraction(const string16& contraction, int tag) {
- SpellcheckWordIterator word_iterator;
- word_iterator.Initialize(&character_attributes_, contraction.c_str(),
- contraction.length(), false);
-
- string16 word;
- int word_start;
- int word_length;
- while (word_iterator.GetNextWord(&word, &word_start, &word_length)) {
- if (!CheckSpelling(word, tag))
- return false;
- }
- return true;
-}
-
-bool SpellChecker::SpellCheckWord(
- const char16* in_word,
- int in_word_len,
- int tag,
- int* misspelling_start,
- int* misspelling_len,
- std::vector<string16>* optional_suggestions) {
- DCHECK(in_word_len >= 0);
- DCHECK(misspelling_start && misspelling_len) << "Out vars must be given.";
-
- // This must always be called on the same thread (normally the I/O thread).
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
-
- // Check if the platform spellchecker is being used.
- if (!is_using_platform_spelling_engine_) {
- // If it isn't, try and init hunspell.
- Initialize();
-
- // Check to see if hunspell was successfuly initialized.
- if (!hunspell_.get())
- return true; // Unable to spellcheck, return word is OK.
- }
-
- StatsScope<StatsRate> timer(chrome::Counters::spellcheck_lookup());
-
- *misspelling_start = 0;
- *misspelling_len = 0;
- if (in_word_len == 0)
- return true; // No input means always spelled correctly.
-
- SpellcheckWordIterator word_iterator;
- string16 word;
- int word_start;
- int word_length;
- word_iterator.Initialize(&character_attributes_, in_word, in_word_len, true);
- while (word_iterator.GetNextWord(&word, &word_start, &word_length)) {
- // Found a word (or a contraction) that the spellchecker can check the
- // spelling of.
- bool word_ok = CheckSpelling(word, tag);
- if (word_ok)
- continue;
-
- // If the given word is a concatenated word of two or more valid words
- // (e.g. "hello:hello"), we should treat it as a valid word.
- if (IsValidContraction(word, tag))
- continue;
-
- *misspelling_start = word_start;
- *misspelling_len = word_length;
-
- // Get the list of suggested words.
- if (optional_suggestions)
- FillSuggestionList(word, optional_suggestions);
- return false;
- }
-
- return true;
-}
-
-// This task is called in the file loop to write the new word to the custom
-// dictionary in disc.
-class AddWordToCustomDictionaryTask : public Task {
- public:
- AddWordToCustomDictionaryTask(const FilePath& file_name,
- const string16& word)
- : file_name_(file_name),
- word_(UTF16ToUTF8(word)) {
- }
-
- private:
- void Run();
-
- FilePath file_name_;
- std::string word_;
-};
-
-void AddWordToCustomDictionaryTask::Run() {
- // Add the word with a new line. Note that, although this would mean an
- // extra line after the list of words, this is potentially harmless and
- // faster, compared to verifying everytime whether to append a new line
- // or not.
- word_ += "\n";
- FILE* f = file_util::OpenFile(file_name_, "a+");
- if (f != NULL)
- fputs(word_.c_str(), f);
- file_util::CloseFile(f);
-}
-
-void SpellChecker::AddWord(const string16& word) {
- if (is_using_platform_spelling_engine_) {
- SpellCheckerPlatform::AddWord(word);
- return;
- }
-
- // Check if the |hunspell_| has been initialized at all.
- Initialize();
-
- // Add the word to hunspell.
- std::string word_to_add = UTF16ToUTF8(word);
- // Don't attempt to add an empty word, or one larger than Hunspell can handle
- if (!word_to_add.empty() && word_to_add.length() < MAXWORDLEN) {
- // Either add the word to |hunspell_|, or, if |hunspell_| is still loading,
- // defer it till after the load completes.
- if (hunspell_.get())
- hunspell_->add(word_to_add.c_str());
- else
- custom_words_.push(word_to_add);
- }
-
- // Now add the word to the custom dictionary file.
- ChromeThread::PostTask(
- ChromeThread::FILE, FROM_HERE,
- new AddWordToCustomDictionaryTask(custom_dictionary_file_name_, word));
-}
-
-bool SpellChecker::CheckSpelling(const string16& word_to_check, int tag) {
- bool word_correct = false;
-
- TimeTicks begin_time = TimeTicks::Now();
- if (is_using_platform_spelling_engine_) {
- word_correct = SpellCheckerPlatform::CheckSpelling(word_to_check, tag);
- } else {
- std::string word_to_check_utf8(UTF16ToUTF8(word_to_check));
- // Hunspell shouldn't let us exceed its max, but check just in case
- if (word_to_check_utf8.length() < MAXWORDLEN) {
- // |hunspell_->spell| returns 0 if the word is spelled correctly and
- // non-zero otherwsie.
- word_correct = (hunspell_->spell(word_to_check_utf8.c_str()) != 0);
- }
- }
- DHISTOGRAM_TIMES("Spellcheck.CheckTime", TimeTicks::Now() - begin_time);
-
- return word_correct;
-}
-
-void SpellChecker::FillSuggestionList(
- const string16& wrong_word,
- std::vector<string16>* optional_suggestions) {
- if (is_using_platform_spelling_engine_) {
- SpellCheckerPlatform::FillSuggestionList(wrong_word, optional_suggestions);
- return;
- }
- char** suggestions;
- TimeTicks begin_time = TimeTicks::Now();
- int number_of_suggestions = hunspell_->suggest(&suggestions,
- UTF16ToUTF8(wrong_word).c_str());
- DHISTOGRAM_TIMES("Spellcheck.SuggestTime",
- TimeTicks::Now() - begin_time);
-
- // Populate the vector of WideStrings.
- for (int i = 0; i < number_of_suggestions; i++) {
- if (i < kMaxSuggestions)
- optional_suggestions->push_back(UTF8ToUTF16(suggestions[i]));
- free(suggestions[i]);
- }
- if (suggestions != NULL)
- free(suggestions);
-}
diff --git a/chrome/browser/spellchecker.h b/chrome/browser/spellchecker.h
deleted file mode 100644
index 630f815..0000000
--- a/chrome/browser/spellchecker.h
+++ /dev/null
@@ -1,247 +0,0 @@
-// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_SPELLCHECKER_H_
-#define CHROME_BROWSER_SPELLCHECKER_H_
-
-#include <queue>
-#include <string>
-#include <vector>
-
-#include "app/l10n_util.h"
-#include "base/string16.h"
-#include "base/task.h"
-#include "base/time.h"
-#include "chrome/browser/chrome_thread.h"
-#include "chrome/browser/net/url_fetcher.h"
-#include "chrome/browser/profile.h"
-#include "chrome/browser/spellcheck_worditerator.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/common/pref_member.h"
-#include "unicode/uscript.h"
-
-class FilePath;
-class Hunspell;
-class PrefService;
-class Profile;
-class URLFetcher;
-class URLRequestContextGetter;
-
-namespace file_util {
-class MemoryMappedFile;
-}
-
-// The Browser's Spell Checker. It checks and suggests corrections.
-//
-// This object is not threadsafe. In normal usage (not unit tests) it lives on
-// the I/O thread of the browser. It is threadsafe refcounted so that I/O thread
-// and the profile on the main thread (which gives out references to it) can
-// keep it. However, all usage of this must be on the I/O thread.
-//
-// This object should also be deleted on the I/O thread only. It owns a
-// reference to URLRequestContext which in turn owns the cache, etc. and must be
-// deleted on the I/O thread itself.
-class SpellChecker
- : public base::RefCountedThreadSafe<
- SpellChecker, ChromeThread::DeleteOnIOThread>,
- public URLFetcher::Delegate {
- public:
- // Creates the spellchecker by reading dictionaries from the given directory,
- // and defaulting to the given language. Both strings must be provided.
- //
- // The request context is used to download dictionaries if they do not exist.
- // This can be NULL if you don't want this (like in tests).
- // The |custom_dictionary_file_name| should be left blank so that Spellchecker
- // can figure out the custom dictionary file. It is non empty only for unit
- // testing.
- SpellChecker(const FilePath& dict_dir,
- const std::string& language,
- URLRequestContextGetter* request_context_getter,
- const FilePath& custom_dictionary_file_name);
-
- // SpellCheck a word.
- // Returns true if spelled correctly, false otherwise.
- // If the spellchecker failed to initialize, always returns true.
- // The |tag| parameter should either be a unique identifier for the document
- // that the word came from (if the current platform requires it), or 0.
- // In addition, finds the suggested words for a given word
- // and puts them into |*optional_suggestions|.
- // If the word is spelled correctly, the vector is empty.
- // If optional_suggestions is NULL, suggested words will not be looked up.
- // Note that Doing suggest lookups can be slow.
- bool SpellCheckWord(const char16* in_word,
- int in_word_len,
- int tag,
- int* misspelling_start,
- int* misspelling_len,
- std::vector<string16>* optional_suggestions);
-
- // Find a possible correctly spelled word for a misspelled word. Computes an
- // empty string if input misspelled word is too long, there is ambiguity, or
- // the correct spelling cannot be determined.
- string16 GetAutoCorrectionWord(const string16& word, int tag);
-
- // Turn auto spell correct support ON or OFF.
- // |turn_on| = true means turn ON; false means turn OFF.
- void EnableAutoSpellCorrect(bool turn_on);
-
- // Add custom word to the dictionary, which means:
- // a) Add it to the current hunspell object for immediate use,
- // b) Add the word to a file in disk for custom dictionary.
- void AddWord(const string16& word);
-
- // Get SpellChecker supported languages.
- static void SpellCheckLanguages(std::vector<std::string>* languages);
-
- // This function computes a vector of strings which are to be displayed in
- // the context menu over a text area for changing spell check languages. It
- // returns the index of the current spell check language in the vector.
- // TODO(port): this should take a vector of string16, but the implementation
- // has some dependencies in l10n util that need porting first.
- static int GetSpellCheckLanguages(
- Profile* profile,
- std::vector<std::string>* languages);
-
- // This function returns the corresponding language-region code for the
- // spell check language. For example, for hi, it returns hi-IN.
- static std::string GetSpellCheckLanguageRegion(std::string input_language);
-
- // This function returns ll (language code) from ll-RR where 'RR' (region
- // code) is redundant. However, if the region code matters, it's preserved.
- // That is, it returns 'hi' and 'en-GB' for 'hi-IN' and 'en-GB' respectively.
- static std::string GetLanguageFromLanguageRegion(std::string input_language);
-
- private:
- friend class ChromeThread;
- friend class DeleteTask<SpellChecker>;
- friend class ReadDictionaryTask;
- FRIEND_TEST(SpellCheckTest, SpellCheckStrings_EN_US);
- FRIEND_TEST(SpellCheckTest, SpellCheckSuggestions_EN_US);
- FRIEND_TEST(SpellCheckTest, SpellCheckText);
- FRIEND_TEST(SpellCheckTest, DISABLED_SpellCheckAddToDictionary_EN_US);
- FRIEND_TEST(SpellCheckTest,
- DISABLED_SpellCheckSuggestionsAddToDictionary_EN_US);
- FRIEND_TEST(SpellCheckTest, GetAutoCorrectionWord_EN_US);
- FRIEND_TEST(SpellCheckTest, IgnoreWords_EN_US);
-
- // Only delete on the I/O thread (see above).
- ~SpellChecker();
-
- // URLFetcher::Delegate implementation. Called when we finish downloading the
- // spellcheck dictionary; saves the dictionary to disk.
- virtual void OnURLFetchComplete(const URLFetcher* source,
- const GURL& url,
- const URLRequestStatus& status,
- int response_code,
- const ResponseCookies& cookies,
- const std::string& data);
-
- // When called, relays the request to check the spelling to the proper
- // backend, either hunspell or a platform-specific backend.
- bool CheckSpelling(const string16& word_to_check, int tag);
-
- // When called, relays the request to fill the list with suggestions to
- // the proper backend, either hunspell or a platform-specific backend.
- void FillSuggestionList(const string16& wrong_word,
- std::vector<string16>* optional_suggestions);
-
- // Initializes the Hunspell Dictionary.
- bool Initialize();
-
- // Called when |hunspell| is done loading, succesfully or not. If |hunspell|
- // and |bdict_file| are non-NULL, assume ownership.
- void HunspellInited(Hunspell* hunspell,
- file_util::MemoryMappedFile* bdict_file,
- bool file_existed);
-
- // Either start downloading a dictionary if we have not already, or do nothing
- // if we have already tried to download one.
- void DoDictionaryDownload();
-
- // Returns whether or not the given word is a contraction of valid words
- // (e.g. "word:word").
- bool IsValidContraction(const string16& word, int tag);
-
- // Return the file name of the dictionary, including the path and the version
- // numbers.
- FilePath GetVersionedFileName(const std::string& language,
- const FilePath& dict_dir);
-
- static std::string GetCorrespondingSpellCheckLanguage(
- const std::string& language);
-
- // Start downloading a dictionary from the server. On completion, the
- // OnURLFetchComplete() function is invoked.
- void StartDictionaryDownload(const FilePath& file_name);
-
- // This method is called in the IO thread after dictionary download has
- // completed in FILE thread.
- void OnDictionarySaveComplete();
-
- // The given path to the directory whether SpellChecker first tries to
- // download the spellcheck bdic dictionary file.
- FilePath given_dictionary_directory_;
-
- // Path to the custom dictionary file.
- FilePath custom_dictionary_file_name_;
-
- // BDIC file name (e.g. en-US_1_1.bdic).
- FilePath bdic_file_name_;
-
- // We memory-map the BDict file.
- scoped_ptr<file_util::MemoryMappedFile> bdict_file_;
-
- // The hunspell dictionary in use.
- scoped_ptr<Hunspell> hunspell_;
-
- // Represents character attributes used for filtering out characters which
- // are not supported by this SpellChecker object.
- SpellcheckCharAttribute character_attributes_;
-
- // Flag indicating whether we've tried to initialize. If we've already
- // attempted initialiation, we won't retry to avoid failure loops.
- bool tried_to_init_;
-
- // The language that this spellchecker works in.
- std::string language_;
-
- // This object must only be used on the same thread. However, it is normally
- // created on the UI thread. This checks calls to SpellCheckWord and the
- // destructor to make sure we're only ever running on the same thread.
- //
- // This will be NULL if it is not initialized yet (not initialized in the
- // constructor since that's on a different thread).
- MessageLoop* worker_loop_;
-
- // Flag indicating whether we tried to download the dictionary file.
- bool tried_to_download_dictionary_file_;
-
- // Used for requests. MAY BE NULL which means don't try to download.
- URLRequestContextGetter* request_context_getter_;
-
- // True when we're downloading or saving a dictionary.
- bool obtaining_dictionary_;
-
- // Remember state for auto spell correct.
- bool auto_spell_correct_turned_on_;
-
- // True if a platform-specific spellchecking engine is being used,
- // and False if hunspell is being used.
- bool is_using_platform_spelling_engine_;
-
- // URLFetcher to download a file in memory.
- scoped_ptr<URLFetcher> fetcher_;
-
- // While Hunspell is loading, we add any new custom words to this queue.
- // We will add them to |hunspell_| when it is done loading.
- std::queue<std::string> custom_words_;
-
- // Used for generating callbacks to spellchecker, since spellchecker is a
- // non-reference counted object.
- ScopedRunnableMethodFactory<SpellChecker> method_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(SpellChecker);
-};
-
-#endif // CHROME_BROWSER_SPELLCHECKER_H_
diff --git a/chrome/browser/spellchecker_common.h b/chrome/browser/spellchecker_common.h
deleted file mode 100644
index 4d393ab..0000000
--- a/chrome/browser/spellchecker_common.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_SPELLCHECKER_COMMON_H_
-#define CHROME_BROWSER_SPELLCHECKER_COMMON_H_
-
-#include <string>
-#include <vector>
-
-// Some constants and typedefs that are common to all spellchecker
-// files/classes/backends/platforms/whatever.
-
-static const int kMaxSuggestions = 5; // Max number of dictionary suggestions.
-
-static const int kMaxAutoCorrectWordSize = 8;
-
-#endif // CHROME_BROWSER_SPELLCHECKER_COMMON_H_
-
diff --git a/chrome/browser/spellchecker_linux.cc b/chrome/browser/spellchecker_linux.cc
index 9f0f144..8637edc 100644
--- a/chrome/browser/spellchecker_linux.cc
+++ b/chrome/browser/spellchecker_linux.cc
@@ -5,14 +5,13 @@
// If linux ever gains a platform specific spellchecker, it will be
// implemented here.
-#include "base/string16.h"
-#include "chrome/browser/spellchecker_common.h"
+#include "spellchecker_platform_engine.h"
namespace SpellCheckerPlatform {
bool SpellCheckerAvailable() {
// As of Summer 2009, there is no commonly accepted platform spellchecker
- // for linux, so we'll return false here.
+ // for Linux, so we'll return false here.
return false;
}
@@ -54,7 +53,7 @@ void RemoveWord(const string16& word) {}
int GetDocumentTag() { return 0; }
-void IgnoreWord(const std::string& word) {}
+void IgnoreWord(const string16& word) {}
void CloseDocumentWithTag(int tag) {}
diff --git a/chrome/browser/spellchecker_mac.mm b/chrome/browser/spellchecker_mac.mm
index 72c06e1..70db304 100644
--- a/chrome/browser/spellchecker_mac.mm
+++ b/chrome/browser/spellchecker_mac.mm
@@ -5,14 +5,15 @@
// This file implements the interface defined in spellchecker_platform_engine.h
// for the OS X platform.
+#include "chrome/browser/spellchecker_platform_engine.h"
+
#import <Cocoa/Cocoa.h>
#include "base/logging.h"
#include "base/time.h"
#include "base/histogram.h"
#include "base/sys_string_conversions.h"
-#include "chrome/browser/spellchecker_common.h"
-#include "chrome/browser/spellchecker_platform_engine.h"
+#include "chrome/common/spellcheck_common.h"
using base::TimeTicks;
namespace {
@@ -175,7 +176,7 @@ void FillSuggestionList(const string16& wrong_word,
TimeTicks::Now() - begin_time);
for (int i = 0; i < static_cast<int>([guesses count]); i++) {
- if (i < kMaxSuggestions) {
+ if (i < SpellCheckCommon::kMaxSuggestions) {
optional_suggestions->push_back(base::SysNSStringToUTF16(
[guesses objectAtIndex:i]));
}
diff --git a/chrome/browser/spellchecker_platform_engine.h b/chrome/browser/spellchecker_platform_engine.h
index d9a0588..5762ab2 100644
--- a/chrome/browser/spellchecker_platform_engine.h
+++ b/chrome/browser/spellchecker_platform_engine.h
@@ -12,7 +12,6 @@
#include <vector>
#include "base/string16.h"
-#include "chrome/browser/spellchecker_common.h"
namespace SpellCheckerPlatform {
diff --git a/chrome/browser/spellchecker_platform_engine_unittest.cc b/chrome/browser/spellchecker_platform_engine_unittest.cc
new file mode 100644
index 0000000..d4bf050
--- /dev/null
+++ b/chrome/browser/spellchecker_platform_engine_unittest.cc
@@ -0,0 +1,393 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/string_util.h"
+#include "chrome/browser/spellchecker_platform_engine.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if defined(OS_MACOSX)
+#define MAYBE_IgnoreWords_EN_US IgnoreWords_EN_US
+#else
+#define MAYBE_IgnoreWords_EN_US DISABLED_IgnoreWords_EN_US
+#endif
+
+// Tests that words are properly ignored. Currently only enabled on OS X as it
+// is the only platform to support ignoring words. Note that in this test, we
+// supply a non-zero doc_tag, in order to test that ignored words are matched to
+// the correct document.
+TEST(PlatformSpellCheckTest, MAYBE_IgnoreWords_EN_US) {
+ static const struct {
+ // A misspelled word.
+ const char* input;
+ bool input_result;
+ } kTestCases[] = {
+ {"teh"},
+ {"moer"},
+ {"watre"},
+ {"noen"},
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
+ string16 word(UTF8ToUTF16(kTestCases[i].input));
+ std::vector<string16> suggestions;
+ size_t input_length = 0;
+ if (kTestCases[i].input != NULL) {
+ input_length = word.length();
+ }
+
+ int doc_tag = SpellCheckerPlatform::GetDocumentTag();
+ bool result = SpellCheckerPlatform::CheckSpelling(word, doc_tag);
+
+ // The word should show up as misspelled.
+ EXPECT_EQ(kTestCases[i].input_result, result);
+
+ // Ignore the word.
+ SpellCheckerPlatform::IgnoreWord(word);
+
+ // Spellcheck again.
+ result = SpellCheckerPlatform::CheckSpelling(word, doc_tag);
+
+ // The word should now show up as correctly spelled.
+ EXPECT_EQ(!(kTestCases[i].input_result), result);
+
+ // Close the docuemnt. Any words that we had previously ignored should no
+ // longer be ignored and thus should show up as misspelled.
+ SpellCheckerPlatform::CloseDocumentWithTag(doc_tag);
+
+ // Spellcheck one more time.
+ result = SpellCheckerPlatform::CheckSpelling(word, doc_tag);
+
+ // The word should now show be spelled wrong again
+ EXPECT_EQ(kTestCases[i].input_result, result);
+ }
+} // Test IgnoreWords_EN_US
+
+#if defined(OS_MACOSX)
+TEST(PlatformSpellCheckTest, SpellCheckSuggestions_EN_US) {
+ static const struct {
+ // A string to be tested.
+ const wchar_t* input;
+
+ // A suggested word that should occur.
+ const wchar_t* suggested_word;
+ } kTestCases[] = { // A valid English word with a preceding whitespace
+ // We need to have separate test cases here, since hunspell and the OS X
+ // spellchecking service occasionally differ on what they consider a valid
+ // suggestion for a given word, although these lists could likely be
+ // integrated somewhat. The test cases for non-Mac are in
+ // chrome/renderer/spellcheck_unittest.cc
+ // These words come from the wikipedia page of the most commonly
+ // misspelled words in english.
+ // (http://en.wikipedia.org/wiki/Commonly_misspelled_words).
+ {L"absense", L"absence"},
+ {L"acceptible", L"acceptable"},
+ {L"accidentaly", L"accidentally"},
+ {L"accomodate", L"accommodate"},
+ {L"acheive", L"achieve"},
+ {L"acknowlege", L"acknowledge"},
+ {L"acquaintence", L"acquaintance"},
+ {L"aquire", L"acquire"},
+ {L"aquit", L"acquit"},
+ {L"acrage", L"acreage"},
+ {L"adress", L"address"},
+ {L"adultary", L"adultery"},
+ {L"advertize", L"advertise"},
+ {L"adviseable", L"advisable"},
+ {L"agression", L"aggression"},
+ {L"alchohol", L"alcohol"},
+ {L"alege", L"allege"},
+ {L"allegaince", L"allegiance"},
+ {L"allmost", L"almost"},
+ // Ideally, this test should pass. It works in firefox, but not in hunspell
+ // or OS X.
+ // {L"alot", L"a lot"},
+ {L"amatuer", L"amateur"},
+ {L"ammend", L"amend"},
+ {L"amung", L"among"},
+ {L"anually", L"annually"},
+ {L"apparant", L"apparent"},
+ {L"artic", L"arctic"},
+ {L"arguement", L"argument"},
+ {L"athiest", L"atheist"},
+ {L"athelete", L"athlete"},
+ {L"avrage", L"average"},
+ {L"awfull", L"awful"},
+ {L"ballance", L"balance"},
+ {L"basicly", L"basically"},
+ {L"becuase", L"because"},
+ {L"becomeing", L"becoming"},
+ {L"befor", L"before"},
+ {L"begining", L"beginning"},
+ {L"beleive", L"believe"},
+ {L"bellweather", L"bellwether"},
+ {L"benifit", L"benefit"},
+ {L"bouy", L"buoy"},
+ {L"briliant", L"brilliant"},
+ {L"burgler", L"burglar"},
+ {L"camoflage", L"camouflage"},
+ {L"carrer", L"career"},
+ {L"carefull", L"careful"},
+ {L"Carribean", L"Caribbean"},
+ {L"catagory", L"category"},
+ {L"cauhgt", L"caught"},
+ {L"cieling", L"ceiling"},
+ {L"cemetary", L"cemetery"},
+ {L"certin", L"certain"},
+ {L"changable", L"changeable"},
+ {L"cheif", L"chief"},
+ {L"citezen", L"citizen"},
+ {L"collaegue", L"colleague"},
+ {L"colum", L"column"},
+ {L"comming", L"coming"},
+ {L"commited", L"committed"},
+ {L"compitition", L"competition"},
+ {L"conceed", L"concede"},
+ {L"congradulate", L"congratulate"},
+ {L"consciencious", L"conscientious"},
+ {L"concious", L"conscious"},
+ {L"concensus", L"consensus"},
+ {L"contraversy", L"controversy"},
+ {L"conveniance", L"convenience"},
+ {L"critecize", L"criticize"},
+ {L"dacquiri", L"daiquiri"},
+ {L"decieve", L"deceive"},
+ {L"dicide", L"decide"},
+ {L"definate", L"definite"},
+ {L"definitly", L"definitely"},
+ {L"deposite", L"deposit"},
+ {L"desparate", L"desperate"},
+ {L"develope", L"develop"},
+ {L"diffrence", L"difference"},
+ {L"dilema", L"dilemma"},
+ {L"disapear", L"disappear"},
+ {L"disapoint", L"disappoint"},
+ {L"disasterous", L"disastrous"},
+ {L"disipline", L"discipline"},
+ {L"drunkeness", L"drunkenness"},
+ {L"dumbell", L"dumbbell"},
+ {L"durring", L"during"},
+ {L"easely", L"easily"},
+ {L"eigth", L"eight"},
+ {L"embarass", L"embarrass"},
+ {L"enviroment", L"environment"},
+ {L"equiped", L"equipped"},
+ {L"equiptment", L"equipment"},
+ {L"exagerate", L"exaggerate"},
+ {L"excede", L"exceed"},
+ {L"exellent", L"excellent"},
+ {L"exsept", L"except"},
+ {L"exercize", L"exercise"},
+ {L"exilerate", L"exhilarate"},
+ {L"existance", L"existence"},
+ {L"experiance", L"experience"},
+ {L"experament", L"experiment"},
+ {L"explaination", L"explanation"},
+ {L"extreem", L"extreme"},
+ {L"familier", L"familiar"},
+ {L"facinating", L"fascinating"},
+ {L"firey", L"fiery"},
+ {L"finaly", L"finally"},
+ {L"flourescent", L"fluorescent"},
+ {L"foriegn", L"foreign"},
+ {L"fourty", L"forty"},
+ {L"foreward", L"forward"},
+ {L"freind", L"friend"},
+ {L"fullfil", L"fulfill"},
+ {L"fundemental", L"fundamental"},
+ {L"guage", L"gauge"},
+ {L"generaly", L"generally"},
+ {L"goverment", L"government"},
+ {L"grammer", L"grammar"},
+ {L"gratefull", L"grateful"},
+ {L"garantee", L"guarantee"},
+ {L"guidence", L"guidance"},
+ {L"happyness", L"happiness"},
+ {L"harrass", L"harass"},
+ {L"heighth", L"height"},
+ {L"heirarchy", L"hierarchy"},
+ {L"humerous", L"humorous"},
+ {L"hygene", L"hygiene"},
+ {L"hipocrit", L"hypocrite"},
+ {L"idenity", L"identity"},
+ {L"ignorence", L"ignorance"},
+ {L"imaginery", L"imaginary"},
+ {L"immitate", L"imitate"},
+ {L"immitation", L"imitation"},
+ {L"imediately", L"immediately"},
+ {L"incidently", L"incidentally"},
+ {L"independant", L"independent"},
+ {L"indispensible", L"indispensable"},
+ {L"innoculate", L"inoculate"},
+ {L"inteligence", L"intelligence"},
+ {L"intresting", L"interesting"},
+ {L"interuption", L"interruption"},
+ {L"irrelevent", L"irrelevant"},
+ {L"irritible", L"irritable"},
+ {L"iland", L"island"},
+ {L"jellous", L"jealous"},
+ {L"knowlege", L"knowledge"},
+ {L"labratory", L"laboratory"},
+ {L"liesure", L"leisure"},
+ {L"lenght", L"length"},
+ {L"liason", L"liaison"},
+ {L"libary", L"library"},
+ {L"lisence", L"license"},
+ {L"lonelyness", L"loneliness"},
+ {L"lieing", L"lying"},
+ {L"maintenence", L"maintenance"},
+ {L"manuever", L"maneuver"},
+ {L"marrige", L"marriage"},
+ {L"mathmatics", L"mathematics"},
+ {L"medcine", L"medicine"},
+ {L"medeval", L"medieval"},
+ {L"momento", L"memento"},
+ {L"millenium", L"millennium"},
+ {L"miniture", L"miniature"},
+ {L"minite", L"minute"},
+ {L"mischevous", L"mischievous"},
+ {L"mispell", L"misspell"},
+ // Maybe this one should pass, as it works in hunspell, but not in firefox.
+ // {L"misterius", L"mysterious"},
+ {L"naturaly", L"naturally"},
+ {L"neccessary", L"necessary"},
+ {L"neice", L"niece"},
+ {L"nieghbor", L"neighbor"},
+ {L"nieghbour", L"neighbor"},
+ {L"niether", L"neither"},
+ {L"noticable", L"noticeable"},
+ {L"occassion", L"occasion"},
+ {L"occasionaly", L"occasionally"},
+ {L"occurrance", L"occurrence"},
+ {L"occured", L"occurred"},
+ {L"oficial", L"official"},
+ {L"offen", L"often"},
+ {L"ommision", L"omission"},
+ {L"oprate", L"operate"},
+ {L"oppurtunity", L"opportunity"},
+ {L"orignal", L"original"},
+ {L"outragous", L"outrageous"},
+ {L"parrallel", L"parallel"},
+ {L"parliment", L"parliament"},
+ {L"particurly", L"particularly"},
+ {L"passtime", L"pastime"},
+ {L"peculier", L"peculiar"},
+ {L"percieve", L"perceive"},
+ {L"pernament", L"permanent"},
+ {L"perseverence", L"perseverance"},
+ {L"personaly", L"personally"},
+ {L"personell", L"personnel"},
+ {L"persaude", L"persuade"},
+ {L"pichure", L"picture"},
+ {L"peice", L"piece"},
+ {L"plagerize", L"plagiarize"},
+ {L"playright", L"playwright"},
+ {L"plesant", L"pleasant"},
+ {L"pollitical", L"political"},
+ {L"posession", L"possession"},
+ {L"potatos", L"potatoes"},
+ {L"practicle", L"practical"},
+ {L"preceed", L"precede"},
+ {L"predjudice", L"prejudice"},
+ {L"presance", L"presence"},
+ {L"privelege", L"privilege"},
+ // This one should probably work. It does in FF and Hunspell.
+ // {L"probly", L"probably"},
+ {L"proffesional", L"professional"},
+ {L"professer", L"professor"},
+ {L"promiss", L"promise"},
+ {L"pronounciation", L"pronunciation"},
+ {L"prufe", L"proof"},
+ {L"psycology", L"psychology"},
+ {L"publically", L"publicly"},
+ {L"quanity", L"quantity"},
+ {L"quarentine", L"quarantine"},
+ {L"questionaire", L"questionnaire"},
+ {L"readible", L"readable"},
+ {L"realy", L"really"},
+ {L"recieve", L"receive"},
+ {L"reciept", L"receipt"},
+ {L"reconize", L"recognize"},
+ {L"recomend", L"recommend"},
+ {L"refered", L"referred"},
+ {L"referance", L"reference"},
+ {L"relevent", L"relevant"},
+ {L"religous", L"religious"},
+ {L"repitition", L"repetition"},
+ {L"restarant", L"restaurant"},
+ {L"rythm", L"rhythm"},
+ {L"rediculous", L"ridiculous"},
+ {L"sacrefice", L"sacrifice"},
+ {L"saftey", L"safety"},
+ {L"sissors", L"scissors"},
+ {L"secratary", L"secretary"},
+ {L"sieze", L"seize"},
+ {L"seperate", L"separate"},
+ {L"sargent", L"sergeant"},
+ {L"shineing", L"shining"},
+ {L"similer", L"similar"},
+ {L"sinceerly", L"sincerely"},
+ {L"speach", L"speech"},
+ {L"stoping", L"stopping"},
+ {L"strenght", L"strength"},
+ {L"succede", L"succeed"},
+ {L"succesful", L"successful"},
+ {L"supercede", L"supersede"},
+ {L"surelly", L"surely"},
+ {L"suprise", L"surprise"},
+ {L"temperture", L"temperature"},
+ {L"temprary", L"temporary"},
+ {L"tomatos", L"tomatoes"},
+ {L"tommorrow", L"tomorrow"},
+ {L"tounge", L"tongue"},
+ {L"truely", L"truly"},
+ {L"twelth", L"twelfth"},
+ {L"tyrany", L"tyranny"},
+ {L"underate", L"underrate"},
+ {L"untill", L"until"},
+ {L"unuseual", L"unusual"},
+ {L"upholstry", L"upholstery"},
+ {L"usible", L"usable"},
+ {L"useing", L"using"},
+ {L"usualy", L"usually"},
+ {L"vaccuum", L"vacuum"},
+ {L"vegatarian", L"vegetarian"},
+ {L"vehical", L"vehicle"},
+ {L"visious", L"vicious"},
+ {L"villege", L"village"},
+ {L"wierd", L"weird"},
+ {L"wellcome", L"welcome"},
+ {L"wellfare", L"welfare"},
+ {L"wilfull", L"willful"},
+ {L"withold", L"withhold"},
+ {L"writting", L"writing"},
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
+ std::vector<string16> suggestions;
+ size_t input_length = 0;
+ if (kTestCases[i].input != NULL) {
+ input_length = wcslen(kTestCases[i].input);
+ }
+ bool result = SpellCheckerPlatform::CheckSpelling(
+ WideToUTF16(kTestCases[i].input), 0);
+ EXPECT_FALSE(result);
+
+ SpellCheckerPlatform::FillSuggestionList(WideToUTF16(kTestCases[i].input),
+ &suggestions);
+
+ // Check if the suggested words occur.
+ bool suggested_word_is_present = false;
+ for (int j=0; j < static_cast<int>(suggestions.size()); j++) {
+ if (suggestions.at(j).compare(WideToUTF16(kTestCases[i].suggested_word))
+ == 0) {
+ suggested_word_is_present = true;
+ break;
+ }
+ }
+
+ EXPECT_TRUE(suggested_word_is_present);
+ }
+}
+
+#endif // defined(OS_MACOSX)
diff --git a/chrome/browser/spellchecker_win.cc b/chrome/browser/spellchecker_win.cc
index cee7a98..1f318a0 100644
--- a/chrome/browser/spellchecker_win.cc
+++ b/chrome/browser/spellchecker_win.cc
@@ -7,8 +7,6 @@
#include "chrome/browser/spellchecker_platform_engine.h"
-#include "chrome/browser/spellchecker_common.h"
-
namespace SpellCheckerPlatform {
bool SpellCheckerAvailable() {
diff --git a/chrome/browser/tab_contents/render_view_context_menu.cc b/chrome/browser/tab_contents/render_view_context_menu.cc
index 9f5665c6..841e770 100644
--- a/chrome/browser/tab_contents/render_view_context_menu.cc
+++ b/chrome/browser/tab_contents/render_view_context_menu.cc
@@ -20,15 +20,13 @@
#include "chrome/browser/profile.h"
#include "chrome/browser/search_versus_navigate_classifier.h"
#include "chrome/browser/search_engines/template_url_model.h"
-#if defined(SPELLCHECKER_IN_RENDERER)
#include "chrome/browser/spellcheck_host.h"
-#endif
-#include "chrome/browser/spellchecker.h"
#include "chrome/browser/spellchecker_platform_engine.h"
#include "chrome/browser/tab_contents/navigation_entry.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/platform_util.h"
+#include "chrome/common/pref_names.h"
#include "chrome/common/pref_service.h"
#include "chrome/common/url_constants.h"
#include "grit/generated_resources.h"
@@ -273,7 +271,7 @@ void RenderViewContextMenu::AppendEditableItems() {
// Add Spell Check languages to sub menu.
std::vector<std::string> spellcheck_languages;
- SpellChecker::GetSpellCheckLanguages(profile_,
+ SpellCheckHost::GetSpellCheckLanguages(profile_,
&spellcheck_languages);
DCHECK(spellcheck_languages.size() <
IDC_SPELLCHECK_LANGUAGES_LAST - IDC_SPELLCHECK_LANGUAGES_FIRST);
@@ -490,7 +488,7 @@ bool RenderViewContextMenu::ItemIsChecked(int id) const {
return false;
std::vector<std::string> languages;
- return SpellChecker::GetSpellCheckLanguages(profile_, &languages) ==
+ return SpellCheckHost::GetSpellCheckLanguages(profile_, &languages) ==
(id - IDC_SPELLCHECK_LANGUAGES_FIRST);
}
@@ -500,7 +498,7 @@ void RenderViewContextMenu::ExecuteItemCommand(int id) {
id < IDC_SPELLCHECK_LANGUAGES_LAST) {
const size_t language_number = id - IDC_SPELLCHECK_LANGUAGES_FIRST;
std::vector<std::string> languages;
- SpellChecker::GetSpellCheckLanguages(profile_, &languages);
+ SpellCheckHost::GetSpellCheckLanguages(profile_, &languages);
if (language_number < languages.size()) {
StringPrefMember dictionary_language;
dictionary_language.Init(prefs::kSpellCheckDictionary,
@@ -724,17 +722,13 @@ void RenderViewContextMenu::ExecuteItemCommand(int id) {
source_tab_contents_->render_view_host()->ToggleSpellCheck();
break;
case IDS_CONTENT_CONTEXT_ADD_TO_DICTIONARY: {
-#if defined(SPELLCHECKER_IN_RENDERER)
SpellCheckHost* spellcheck_host = profile_->GetSpellCheckHost();
if (!spellcheck_host) {
NOTREACHED();
break;
}
spellcheck_host->AddWord(UTF16ToUTF8(params_.misspelled_word));
-#else
- source_tab_contents_->render_view_host()->AddToDictionary(
- params_.misspelled_word);
-#endif
+ SpellCheckerPlatform::AddWord(params_.misspelled_word);
break;
}
diff --git a/chrome/browser/views/options/languages_page_view.cc b/chrome/browser/views/options/languages_page_view.cc
index d7c7604..542c66f 100644
--- a/chrome/browser/views/options/languages_page_view.cc
+++ b/chrome/browser/views/options/languages_page_view.cc
@@ -1,6 +1,7 @@
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+
#include <windows.h>
#include <shlobj.h>
#include <vsstyle.h>
@@ -21,11 +22,11 @@
#include "chrome/browser/language_combobox_model.h"
#include "chrome/browser/language_order_table_model.h"
#include "chrome/browser/shell_dialogs.h"
-#include "chrome/browser/spellchecker.h"
#include "chrome/browser/views/restart_message_box.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/pref_service.h"
+#include "chrome/common/spellcheck_common.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
@@ -350,7 +351,7 @@ void LanguagesPageView::InitControlLayout() {
// Determine Locale Codes.
std::vector<std::string> spell_check_languages;
- SpellChecker::SpellCheckLanguages(&spell_check_languages);
+ SpellCheckCommon::SpellCheckLanguages(&spell_check_languages);
dictionary_language_model_.reset(new LanguageComboboxModel(profile(),
spell_check_languages));
change_dictionary_language_combobox_ =
@@ -432,7 +433,7 @@ void LanguagesPageView::NotifyPrefChanged(const std::wstring* pref_name) {
const std::string& lang_region = WideToASCII(
dictionary_language_.GetValue());
dictionary_language_.SetValue(ASCIIToWide(
- SpellChecker::GetLanguageFromLanguageRegion(lang_region)));
+ SpellCheckCommon::GetLanguageFromLanguageRegion(lang_region)));
index = dictionary_language_model_->GetSelectedLanguageIndex(
prefs::kSpellCheckDictionary);
}
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 47ba1d3..e37fe8e 100755
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -682,6 +682,8 @@
'common/sandbox_init_wrapper_win.cc',
'common/sandbox_mac.h',
'common/sandbox_mac.mm',
+ 'common/spellcheck_common.cc',
+ 'common/spellcheck_common.h',
'common/security_filter_peer.cc',
'common/security_filter_peer.h',
'common/nacl_messages.h',
@@ -2138,10 +2140,6 @@
'browser/shell_integration_win.cc',
'browser/spellcheck_host.cc',
'browser/spellcheck_host.h',
- 'browser/spellcheck_worditerator.cc',
- 'browser/spellcheck_worditerator.h',
- 'browser/spellchecker.cc',
- 'browser/spellchecker.h',
'browser/spellchecker_common.h',
'browser/spellchecker_linux.cc',
'browser/spellchecker_mac.mm',
@@ -3437,15 +3435,6 @@
'../third_party/tcmalloc/tcmalloc.gyp:tcmalloc',
],
},],
- # Mac-specific rules.
- ['OS=="mac"', {
- 'sources!': [
- 'renderer/spellchecker/spellcheck.cc',
- 'renderer/spellchecker/spellcheck.h',
- 'renderer/spellchecker/spellcheck_worditerator.cc',
- 'renderer/spellchecker/spellcheck_worditerator.h',
- ],
- },],
],
},
{
@@ -4750,7 +4739,7 @@
'browser/sessions/session_service_unittest.cc',
'browser/sessions/tab_restore_service_unittest.cc',
'browser/shell_integration_unittest.cc',
- 'browser/spellcheck_unittest.cc',
+ 'browser/spellchecker_platform_engine_unittest.cc',
'browser/ssl/ssl_host_state_unittest.cc',
'browser/sync/glue/bookmark_model_worker_unittest.cc',
'browser/sync/glue/http_bridge_unittest.cc',
@@ -4808,6 +4797,7 @@
'renderer/render_view_unittest_mac.mm',
'renderer/render_widget_unittest.cc',
'renderer/renderer_main_unittest.cc',
+ 'renderer/spellchecker/spellcheck_unittest.cc',
'test/browser_with_test_window_test.cc',
'test/browser_with_test_window_test.h',
'test/file_test_utils.cc',
diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h
index 781e252..c162cfc 100644
--- a/chrome/common/notification_type.h
+++ b/chrome/common/notification_type.h
@@ -544,12 +544,6 @@ class NotificationType {
// Profile, and the details aren't used.
BOOKMARK_MODEL_LOADED,
- // Sent when the spellchecker object changes. Note that this is not sent
- // the first time the spellchecker gets initialized. The source is the
- // profile, the details is SpellcheckerReinitializedDetails defined in
- // profile.
- SPELLCHECKER_REINITIALIZED,
-
// Sent when SpellCheckHost has been reloaded. The source is the profile,
// the details are NoDetails.
SPELLCHECK_HOST_REINITIALIZED,
@@ -558,6 +552,12 @@ class NotificationType {
// is the SpellCheckHost, the details are NoDetails.
SPELLCHECK_WORD_ADDED,
+ // Sent by the profile when the automatic spell correction setting has been
+ // toggled. It exists as a notification rather than just letting interested
+ // parties listen for the pref change because some objects may outlive the
+ // profile. Source is profile, details is NoDetails.
+ SPELLCHECK_AUTOSPELL_TOGGLED,
+
// Sent when the bookmark bubble is shown for a particular URL. The source
// is the profile, the details the URL.
BOOKMARK_BUBBLE_SHOWN,
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index b883e87..ec9e869 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -833,7 +833,6 @@ IPC_BEGIN_MESSAGES(View)
IPC_MESSAGE_CONTROL1(ViewMsg_SocketStream_Closed,
int /* socket_id */)
-#if defined(SPELLCHECKER_IN_RENDERER)
// SpellChecker messages.
// Passes some initialization params to the renderer's spellchecker. This can
@@ -853,7 +852,6 @@ IPC_BEGIN_MESSAGES(View)
// Toggle the auto spell correct functionality.
IPC_MESSAGE_CONTROL1(ViewMsg_SpellChecker_EnableAutoSpellCorrect,
bool /* enable */)
-#endif
IPC_END_MESSAGES(View)
@@ -1130,11 +1128,6 @@ IPC_BEGIN_MESSAGES(ViewHost)
IPC_MESSAGE_ROUTED1(ViewHostMsg_UpdateSpellingPanelWithMisspelledWord,
string16 /* the word to update the panel with */)
- IPC_SYNC_MESSAGE_ROUTED2_1(ViewHostMsg_GetAutoCorrectWord,
- string16 /* word to check */,
- int /* tag for the document containg the word */,
- string16 /* autocorrected word */)
-
// Initiate a download based on user actions like 'ALT+click'.
IPC_MESSAGE_ROUTED2(ViewHostMsg_DownloadUrl,
GURL /* url */,
@@ -2037,11 +2030,19 @@ IPC_BEGIN_MESSAGES(ViewHost)
GURL /* URL of requestor */,
std::string /* signed public key and challenge */)
-#if defined(SPELLCHECKER_IN_RENDERER)
// The renderer has tried to spell check a word, but couldn't because no
// dictionary was available to load. Request that the browser find an
// appropriate dictionary and return it.
IPC_MESSAGE_CONTROL0(ViewHostMsg_SpellChecker_RequestDictionary)
-#endif
+
+ IPC_SYNC_MESSAGE_CONTROL2_1(ViewHostMsg_SpellChecker_PlatformCheckSpelling,
+ string16 /* word */,
+ int /* document tag */,
+ bool /* correct */)
+
+ IPC_SYNC_MESSAGE_CONTROL1_1(
+ ViewHostMsg_SpellChecker_PlatformFillSuggestionList,
+ string16 /* word */,
+ std::vector<string16> /* suggestions */)
IPC_END_MESSAGES(ViewHost)
diff --git a/chrome/common/spellcheck_common.cc b/chrome/common/spellcheck_common.cc
new file mode 100644
index 0000000..e06d2eb
--- /dev/null
+++ b/chrome/common/spellcheck_common.cc
@@ -0,0 +1,174 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/spellcheck_common.h"
+
+#include "base/file_path.h"
+
+namespace SpellCheckCommon {
+
+static const struct {
+ // The language.
+ const char* language;
+
+ // The corresponding language and region, used by the dictionaries.
+ const char* language_region;
+} g_supported_spellchecker_languages[] = {
+ // Several languages are not to be included in the spellchecker list:
+ // th-TH, hu-HU, bg-BG, uk-UA
+ {"ca", "ca-ES"},
+ {"cs", "cs-CZ"},
+ {"da", "da-DK"},
+ {"de", "de-DE"},
+ {"el", "el-GR"},
+ {"en-AU", "en-AU"},
+ {"en-GB", "en-GB"},
+ {"en-US", "en-US"},
+ {"es", "es-ES"},
+ {"et", "et-EE"},
+ {"fr", "fr-FR"},
+ {"he", "he-IL"},
+ {"hi", "hi-IN"},
+ {"hr", "hr-HR"},
+ {"id", "id-ID"},
+ {"it", "it-IT"},
+ {"lt", "lt-LT"},
+ {"lv", "lv-LV"},
+ {"nb", "nb-NO"},
+ {"nl", "nl-NL"},
+ {"pl", "pl-PL"},
+ {"pt-BR", "pt-BR"},
+ {"pt-PT", "pt-PT"},
+ {"ro", "ro-RO"},
+ {"ru", "ru-RU"},
+ {"sk", "sk-SK"},
+ {"sl", "sl-SI"},
+ {"sv", "sv-SE"},
+ {"tr", "tr-TR"},
+ {"vi", "vi-VN"},
+};
+
+// This function returns the language-region version of language name.
+// e.g. returns hi-IN for hi.
+std::string GetSpellCheckLanguageRegion(const std::string& input_language) {
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(g_supported_spellchecker_languages);
+ ++i) {
+ if (g_supported_spellchecker_languages[i].language == input_language) {
+ return std::string(
+ g_supported_spellchecker_languages[i].language_region);
+ }
+ }
+
+ return input_language;
+}
+
+FilePath GetVersionedFileName(const std::string& input_language,
+ const FilePath& dict_dir) {
+ // The default dictionary version is 1-2. These versions have been augmented
+ // with additional words found by the translation team.
+ static const char kDefaultVersionString[] = "-1-2";
+
+ // The following dictionaries have either not been augmented with additional
+ // words (version 1-1) or have new words, as well as an upgraded dictionary
+ // as of Feb 2009 (version 1-3).
+ static const struct {
+ // The language input.
+ const char* language;
+
+ // The corresponding version.
+ const char* version;
+ } special_version_string[] = {
+ {"en-AU", "-1-1"},
+ {"en-GB", "-1-1"},
+ {"es-ES", "-1-1"},
+ {"nl-NL", "-1-1"},
+ {"ru-RU", "-1-1"},
+ {"sv-SE", "-1-1"},
+ {"he-IL", "-1-1"},
+ {"el-GR", "-1-1"},
+ {"hi-IN", "-1-1"},
+ {"tr-TR", "-1-1"},
+ {"et-EE", "-1-1"},
+ {"fr-FR", "-1-4"}, // To fix a crash, fr dictionary was updated to 1.4.
+ {"lt-LT", "-1-3"},
+ {"pl-PL", "-1-3"}
+ };
+
+ // Generate the bdict file name using default version string or special
+ // version string, depending on the language.
+ std::string language = GetSpellCheckLanguageRegion(input_language);
+ std::string versioned_bdict_file_name(language + kDefaultVersionString +
+ ".bdic");
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(special_version_string); ++i) {
+ if (language == special_version_string[i].language) {
+ versioned_bdict_file_name =
+ language + special_version_string[i].version + ".bdic";
+ break;
+ }
+ }
+
+ return dict_dir.AppendASCII(versioned_bdict_file_name);
+}
+
+std::string GetCorrespondingSpellCheckLanguage(const std::string& language) {
+ // Look for exact match in the Spell Check language list.
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(g_supported_spellchecker_languages);
+ ++i) {
+ // First look for exact match in the language region of the list.
+ std::string spellcheck_language(
+ g_supported_spellchecker_languages[i].language);
+ if (spellcheck_language == language)
+ return language;
+
+ // Next, look for exact match in the language_region part of the list.
+ std::string spellcheck_language_region(
+ g_supported_spellchecker_languages[i].language_region);
+ if (spellcheck_language_region == language)
+ return g_supported_spellchecker_languages[i].language;
+ }
+
+ // Look for a match by comparing only language parts. All the 'en-RR'
+ // except for 'en-GB' exactly matched in the above loop, will match
+ // 'en-US'. This is not ideal because 'en-ZA', 'en-NZ' had
+ // better be matched with 'en-GB'. This does not handle cases like
+ // 'az-Latn-AZ' vs 'az-Arab-AZ', either, but we don't use 3-part
+ // locale ids with a script code in the middle, yet.
+ // TODO(jungshik): Add a better fallback.
+ std::string language_part(language, 0, language.find('-'));
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(g_supported_spellchecker_languages);
+ ++i) {
+ std::string spellcheck_language(
+ g_supported_spellchecker_languages[i].language_region);
+ if (spellcheck_language.substr(0, spellcheck_language.find('-')) ==
+ language_part) {
+ return spellcheck_language;
+ }
+ }
+
+ // No match found - return blank.
+ return std::string();
+}
+
+
+void SpellCheckLanguages(std::vector<std::string>* languages) {
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(g_supported_spellchecker_languages);
+ ++i) {
+ languages->push_back(g_supported_spellchecker_languages[i].language);
+ }
+}
+
+
+std::string GetLanguageFromLanguageRegion(std::string input_language) {
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(g_supported_spellchecker_languages);
+ ++i) {
+ std::string language(
+ g_supported_spellchecker_languages[i].language_region);
+ if (language == input_language)
+ return std::string(g_supported_spellchecker_languages[i].language);
+ }
+
+ return input_language;
+}
+
+} // namespace SpellCheckCommon
diff --git a/chrome/common/spellcheck_common.h b/chrome/common/spellcheck_common.h
new file mode 100644
index 0000000..5c2569e
--- /dev/null
+++ b/chrome/common/spellcheck_common.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_SPELLCHECK_COMMON_H_
+#define CHROME_COMMON_SPELLCHECK_COMMON_H_
+
+#include <string>
+#include <vector>
+
+class FilePath;
+
+namespace SpellCheckCommon {
+
+// Max number of dictionary suggestions.
+static const int kMaxSuggestions = 5;
+
+static const int kMaxAutoCorrectWordSize = 8;
+
+FilePath GetVersionedFileName(const std::string& input_language,
+ const FilePath& dict_dir);
+
+std::string GetCorrespondingSpellCheckLanguage(const std::string& language);
+
+// Get SpellChecker supported languages.
+void SpellCheckLanguages(std::vector<std::string>* languages);
+
+
+// This function returns ll (language code) from ll-RR where 'RR' (region
+// code) is redundant. However, if the region code matters, it's preserved.
+// That is, it returns 'hi' and 'en-GB' for 'hi-IN' and 'en-GB' respectively.
+std::string GetLanguageFromLanguageRegion(std::string input_language);
+
+} // namespace SpellCheckCommon
+
+#endif // CHROME_COMMON_SPELLCHECK_COMMON_H_
diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc
index 7779a01..0ca3603 100644
--- a/chrome/renderer/render_thread.cc
+++ b/chrome/renderer/render_thread.cc
@@ -53,9 +53,7 @@
#include "chrome/renderer/renderer_webkitclient_impl.h"
#include "chrome/renderer/renderer_web_database_observer.h"
#include "chrome/renderer/socket_stream_dispatcher.h"
-#if defined(SPELLCHECKER_IN_RENDERER)
#include "chrome/renderer/spellchecker/spellcheck.h"
-#endif
#include "chrome/renderer/user_script_slave.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_platform_file.h"
@@ -158,9 +156,7 @@ void RenderThread::Init() {
AddFilter(devtools_agent_filter_.get());
db_message_filter_ = new DBMessageFilter();
AddFilter(db_message_filter_.get());
-#if defined(SPELLCHECKER_IN_RENDERER)
spellchecker_.reset(new SpellCheck());
-#endif
#if defined(OS_POSIX)
suicide_on_channel_error_filter_ = new SuicideOnChannelErrorFilter;
@@ -341,14 +337,12 @@ void RenderThread::OnControlMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(ViewMsg_SetIPCLoggingEnabled,
OnSetIPCLoggingEnabled)
#endif
-#if defined(SPELLCHECKER_IN_RENDERER)
IPC_MESSAGE_HANDLER(ViewMsg_SpellChecker_Init,
OnInitSpellChecker)
IPC_MESSAGE_HANDLER(ViewMsg_SpellChecker_WordAdded,
OnSpellCheckWordAdded)
IPC_MESSAGE_HANDLER(ViewMsg_SpellChecker_EnableAutoSpellCorrect,
OnSpellCheckEnableAutoSpellCorrect)
-#endif
IPC_END_MESSAGE_MAP()
}
@@ -455,12 +449,6 @@ void RenderThread::SetCacheMode(bool enabled) {
Send(new ViewHostMsg_SetCacheMode(enabled));
}
-#if defined(SPELLCHECKER_IN_RENDERER)
-void RenderThread::RequestSpellCheckDictionary() {
- Send(new ViewHostMsg_SpellChecker_RequestDictionary);
-}
-#endif
-
static void* CreateHistogram(
const char *name, int min, int max, size_t buckets) {
Histogram* histogram = new Histogram(name, min, max, buckets);
@@ -614,9 +602,7 @@ void RenderThread::OnExtensionMessageInvoke(const std::string& function_name,
}
void RenderThread::OnPurgeMemory() {
-#if defined(SPELLCHECKER_IN_RENDERER)
spellchecker_.reset(new SpellCheck());
-#endif
EnsureWebKitInitialized();
@@ -659,7 +645,6 @@ void RenderThread::OnPurgePluginListCache(bool reload_pages) {
plugin_refresh_allowed_ = true;
}
-#if defined(SPELLCHECKER_IN_RENDERER)
void RenderThread::OnInitSpellChecker(
IPC::PlatformFileForTransit bdict_file,
const std::vector<std::string>& custom_words,
@@ -677,4 +662,3 @@ void RenderThread::OnSpellCheckWordAdded(const std::string& word) {
void RenderThread::OnSpellCheckEnableAutoSpellCorrect(bool enable) {
spellchecker_->EnableAutoSpellCorrect(enable);
}
-#endif
diff --git a/chrome/renderer/render_thread.h b/chrome/renderer/render_thread.h
index 44dc6ab..305607a 100644
--- a/chrome/renderer/render_thread.h
+++ b/chrome/renderer/render_thread.h
@@ -124,11 +124,9 @@ class RenderThread : public RenderThreadBase,
return socket_stream_dispatcher_.get();
}
-#if defined(SPELLCHECKER_IN_RENDERER)
SpellCheck* spellchecker() const {
return spellchecker_.get();
}
-#endif
bool plugin_refresh_allowed() const { return plugin_refresh_allowed_; }
@@ -148,11 +146,6 @@ class RenderThread : public RenderThreadBase,
// Sends a message to the browser to enable or disable the disk cache.
void SetCacheMode(bool enabled);
-#if defined(SPELLCHECKER_IN_RENDERER)
- // Send a message to the browser to request a spellcheck dictionary.
- void RequestSpellCheckDictionary();
-#endif
-
private:
virtual void OnControlMessageReceived(const IPC::Message& msg);
@@ -200,14 +193,12 @@ class RenderThread : public RenderThreadBase,
void OnPurgeMemory();
void OnPurgePluginListCache(bool reload_pages);
-#if defined(SPELLCHECKER_IN_RENDERER)
void OnInitSpellChecker(IPC::PlatformFileForTransit bdict_file,
const std::vector<std::string>& custom_words,
const std::string& language,
bool auto_spell_correct);
void OnSpellCheckWordAdded(const std::string& word);
void OnSpellCheckEnableAutoSpellCorrect(bool enable);
-#endif
// Gather usage statistics from the in-memory cache and inform our host.
// These functions should be call periodically so that the host can make
@@ -232,9 +223,7 @@ class RenderThread : public RenderThreadBase,
scoped_ptr<WebKit::WebStorageEventDispatcher> dom_storage_event_dispatcher_;
scoped_ptr<SocketStreamDispatcher> socket_stream_dispatcher_;
scoped_ptr<RendererWebDatabaseObserver> renderer_web_database_observer_;
-#if defined(SPELLCHECKER_IN_RENDERER)
scoped_ptr<SpellCheck> spellchecker_;
-#endif
// Used on the renderer and IPC threads.
scoped_refptr<DBMessageFilter> db_message_filter_;
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 492823f..030222a 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -52,9 +52,7 @@
#include "chrome/renderer/plugin_channel_host.h"
#include "chrome/renderer/print_web_view_helper.h"
#include "chrome/renderer/render_process.h"
-#if defined(SPELLCHECKER_IN_RENDERER)
#include "chrome/renderer/spellchecker/spellcheck.h"
-#endif
#include "chrome/renderer/user_script_slave.h"
#include "chrome/renderer/visitedlink_slave.h"
#include "chrome/renderer/webplugin_delegate_pepper.h"
@@ -1503,19 +1501,14 @@ void RenderView::spellCheck(const WebString& text,
int& misspelled_length) {
EnsureDocumentTag();
-#if defined(SPELLCHECKER_IN_RENDERER)
string16 word(text);
RenderThread* thread = RenderThread::current();
// Will be NULL during unit tests.
if (thread) {
- RenderThread::current()->spellchecker()->SpellCheckWord(
+ thread->spellchecker()->SpellCheckWord(
word.c_str(), word.size(), document_tag_,
&misspelled_offset, &misspelled_length, NULL);
}
-#else
- Send(new ViewHostMsg_SpellCheck(routing_id_, text, document_tag_,
- &misspelled_offset, &misspelled_length));
-#endif
}
WebString RenderView::autoCorrectWord(const WebKit::WebString& word) {
@@ -1523,18 +1516,13 @@ WebString RenderView::autoCorrectWord(const WebKit::WebString& word) {
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kExperimentalSpellcheckerFeatures)) {
EnsureDocumentTag();
-#if defined(SPELLCHECKER_IN_RENDERER)
RenderThread* thread = RenderThread::current();
// Will be NULL during unit tests.
if (thread) {
autocorrect_word =
- RenderThread::current()->spellchecker()->GetAutoCorrectionWord(
+ thread->spellchecker()->GetAutoCorrectionWord(
word, document_tag_);
}
-#else
- Send(new ViewHostMsg_GetAutoCorrectWord(
- routing_id_, word, document_tag_, &autocorrect_word));
-#endif
}
return autocorrect_word;
}
@@ -1619,7 +1607,19 @@ bool RenderView::runModalBeforeUnloadDialog(
void RenderView::showContextMenu(
WebFrame* frame, const WebContextMenuData& data) {
- Send(new ViewHostMsg_ContextMenu(routing_id_, ContextMenuParams(data)));
+ ContextMenuParams params = ContextMenuParams(data);
+ if (!params.misspelled_word.empty() && RenderThread::current()) {
+ int misspelled_offset, misspelled_length;
+ bool misspelled = RenderThread::current()->spellchecker()->SpellCheckWord(
+ params.misspelled_word.c_str(), params.misspelled_word.size(),
+ document_tag_,
+ &misspelled_offset, &misspelled_length,
+ &params.dictionary_suggestions);
+ if (!misspelled)
+ params.misspelled_word.clear();
+ }
+
+ Send(new ViewHostMsg_ContextMenu(routing_id_, params));
}
void RenderView::setStatusText(const WebString& text) {
@@ -2547,7 +2547,7 @@ void RenderView::didChangeContentsSize(WebFrame* frame, const WebSize& size) {
// they're different.
int width = webview()->mainFrame()->contentsPreferredWidth();
int height = webview()->mainFrame()->documentElementScrollHeight();
-
+
if (width != preferred_size_.width() ||
height != preferred_size_.height()) {
preferred_size_.set_width(width);
diff --git a/chrome/renderer/spellchecker/spellcheck.cc b/chrome/renderer/spellchecker/spellcheck.cc
index 3b02b54..3fa20f8 100644
--- a/chrome/renderer/spellchecker/spellcheck.cc
+++ b/chrome/renderer/spellchecker/spellcheck.cc
@@ -7,18 +7,16 @@
#include "base/file_util.h"
#include "base/histogram.h"
#include "base/time.h"
+#include "chrome/common/render_messages.h"
+#include "chrome/common/spellcheck_common.h"
#include "chrome/renderer/render_thread.h"
#include "third_party/hunspell/src/hunspell/hunspell.hxx"
-static const int kMaxAutoCorrectWordSize = 8;
-static const int kMaxSuggestions = 5;
-
using base::TimeTicks;
SpellCheck::SpellCheck()
: file_(base::kInvalidPlatformFileValue),
auto_spell_correct_turned_on_(false),
- // TODO(estade): initialize this properly.
is_using_platform_spelling_engine_(false),
initialized_(false) {
// Wait till we check the first word before doing any initializing.
@@ -34,6 +32,9 @@ void SpellCheck::Init(base::PlatformFile file,
hunspell_.reset();
bdict_file_.reset();
file_ = file;
+ is_using_platform_spelling_engine_ =
+ file == base::kInvalidPlatformFileValue && !language.empty();
+
character_attributes_.SetDefaultLanguage(language);
custom_words_.insert(custom_words_.end(),
@@ -58,8 +59,10 @@ bool SpellCheck::SpellCheckWord(
return true;
// Do nothing if spell checking is disabled.
- if (initialized_ && file_ == base::kInvalidPlatformFileValue)
+ if (initialized_ && file_ == base::kInvalidPlatformFileValue &&
+ !is_using_platform_spelling_engine_) {
return true;
+ }
*misspelling_start = 0;
*misspelling_len = 0;
@@ -100,15 +103,15 @@ string16 SpellCheck::GetAutoCorrectionWord(const string16& word, int tag) {
return autocorrect_word; // Return the empty string.
int word_length = static_cast<int>(word.size());
- if (word_length < 2 || word_length > kMaxAutoCorrectWordSize)
+ if (word_length < 2 || word_length > SpellCheckCommon::kMaxAutoCorrectWordSize)
return autocorrect_word;
if (InitializeIfNeeded())
return autocorrect_word;
- char16 misspelled_word[kMaxAutoCorrectWordSize + 1];
+ char16 misspelled_word[SpellCheckCommon::kMaxAutoCorrectWordSize + 1];
const char16* word_char = word.c_str();
- for (int i = 0; i <= kMaxAutoCorrectWordSize; i++) {
+ for (int i = 0; i <= SpellCheckCommon::kMaxAutoCorrectWordSize; i++) {
if (i >= word_length)
misspelled_word[i] = NULL;
else
@@ -188,15 +191,18 @@ void SpellCheck::AddWordToHunspell(const std::string& word) {
}
bool SpellCheck::InitializeIfNeeded() {
+ if (is_using_platform_spelling_engine_)
+ return false;
+
if (!initialized_) {
- RenderThread::current()->RequestSpellCheckDictionary();
+ RenderThread::current()->Send(
+ new ViewHostMsg_SpellChecker_RequestDictionary);
initialized_ = true;
return true;
}
// Check if the platform spellchecker is being used.
- if (!is_using_platform_spelling_engine_ &&
- file_ != base::kInvalidPlatformFileValue) {
+ if (file_ != base::kInvalidPlatformFileValue) {
// If it isn't, init hunspell.
InitializeHunspell();
}
@@ -210,8 +216,9 @@ bool SpellCheck::CheckSpelling(const string16& word_to_check, int tag) {
bool word_correct = false;
if (is_using_platform_spelling_engine_) {
- // TODO(estade): sync IPC to browser.
- word_correct = true;
+ RenderThread::current()->Send(
+ new ViewHostMsg_SpellChecker_PlatformCheckSpelling(word_to_check, tag,
+ &word_correct));
} else {
std::string word_to_check_utf8(UTF16ToUTF8(word_to_check));
// Hunspell shouldn't let us exceed its max, but check just in case
@@ -229,7 +236,9 @@ void SpellCheck::FillSuggestionList(
const string16& wrong_word,
std::vector<string16>* optional_suggestions) {
if (is_using_platform_spelling_engine_) {
- // TODO(estade): sync IPC to browser.
+ RenderThread::current()->Send(
+ new ViewHostMsg_SpellChecker_PlatformFillSuggestionList(
+ wrong_word, optional_suggestions));
return;
}
char** suggestions;
@@ -238,7 +247,7 @@ void SpellCheck::FillSuggestionList(
// Populate the vector of WideStrings.
for (int i = 0; i < number_of_suggestions; i++) {
- if (i < kMaxSuggestions)
+ if (i < SpellCheckCommon::kMaxSuggestions)
optional_suggestions->push_back(UTF8ToUTF16(suggestions[i]));
free(suggestions[i]);
}
diff --git a/chrome/renderer/spellchecker/spellcheck.h b/chrome/renderer/spellchecker/spellcheck.h
index ef194bd..94b9a07 100644
--- a/chrome/renderer/spellchecker/spellcheck.h
+++ b/chrome/renderer/spellchecker/spellcheck.h
@@ -52,6 +52,9 @@ class SpellCheck {
// Find a possible correctly spelled word for a misspelled word. Computes an
// empty string if input misspelled word is too long, there is ambiguity, or
// the correct spelling cannot be determined.
+ // NOTE: If using the platform spellchecker, this will send a *lot* of sync
+ // IPCs. We should probably refactor this if we ever plan to take it out from
+ // behind its command line flag.
string16 GetAutoCorrectionWord(const string16& word, int tag);
// Turn auto spell correct support ON or OFF.
diff --git a/chrome/browser/spellcheck_unittest.cc b/chrome/renderer/spellchecker/spellcheck_unittest.cc
index b50f802..2ed20a6 100644
--- a/chrome/browser/spellcheck_unittest.cc
+++ b/chrome/renderer/spellchecker/spellcheck_unittest.cc
@@ -7,31 +7,14 @@
#include "base/file_util.h"
#include "base/message_loop.h"
#include "base/path_service.h"
+#include "base/platform_file.h"
#include "base/sys_string_conversions.h"
-#include "chrome/browser/chrome_thread.h"
-#include "chrome/browser/spellchecker.h"
-#include "chrome/browser/spellchecker_platform_engine.h"
+#include "chrome/renderer/spellchecker/spellcheck.h"
#include "chrome/common/chrome_paths.h"
+#include "chrome/common/spellcheck_common.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
-const FilePath::CharType kTempCustomDictionaryFile[] =
- FILE_PATH_LITERAL("temp_custom_dictionary.txt");
-} // namespace
-
-class SpellCheckTest : public testing::Test {
- public:
- SpellCheckTest()
- : file_thread_(ChromeThread::FILE, &message_loop_),
- io_thread_(ChromeThread::IO, &message_loop_) {}
-
- protected:
- MessageLoop message_loop_;
-
- private:
- ChromeThread file_thread_;
- ChromeThread io_thread_; // To keep DCHECKs inside spell checker happy.
-};
// Represents a special initialization function used only for the unit tests
// in this file.
@@ -49,6 +32,33 @@ FilePath GetHunspellDirectory() {
return hunspell_directory;
}
+class SpellCheckTest : public testing::Test {
+ public:
+ SpellCheckTest() {
+ ReinitializeSpellCheck("en-US");
+ }
+
+ void ReinitializeSpellCheck(const std::string& language) {
+ spell_check_.reset(new SpellCheck());
+
+ FilePath hunspell_directory = GetHunspellDirectory();
+ EXPECT_FALSE(hunspell_directory.empty());
+ base::PlatformFile file = base::CreatePlatformFile(
+ SpellCheckCommon::GetVersionedFileName(language, hunspell_directory),
+ base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ, NULL);
+ spell_check_->Init(
+ file, std::vector<std::string>(), language);
+ }
+
+ virtual ~SpellCheckTest() {
+ }
+
+ SpellCheck* spell_check() { return spell_check_.get(); }
+
+ private:
+ scoped_ptr<SpellCheck> spell_check_;
+};
+
// Operates unit tests for the webkit_glue::SpellCheckWord() function
// with the US English dictionary.
// The unit tests in this function consist of:
@@ -276,14 +286,6 @@ TEST_F(SpellCheckTest, SpellCheckStrings_EN_US) {
{L"qwertyuiopasdf", false, 0, 14},
};
- FilePath hunspell_directory = GetHunspellDirectory();
- ASSERT_FALSE(hunspell_directory.empty());
-
- scoped_refptr<SpellChecker> spell_checker(new SpellChecker(
- hunspell_directory, "en-US", NULL, FilePath()));
- spell_checker->Initialize();
- message_loop_.RunAllPending();
-
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
size_t input_length = 0;
if (kTestCases[i].input != NULL) {
@@ -291,7 +293,7 @@ TEST_F(SpellCheckTest, SpellCheckStrings_EN_US) {
}
int misspelling_start;
int misspelling_length;
- bool result = spell_checker->SpellCheckWord(
+ bool result = spell_check()->SpellCheckWord(
WideToUTF16(kTestCases[i].input).c_str(),
static_cast<int>(input_length),
0,
@@ -318,297 +320,7 @@ TEST_F(SpellCheckTest, SpellCheckSuggestions_EN_US) {
// A suggested word that should occur.
const wchar_t* suggested_word;
- } kTestCases[] = { // A valid English word with a preceding whitespace
- // We need to have separate test cases here, since hunspell and the OS X
- // spellchecking service occasionally differ on what they consider a valid
- // suggestion for a given word, although these lists could likely be
- // integrated somewhat.
-#if defined(OS_MACOSX)
- // These words come from the wikipedia page of the most commonly
- // misspelled words in english.
- // (http://en.wikipedia.org/wiki/Commonly_misspelled_words).
- {L"absense", false, 0, 0, L"absence"},
- {L"acceptible", false, 0, 0, L"acceptable"},
- {L"accidentaly", false, 0, 0, L"accidentally"},
- {L"accomodate", false, 0, 0, L"accommodate"},
- {L"acheive", false, 0, 0, L"achieve"},
- {L"acknowlege", false, 0, 0, L"acknowledge"},
- {L"acquaintence", false, 0, 0, L"acquaintance"},
- {L"aquire", false, 0, 0, L"acquire"},
- {L"aquit", false, 0, 0, L"acquit"},
- {L"acrage", false, 0, 0, L"acreage"},
- {L"adress", false, 0, 0, L"address"},
- {L"adultary", false, 0, 0, L"adultery"},
- {L"advertize", false, 0, 0, L"advertise"},
- {L"adviseable", false, 0, 0, L"advisable"},
- {L"agression", false, 0, 0, L"aggression"},
- {L"alchohol", false, 0, 0, L"alcohol"},
- {L"alege", false, 0, 0, L"allege"},
- {L"allegaince", false, 0, 0, L"allegiance"},
- {L"allmost", false, 0, 0, L"almost"},
- // Ideally, this test should pass. It works in firefox, but not in hunspell
- // or OS X.
- // {L"alot", false, 0, 0, L"a lot"},
- {L"amatuer", false, 0, 0, L"amateur"},
- {L"ammend", false, 0, 0, L"amend"},
- {L"amung", false, 0, 0, L"among"},
- {L"anually", false, 0, 0, L"annually"},
- {L"apparant", false, 0, 0, L"apparent"},
- {L"artic", false, 0, 0, L"arctic"},
- {L"arguement", false, 0, 0, L"argument"},
- {L"athiest", false, 0, 0, L"atheist"},
- {L"athelete", false, 0, 0, L"athlete"},
- {L"avrage", false, 0, 0, L"average"},
- {L"awfull", false, 0, 0, L"awful"},
- {L"ballance", false, 0, 0, L"balance"},
- {L"basicly", false, 0, 0, L"basically"},
- {L"becuase", false, 0, 0, L"because"},
- {L"becomeing", false, 0, 0, L"becoming"},
- {L"befor", false, 0, 0, L"before"},
- {L"begining", false, 0, 0, L"beginning"},
- {L"beleive", false, 0, 0, L"believe"},
- {L"bellweather", false, 0, 0, L"bellwether"},
- {L"benifit", false, 0, 0, L"benefit"},
- {L"bouy", false, 0, 0, L"buoy"},
- {L"briliant", false, 0, 0, L"brilliant"},
- {L"burgler", false, 0, 0, L"burglar"},
- {L"camoflage", false, 0, 0, L"camouflage"},
- {L"carrer", false, 0, 0, L"career"},
- {L"carefull", false, 0, 0, L"careful"},
- {L"Carribean", false, 0, 0, L"Caribbean"},
- {L"catagory", false, 0, 0, L"category"},
- {L"cauhgt", false, 0, 0, L"caught"},
- {L"cieling", false, 0, 0, L"ceiling"},
- {L"cemetary", false, 0, 0, L"cemetery"},
- {L"certin", false, 0, 0, L"certain"},
- {L"changable", false, 0, 0, L"changeable"},
- {L"cheif", false, 0, 0, L"chief"},
- {L"citezen", false, 0, 0, L"citizen"},
- {L"collaegue", false, 0, 0, L"colleague"},
- {L"colum", false, 0, 0, L"column"},
- {L"comming", false, 0, 0, L"coming"},
- {L"commited", false, 0, 0, L"committed"},
- {L"compitition", false, 0, 0, L"competition"},
- {L"conceed", false, 0, 0, L"concede"},
- {L"congradulate", false, 0, 0, L"congratulate"},
- {L"consciencious", false, 0, 0, L"conscientious"},
- {L"concious", false, 0, 0, L"conscious"},
- {L"concensus", false, 0, 0, L"consensus"},
- {L"contraversy", false, 0, 0, L"controversy"},
- {L"conveniance", false, 0, 0, L"convenience"},
- {L"critecize", false, 0, 0, L"criticize"},
- {L"dacquiri", false, 0, 0, L"daiquiri"},
- {L"decieve", false, 0, 0, L"deceive"},
- {L"dicide", false, 0, 0, L"decide"},
- {L"definate", false, 0, 0, L"definite"},
- {L"definitly", false, 0, 0, L"definitely"},
- {L"deposite", false, 0, 0, L"deposit"},
- {L"desparate", false, 0, 0, L"desperate"},
- {L"develope", false, 0, 0, L"develop"},
- {L"diffrence", false, 0, 0, L"difference"},
- {L"dilema", false, 0, 0, L"dilemma"},
- {L"disapear", false, 0, 0, L"disappear"},
- {L"disapoint", false, 0, 0, L"disappoint"},
- {L"disasterous", false, 0, 0, L"disastrous"},
- {L"disipline", false, 0, 0, L"discipline"},
- {L"drunkeness", false, 0, 0, L"drunkenness"},
- {L"dumbell", false, 0, 0, L"dumbbell"},
- {L"durring", false, 0, 0, L"during"},
- {L"easely", false, 0, 0, L"easily"},
- {L"eigth", false, 0, 0, L"eight"},
- {L"embarass", false, 0, 0, L"embarrass"},
- {L"enviroment", false, 0, 0, L"environment"},
- {L"equiped", false, 0, 0, L"equipped"},
- {L"equiptment", false, 0, 0, L"equipment"},
- {L"exagerate", false, 0, 0, L"exaggerate"},
- {L"excede", false, 0, 0, L"exceed"},
- {L"exellent", false, 0, 0, L"excellent"},
- {L"exsept", false, 0, 0, L"except"},
- {L"exercize", false, 0, 0, L"exercise"},
- {L"exilerate", false, 0, 0, L"exhilarate"},
- {L"existance", false, 0, 0, L"existence"},
- {L"experiance", false, 0, 0, L"experience"},
- {L"experament", false, 0, 0, L"experiment"},
- {L"explaination", false, 0, 0, L"explanation"},
- {L"extreem", false, 0, 0, L"extreme"},
- {L"familier", false, 0, 0, L"familiar"},
- {L"facinating", false, 0, 0, L"fascinating"},
- {L"firey", false, 0, 0, L"fiery"},
- {L"finaly", false, 0, 0, L"finally"},
- {L"flourescent", false, 0, 0, L"fluorescent"},
- {L"foriegn", false, 0, 0, L"foreign"},
- {L"fourty", false, 0, 0, L"forty"},
- {L"foreward", false, 0, 0, L"forward"},
- {L"freind", false, 0, 0, L"friend"},
- {L"fullfil", false, 0, 0, L"fulfill"},
- {L"fundemental", false, 0, 0, L"fundamental"},
- {L"guage", false, 0, 0, L"gauge"},
- {L"generaly", false, 0, 0, L"generally"},
- {L"goverment", false, 0, 0, L"government"},
- {L"grammer", false, 0, 0, L"grammar"},
- {L"gratefull", false, 0, 0, L"grateful"},
- {L"garantee", false, 0, 0, L"guarantee"},
- {L"guidence", false, 0, 0, L"guidance"},
- {L"happyness", false, 0, 0, L"happiness"},
- {L"harrass", false, 0, 0, L"harass"},
- {L"heighth", false, 0, 0, L"height"},
- {L"heirarchy", false, 0, 0, L"hierarchy"},
- {L"humerous", false, 0, 0, L"humorous"},
- {L"hygene", false, 0, 0, L"hygiene"},
- {L"hipocrit", false, 0, 0, L"hypocrite"},
- {L"idenity", false, 0, 0, L"identity"},
- {L"ignorence", false, 0, 0, L"ignorance"},
- {L"imaginery", false, 0, 0, L"imaginary"},
- {L"immitate", false, 0, 0, L"imitate"},
- {L"immitation", false, 0, 0, L"imitation"},
- {L"imediately", false, 0, 0, L"immediately"},
- {L"incidently", false, 0, 0, L"incidentally"},
- {L"independant", false, 0, 0, L"independent"},
- {L"indispensible", false, 0, 0, L"indispensable"},
- {L"innoculate", false, 0, 0, L"inoculate"},
- {L"inteligence", false, 0, 0, L"intelligence"},
- {L"intresting", false, 0, 0, L"interesting"},
- {L"interuption", false, 0, 0, L"interruption"},
- {L"irrelevent", false, 0, 0, L"irrelevant"},
- {L"irritible", false, 0, 0, L"irritable"},
- {L"iland", false, 0, 0, L"island"},
- {L"jellous", false, 0, 0, L"jealous"},
- {L"knowlege", false, 0, 0, L"knowledge"},
- {L"labratory", false, 0, 0, L"laboratory"},
- {L"liesure", false, 0, 0, L"leisure"},
- {L"lenght", false, 0, 0, L"length"},
- {L"liason", false, 0, 0, L"liaison"},
- {L"libary", false, 0, 0, L"library"},
- {L"lisence", false, 0, 0, L"license"},
- {L"lonelyness", false, 0, 0, L"loneliness"},
- {L"lieing", false, 0, 0, L"lying"},
- {L"maintenence", false, 0, 0, L"maintenance"},
- {L"manuever", false, 0, 0, L"maneuver"},
- {L"marrige", false, 0, 0, L"marriage"},
- {L"mathmatics", false, 0, 0, L"mathematics"},
- {L"medcine", false, 0, 0, L"medicine"},
- {L"medeval", false, 0, 0, L"medieval"},
- {L"momento", false, 0, 0, L"memento"},
- {L"millenium", false, 0, 0, L"millennium"},
- {L"miniture", false, 0, 0, L"miniature"},
- {L"minite", false, 0, 0, L"minute"},
- {L"mischevous", false, 0, 0, L"mischievous"},
- {L"mispell", false, 0, 0, L"misspell"},
- // Maybe this one should pass, as it works in hunspell, but not in firefox.
- // {L"misterius", false, 0, 0, L"mysterious"},
- {L"naturaly", false, 0, 0, L"naturally"},
- {L"neccessary", false, 0, 0, L"necessary"},
- {L"neice", false, 0, 0, L"niece"},
- {L"nieghbor", false, 0, 0, L"neighbor"},
- {L"nieghbour", false, 0, 0, L"neighbor"},
- {L"niether", false, 0, 0, L"neither"},
- {L"noticable", false, 0, 0, L"noticeable"},
- {L"occassion", false, 0, 0, L"occasion"},
- {L"occasionaly", false, 0, 0, L"occasionally"},
- {L"occurrance", false, 0, 0, L"occurrence"},
- {L"occured", false, 0, 0, L"occurred"},
- {L"oficial", false, 0, 0, L"official"},
- {L"offen", false, 0, 0, L"often"},
- {L"ommision", false, 0, 0, L"omission"},
- {L"oprate", false, 0, 0, L"operate"},
- {L"oppurtunity", false, 0, 0, L"opportunity"},
- {L"orignal", false, 0, 0, L"original"},
- {L"outragous", false, 0, 0, L"outrageous"},
- {L"parrallel", false, 0, 0, L"parallel"},
- {L"parliment", false, 0, 0, L"parliament"},
- {L"particurly", false, 0, 0, L"particularly"},
- {L"passtime", false, 0, 0, L"pastime"},
- {L"peculier", false, 0, 0, L"peculiar"},
- {L"percieve", false, 0, 0, L"perceive"},
- {L"pernament", false, 0, 0, L"permanent"},
- {L"perseverence", false, 0, 0, L"perseverance"},
- {L"personaly", false, 0, 0, L"personally"},
- {L"personell", false, 0, 0, L"personnel"},
- {L"persaude", false, 0, 0, L"persuade"},
- {L"pichure", false, 0, 0, L"picture"},
- {L"peice", false, 0, 0, L"piece"},
- {L"plagerize", false, 0, 0, L"plagiarize"},
- {L"playright", false, 0, 0, L"playwright"},
- {L"plesant", false, 0, 0, L"pleasant"},
- {L"pollitical", false, 0, 0, L"political"},
- {L"posession", false, 0, 0, L"possession"},
- {L"potatos", false, 0, 0, L"potatoes"},
- {L"practicle", false, 0, 0, L"practical"},
- {L"preceed", false, 0, 0, L"precede"},
- {L"predjudice", false, 0, 0, L"prejudice"},
- {L"presance", false, 0, 0, L"presence"},
- {L"privelege", false, 0, 0, L"privilege"},
- // This one should probably work. It does in FF and Hunspell.
- // {L"probly", false, 0, 0, L"probably"},
- {L"proffesional", false, 0, 0, L"professional"},
- {L"professer", false, 0, 0, L"professor"},
- {L"promiss", false, 0, 0, L"promise"},
- {L"pronounciation", false, 0, 0, L"pronunciation"},
- {L"prufe", false, 0, 0, L"proof"},
- {L"psycology", false, 0, 0, L"psychology"},
- {L"publically", false, 0, 0, L"publicly"},
- {L"quanity", false, 0, 0, L"quantity"},
- {L"quarentine", false, 0, 0, L"quarantine"},
- {L"questionaire", false, 0, 0, L"questionnaire"},
- {L"readible", false, 0, 0, L"readable"},
- {L"realy", false, 0, 0, L"really"},
- {L"recieve", false, 0, 0, L"receive"},
- {L"reciept", false, 0, 0, L"receipt"},
- {L"reconize", false, 0, 0, L"recognize"},
- {L"recomend", false, 0, 0, L"recommend"},
- {L"refered", false, 0, 0, L"referred"},
- {L"referance", false, 0, 0, L"reference"},
- {L"relevent", false, 0, 0, L"relevant"},
- {L"religous", false, 0, 0, L"religious"},
- {L"repitition", false, 0, 0, L"repetition"},
- {L"restarant", false, 0, 0, L"restaurant"},
- {L"rythm", false, 0, 0, L"rhythm"},
- {L"rediculous", false, 0, 0, L"ridiculous"},
- {L"sacrefice", false, 0, 0, L"sacrifice"},
- {L"saftey", false, 0, 0, L"safety"},
- {L"sissors", false, 0, 0, L"scissors"},
- {L"secratary", false, 0, 0, L"secretary"},
- {L"sieze", false, 0, 0, L"seize"},
- {L"seperate", false, 0, 0, L"separate"},
- {L"sargent", false, 0, 0, L"sergeant"},
- {L"shineing", false, 0, 0, L"shining"},
- {L"similer", false, 0, 0, L"similar"},
- {L"sinceerly", false, 0, 0, L"sincerely"},
- {L"speach", false, 0, 0, L"speech"},
- {L"stoping", false, 0, 0, L"stopping"},
- {L"strenght", false, 0, 0, L"strength"},
- {L"succede", false, 0, 0, L"succeed"},
- {L"succesful", false, 0, 0, L"successful"},
- {L"supercede", false, 0, 0, L"supersede"},
- {L"surelly", false, 0, 0, L"surely"},
- {L"suprise", false, 0, 0, L"surprise"},
- {L"temperture", false, 0, 0, L"temperature"},
- {L"temprary", false, 0, 0, L"temporary"},
- {L"tomatos", false, 0, 0, L"tomatoes"},
- {L"tommorrow", false, 0, 0, L"tomorrow"},
- {L"tounge", false, 0, 0, L"tongue"},
- {L"truely", false, 0, 0, L"truly"},
- {L"twelth", false, 0, 0, L"twelfth"},
- {L"tyrany", false, 0, 0, L"tyranny"},
- {L"underate", false, 0, 0, L"underrate"},
- {L"untill", false, 0, 0, L"until"},
- {L"unuseual", false, 0, 0, L"unusual"},
- {L"upholstry", false, 0, 0, L"upholstery"},
- {L"usible", false, 0, 0, L"usable"},
- {L"useing", false, 0, 0, L"using"},
- {L"usualy", false, 0, 0, L"usually"},
- {L"vaccuum", false, 0, 0, L"vacuum"},
- {L"vegatarian", false, 0, 0, L"vegetarian"},
- {L"vehical", false, 0, 0, L"vehicle"},
- {L"visious", false, 0, 0, L"vicious"},
- {L"villege", false, 0, 0, L"village"},
- {L"wierd", false, 0, 0, L"weird"},
- {L"wellcome", false, 0, 0, L"welcome"},
- {L"wellfare", false, 0, 0, L"welfare"},
- {L"wilfull", false, 0, 0, L"willful"},
- {L"withold", false, 0, 0, L"withhold"},
- {L"writting", false, 0, 0, L"writing"},
-#else
+ } kTestCases[] = {
{L"ello", false, 0, 0, L"hello"},
{L"ello", false, 0, 0, L"cello"},
{L"wate", false, 0, 0, L"water"},
@@ -619,18 +331,9 @@ TEST_F(SpellCheckTest, SpellCheckSuggestions_EN_US) {
{L"jum", false, 0, 0, L"hum"},
{L"jum", false, 0, 0, L"sum"},
{L"jum", false, 0, 0, L"um"},
-#endif // !OS_MACOSX
// TODO (Sidchat): add many more examples.
};
- FilePath hunspell_directory = GetHunspellDirectory();
- ASSERT_FALSE(hunspell_directory.empty());
-
- scoped_refptr<SpellChecker> spell_checker(new SpellChecker(
- hunspell_directory, "en-US", NULL, FilePath()));
- spell_checker->Initialize();
- message_loop_.RunAllPending();
-
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
std::vector<string16> suggestions;
size_t input_length = 0;
@@ -639,7 +342,7 @@ TEST_F(SpellCheckTest, SpellCheckSuggestions_EN_US) {
}
int misspelling_start;
int misspelling_length;
- bool result = spell_checker->SpellCheckWord(
+ bool result = spell_check()->SpellCheckWord(
WideToUTF16(kTestCases[i].input).c_str(),
static_cast<int>(input_length),
0,
@@ -897,22 +600,15 @@ TEST_F(SpellCheckTest, SpellCheckText) {
},
};
- FilePath hunspell_directory = GetHunspellDirectory();
- ASSERT_FALSE(hunspell_directory.empty());
-
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
- scoped_refptr<SpellChecker> spell_checker(new SpellChecker(
- hunspell_directory, kTestCases[i].language, NULL, FilePath()));
- spell_checker->Initialize();
- message_loop_.RunAllPending();
-
+ ReinitializeSpellCheck(kTestCases[i].language);
size_t input_length = 0;
if (kTestCases[i].input != NULL)
input_length = wcslen(kTestCases[i].input);
int misspelling_start = 0;
int misspelling_length = 0;
- bool result = spell_checker->SpellCheckWord(
+ bool result = spell_check()->SpellCheckWord(
WideToUTF16(kTestCases[i].input).c_str(),
static_cast<int>(input_length),
0,
@@ -925,164 +621,6 @@ TEST_F(SpellCheckTest, SpellCheckText) {
}
}
-// This test Adds words to the SpellChecker and veifies that it remembers them.
-TEST_F(SpellCheckTest, DISABLED_SpellCheckAddToDictionary_EN_US) {
- static const struct {
- // A string to be added to SpellChecker.
- const wchar_t* word_to_add;
- } kTestCases[] = { // Words to be added to the SpellChecker.
- {L"Googley"},
- {L"Googleplex"},
- {L"Googler"},
- };
-
- FilePath custom_dictionary_file(kTempCustomDictionaryFile);
- FilePath hunspell_directory = GetHunspellDirectory();
- ASSERT_FALSE(hunspell_directory.empty());
-
- scoped_refptr<SpellChecker> spell_checker(new SpellChecker(
- hunspell_directory, "en-US", NULL, custom_dictionary_file));
- spell_checker->Initialize();
- message_loop_.RunAllPending();
-
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
- // Add the word to spellchecker.
- spell_checker->AddWord(WideToUTF16(kTestCases[i].word_to_add));
-
- // Now check whether it is added to Spellchecker.
- std::vector<string16> suggestions;
- size_t input_length = 0;
- if (kTestCases[i].word_to_add != NULL) {
- input_length = wcslen(kTestCases[i].word_to_add);
- }
- int misspelling_start;
- int misspelling_length;
- bool result = spell_checker->SpellCheckWord(
- WideToUTF16(kTestCases[i].word_to_add).c_str(),
- static_cast<int>(input_length),
- 0,
- &misspelling_start,
- &misspelling_length,
- &suggestions);
-
- // Check for spelling.
- EXPECT_TRUE(result);
- }
-
- // Now initialize another spellchecker to see that AddToWord is permanent.
- scoped_refptr<SpellChecker> spell_checker_new(new SpellChecker(
- hunspell_directory, "en-US", NULL, custom_dictionary_file));
- spell_checker->Initialize();
- message_loop_.RunAllPending();
-
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
- // Now check whether it is added to Spellchecker.
- std::vector<string16> suggestions;
- size_t input_length = 0;
- if (kTestCases[i].word_to_add != NULL) {
- input_length = wcslen(kTestCases[i].word_to_add);
- }
- int misspelling_start;
- int misspelling_length;
- bool result = spell_checker_new->SpellCheckWord(
- WideToUTF16(kTestCases[i].word_to_add).c_str(),
- static_cast<int>(input_length),
- 0,
- &misspelling_start,
- &misspelling_length,
- &suggestions);
-
- // Check for spelling.
- EXPECT_TRUE(result);
- }
-
- // Remove the temp custom dictionary file.
- file_util::Delete(custom_dictionary_file, false);
-}
-
-// SpellChecker should suggest custome words for misspelled words.
-TEST_F(SpellCheckTest, DISABLED_SpellCheckSuggestionsAddToDictionary_EN_US) {
- static const struct {
- // A string to be added to SpellChecker.
- const wchar_t* word_to_add;
- } kTestCases[] = { // word to be added to SpellChecker
- {L"Googley"},
- {L"Googleplex"},
- {L"Googler"},
- };
-
- FilePath custom_dictionary_file(kTempCustomDictionaryFile);
- FilePath hunspell_directory = GetHunspellDirectory();
- ASSERT_FALSE(hunspell_directory.empty());
-
- scoped_refptr<SpellChecker> spell_checker(new SpellChecker(
- hunspell_directory, "en-US", NULL, custom_dictionary_file));
- spell_checker->Initialize();
- message_loop_.RunAllPending();
-
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
- // Add the word to spellchecker.
- spell_checker->AddWord(WideToUTF16(kTestCases[i].word_to_add));
- }
-
- // Now check to see whether the custom words are suggested for
- // misspelled but similar words.
- static const struct {
- // A string to be tested.
- const wchar_t* input;
- // An expected result for this test case.
- // * true: the input string does not have any invalid words.
- // * false: the input string has one or more invalid words.
- bool expected_result;
- // The position and the length of the first invalid word.
- int misspelling_start;
- int misspelling_length;
-
- // A suggested word that should occur.
- const wchar_t* suggested_word;
- } kTestCasesToBeTested[] = {
- {L"oogley", false, 0, 0, L"Googley"},
- {L"oogler", false, 0, 0, L"Googler"},
- {L"oogleplex", false, 0, 0, L"Googleplex"},
- };
-
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCasesToBeTested); ++i) {
- std::vector<string16> suggestions;
- size_t input_length = 0;
- if (kTestCasesToBeTested[i].input != NULL) {
- input_length = wcslen(kTestCasesToBeTested[i].input);
- }
- int misspelling_start;
- int misspelling_length;
- bool result = spell_checker->SpellCheckWord(
- WideToUTF16(kTestCasesToBeTested[i].input).c_str(),
- static_cast<int>(input_length),
- 0,
- &misspelling_start,
- &misspelling_length,
- &suggestions);
-
- // Check for spelling.
- EXPECT_EQ(result, kTestCasesToBeTested[i].expected_result);
-
- // Check if the suggested words occur.
- bool suggested_word_is_present = false;
- for (int j=0; j < static_cast<int>(suggestions.size()); j++) {
- if (suggestions.at(j).compare(
- WideToUTF16(kTestCasesToBeTested[i].suggested_word)) ==
- 0) {
- suggested_word_is_present = true;
- break;
- }
- }
-
- EXPECT_TRUE(suggested_word_is_present);
- }
-
- // Remove the temp custom dictionary file.
- file_util::Delete(custom_dictionary_file, false);
-}
-
TEST_F(SpellCheckTest, GetAutoCorrectionWord_EN_US) {
static const struct {
// A misspelled word.
@@ -1098,21 +636,13 @@ TEST_F(SpellCheckTest, GetAutoCorrectionWord_EN_US) {
{"noen", ""},
{"what", ""},
};
-
- FilePath hunspell_directory = GetHunspellDirectory();
- ASSERT_FALSE(hunspell_directory.empty());
-
- scoped_refptr<SpellChecker> spell_checker(new SpellChecker(
- hunspell_directory, "en-US", NULL, FilePath()));
- spell_checker->EnableAutoSpellCorrect(true);
- spell_checker->Initialize();
- message_loop_.RunAllPending();
+ spell_check()->EnableAutoSpellCorrect(true);
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
string16 misspelled_word(UTF8ToUTF16(kTestCases[i].input));
string16 expected_autocorrect_word(
UTF8ToUTF16(kTestCases[i].expected_result));
- string16 autocorrect_word = spell_checker->GetAutoCorrectionWord(
+ string16 autocorrect_word = spell_check()->GetAutoCorrectionWord(
misspelled_word, 0);
// Check for spelling.
@@ -1120,80 +650,4 @@ TEST_F(SpellCheckTest, GetAutoCorrectionWord_EN_US) {
}
}
-#if defined(OS_MACOSX)
-// Tests that words are properly ignored. Currently only enabled on OS X as it
-// is the only platform to support ignoring words. Note that in this test, we
-// supply a non-zero doc_tag, in order to test that ignored words are matched to
-// the correct document.
-TEST_F(SpellCheckTest, IgnoreWords_EN_US) {
- static const struct {
- // A misspelled word.
- const char* input;
- bool input_result;
- } kTestCases[] = {
- {"teh", false},
- {"moer", false},
- {"watre", false},
- {"noen", false},
- };
-
- FilePath hunspell_directory = GetHunspellDirectory();
- ASSERT_FALSE(hunspell_directory.empty());
-
- scoped_refptr<SpellChecker> spell_checker(new SpellChecker(
- hunspell_directory, "en-US", NULL, FilePath()));
- spell_checker->Initialize();
- message_loop_.RunAllPending();
-
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
- string16 word(UTF8ToUTF16(kTestCases[i].input));
- std::vector<string16> suggestions;
- size_t input_length = 0;
- if (kTestCases[i].input != NULL) {
- input_length = word.length();
- }
- int misspelling_start;
- int misspelling_length;
-
- int doc_tag = SpellCheckerPlatform::GetDocumentTag();
- bool result = spell_checker->SpellCheckWord(word.c_str(),
- static_cast<int>(input_length),
- doc_tag,
- &misspelling_start,
- &misspelling_length,
- &suggestions);
-
- // The word should show up as misspelled.
- EXPECT_EQ(kTestCases[i].input_result, result);
-
- // Ignore the word.
- SpellCheckerPlatform::IgnoreWord(word);
-
- // Spellcheck again.
- result = spell_checker->SpellCheckWord(word.c_str(),
- static_cast<int>(input_length),
- doc_tag,
- &misspelling_start,
- &misspelling_length,
- &suggestions);
-
- // The word should now show up as correctly spelled.
- EXPECT_EQ(!(kTestCases[i].input_result), result);
-
- // Close the docuemnt. Any words that we had previously ignored should no
- // longer be ignored and thus should show up as misspelled.
- SpellCheckerPlatform::CloseDocumentWithTag(doc_tag);
-
- // Spellcheck one more time.
- result = spell_checker->SpellCheckWord(word.c_str(),
- static_cast<int>(input_length),
- doc_tag,
- &misspelling_start,
- &misspelling_length,
- &suggestions);
-
- // The word should now show be spelled wrong again
- EXPECT_EQ(kTestCases[i].input_result, result);
- }
-} // Test IgnoreWords_EN_US
-#endif // OS_MACOSX
+} // namespace
diff --git a/chrome/test/testing_profile.h b/chrome/test/testing_profile.h
index 40b6896..677bb7e 100644
--- a/chrome/test/testing_profile.h
+++ b/chrome/test/testing_profile.h
@@ -175,13 +175,8 @@ class TestingProfile : public Profile {
virtual base::Time GetStartTime() const { return start_time_; }
virtual TabRestoreService* GetTabRestoreService() { return NULL; }
virtual void ResetTabRestoreService() {}
- virtual void ReinitializeSpellChecker() {}
- virtual SpellChecker* GetSpellChecker() { return NULL; }
- virtual void DeleteSpellChecker() {}
-#if defined(SPELLCHECKER_IN_RENDERER)
virtual SpellCheckHost* GetSpellCheckHost() { return NULL; }
virtual void ReinitializeSpellCheckHost(bool force) { }
-#endif
virtual WebKitContext* GetWebKitContext() { return NULL; }
virtual WebKitContext* GetOffTheRecordWebKitContext() { return NULL; }
virtual void MarkAsCleanShutdown() {}