Backout a422b9ff0a9e (bug 591780 part 1) for causing 8% Ts regression on multiple platforms; a=khuey
authorEd Morley <bmo@edmorley.co.uk>
Tue, 06 Sep 2011 14:41:31 +0100
changeset 76570 db9e99d537f232324359b86112d8771bfad029fe
parent 76569 1f5cd567c93a7ef6db27aa0539bdc2a4099935d0
child 76571 6a4e5dbe0d64d7646306b4c9fc50a69b29631551
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewerskhuey
bugs591780
milestone9.0a1
backs outa422b9ff0a9eb3fe278e0866faccb4a4016f40c5
Backout a422b9ff0a9e (bug 591780 part 1) for causing 8% Ts regression on multiple platforms; a=khuey
browser/base/content/nsContextMenu.js
editor/composer/src/nsEditorSpellCheck.cpp
editor/idl/nsIEditorSpellCheck.idl
editor/libeditor/base/Makefile.in
editor/libeditor/base/nsEditor.cpp
editor/libeditor/base/nsEditor.h
editor/txtsvc/public/nsISpellChecker.h
extensions/spellcheck/Makefile.in
extensions/spellcheck/hunspell/src/Makefile.in
extensions/spellcheck/hunspell/src/mozHunspell.cpp
extensions/spellcheck/hunspell/src/mozHunspell.h
extensions/spellcheck/idl/mozISpellCheckingEngine.idl
extensions/spellcheck/src/mozInlineSpellChecker.cpp
extensions/spellcheck/src/mozInlineSpellChecker.h
extensions/spellcheck/src/mozSpellChecker.cpp
extensions/spellcheck/src/mozSpellChecker.h
extensions/spellcheck/src/mozSpellCheckerFactory.cpp
extensions/spellcheck/tests/Makefile.in
extensions/spellcheck/tests/chrome/Makefile.in
extensions/spellcheck/tests/chrome/base/Makefile.in
extensions/spellcheck/tests/chrome/base/base_utf.aff
extensions/spellcheck/tests/chrome/base/base_utf.dic
extensions/spellcheck/tests/chrome/map/Makefile.in
extensions/spellcheck/tests/chrome/map/maputf.aff
extensions/spellcheck/tests/chrome/map/maputf.dic
extensions/spellcheck/tests/chrome/test_add_remove_dictionaries.xul
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -316,18 +316,20 @@ nsContextMenu.prototype = {
                   !this.onTextInput && top.gBidiUI);
   },
 
   initSpellingItems: function() {
     var canSpell = InlineSpellCheckerUI.canSpellCheck;
     var onMisspelling = InlineSpellCheckerUI.overMisspelling;
     this.showItem("spell-check-enabled", canSpell);
     this.showItem("spell-separator", canSpell || this.onEditableArea);
-    document.getElementById("spell-check-enabled")
-            .setAttribute("checked", canSpell && InlineSpellCheckerUI.enabled);
+    if (canSpell) {
+      document.getElementById("spell-check-enabled")
+              .setAttribute("checked", InlineSpellCheckerUI.enabled);
+    }
 
     this.showItem("spell-add-to-dictionary", onMisspelling);
 
     // suggestion list
     this.showItem("spell-suggestions-separator", onMisspelling);
     if (onMisspelling) {
       var suggestionsSeparator =
         document.getElementById("spell-add-to-dictionary");
--- a/editor/composer/src/nsEditorSpellCheck.cpp
+++ b/editor/composer/src/nsEditorSpellCheck.cpp
@@ -645,24 +645,16 @@ nsEditorSpellCheck::SetCurrentDictionary
 
     // Also store it in as a preference. It will be used as a default value
     // when everything else fails.
     Preferences::SetString("spellchecker.dictionary", aDictionary);
   }
   return mSpellChecker->SetCurrentDictionary(aDictionary);
 }
 
-NS_IMETHODIMP
-nsEditorSpellCheck::GetSpellChecker(nsISpellChecker **aSpellChecker)
-{
-  *aSpellChecker = mSpellChecker;
-  NS_IF_ADDREF(*aSpellChecker);
-  return NS_OK;
-}
-
 NS_IMETHODIMP    
 nsEditorSpellCheck::UninitSpellChecker()
 {
   NS_ENSURE_TRUE(mSpellChecker, NS_ERROR_NOT_INITIALIZED);
 
   // Cleanup - kill the spell checker
   DeleteSuggestedWordList();
   mDictionaryList.Clear();
@@ -821,17 +813,21 @@ nsEditorSpellCheck::UpdateCurrentDiction
   // lang attribute, we try to get a dictionary. First try, en-US. If it does
   // not work, pick the first one.
   if (mPreferredLang.IsEmpty()) {
     nsAutoString currentDictionary;
     rv = GetCurrentDictionary(currentDictionary);
     if (NS_FAILED(rv) || currentDictionary.IsEmpty()) {
       rv = SetCurrentDictionary(NS_LITERAL_STRING("en-US"));
       if (NS_FAILED(rv)) {
-        mSpellChecker->CheckCurrentDictionary();
+        nsTArray<nsString> dictList;
+        rv = mSpellChecker->GetDictionaryList(&dictList);
+        if (NS_SUCCEEDED(rv) && dictList.Length() > 0) {
+          SetCurrentDictionary(dictList[0]);
+        }
       }
     }
   }
 
   // If an error was thrown while setting the dictionary, just
   // fail silently so that the spellchecker dialog is allowed to come
   // up. The user can manually reset the language to their choice on
   // the dialog if it is wrong.
--- a/editor/idl/nsIEditorSpellCheck.idl
+++ b/editor/idl/nsIEditorSpellCheck.idl
@@ -35,30 +35,21 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
  
 #include "nsISupports.idl"
 
 interface nsIEditor;
 interface nsITextServicesFilter;
-%{C++
-#include "nsISpellChecker.h"
-%}
-[ptr] native nsISpellChecker(nsISpellChecker);
 
-[scriptable, uuid(334946c3-0e93-4aac-b662-e1b56f95d68b)]
+[scriptable, uuid(af84da62-588f-409f-847d-feecc991bd93)]
 interface nsIEditorSpellCheck : nsISupports
 {
 
-  /**
-   * Get the spell checker used by this editor.
-   */
-  [noscript] readonly attribute nsISpellChecker spellChecker;
-
  /**
    * Returns true if we can enable spellchecking. If there are no available
    * dictionaries, this will return false.
    */
   boolean       canSpellCheck();
 
   /**
    * Turns on the spell checker for the given editor. enableSelectionChecking
--- a/editor/libeditor/base/Makefile.in
+++ b/editor/libeditor/base/Makefile.in
@@ -89,10 +89,9 @@ FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 INCLUDES	+= \
 		-I$(topsrcdir)/editor/libeditor/text \
 		-I$(topsrcdir)/content/base/src \
 		-I$(topsrcdir)/content/events/src \
 		-I$(topsrcdir)/layout/style \
-		-I$(topsrcdir)/extensions/spellcheck/src \
 		$(NULL)
--- a/editor/libeditor/base/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -19,17 +19,16 @@
  * Portions created by the Initial Developer are Copyright (C) 1998
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Pierre Phaneuf <pp@ludusdesign.com>
  *   Daniel Glazman <glazman@netscape.com>
  *   Masayuki Nakano <masayuki@d-toybox.com>
  *   Mats Palmgren <matspal@gmail.com>
- *   Jesper Kristensen <mail@jesperkristensen.dk>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -44,21 +43,16 @@
 #include "nsIDOMDocument.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsIDOMNSHTMLElement.h"
 #include "nsIDOMNSEvent.h"
 #include "nsIMEStateManager.h"
 #include "nsFocusManager.h"
 #include "nsUnicharUtils.h"
 #include "nsReadableUtils.h"
-#include "nsIObserverService.h"
-#include "mozilla/Services.h"
-#include "mozISpellCheckingEngine.h"
-#include "nsIEditorSpellCheck.h"
-#include "mozInlineSpellChecker.h"
 
 #include "nsIDOMText.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMAttr.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMDocumentFragment.h"
 #include "nsIDOMNamedNodeMap.h"
 #include "nsIDOMNodeList.h"
@@ -208,17 +202,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mEventListener)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsEditor)
  NS_INTERFACE_MAP_ENTRY(nsIPhonetic)
  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
  NS_INTERFACE_MAP_ENTRY(nsIEditorIMESupport)
  NS_INTERFACE_MAP_ENTRY(nsIEditor)
- NS_INTERFACE_MAP_ENTRY(nsIObserver)
  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIEditor)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsEditor)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsEditor)
 
 
 NS_IMETHODIMP
@@ -302,23 +295,16 @@ nsEditor::PostCreate()
 
     // nuke the modification count, so the doc appears unmodified
     // do this before we notify listeners
     ResetModificationCount();
 
     // update the UI with our state
     NotifyDocumentListeners(eDocumentCreated);
     NotifyDocumentListeners(eDocumentStateChanged);
-
-    nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
-    if (obs) {
-      obs->AddObserver(this,
-                       SPELLCHECK_DICTIONARY_UPDATE_NOTIFICATION,
-                       PR_FALSE);
-    }
   }
 
   // update nsTextStateManager and caret if we have focus
   nsCOMPtr<nsIContent> focusedContent = GetFocusedContent();
   if (focusedContent) {
     nsCOMPtr<nsIPresShell> ps = GetPresShell();
     NS_ASSERTION(ps, "no pres shell even though we have focus");
     NS_ENSURE_TRUE(ps, NS_ERROR_UNEXPECTED);
@@ -421,22 +407,16 @@ nsEditor::GetDesiredSpellCheckState()
 }
 
 NS_IMETHODIMP
 nsEditor::PreDestroy(PRBool aDestroyingFrames)
 {
   if (mDidPreDestroy)
     return NS_OK;
 
-  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
-  if (obs) {
-    obs->RemoveObserver(this,
-                        SPELLCHECK_DICTIONARY_UPDATE_NOTIFICATION);
-  }
-
   // Let spellchecker clean up its observers etc. It is important not to
   // actually free the spellchecker here, since the spellchecker could have
   // caused flush notifications, which could have gotten here if a textbox
   // is being removed. Setting the spellchecker to NULL could free the
   // object that is still in use! It will be freed when the editor is
   // destroyed.
   if (mInlineSpellChecker)
     mInlineSpellChecker->Cleanup(aDestroyingFrames);
@@ -1298,23 +1278,16 @@ NS_IMETHODIMP nsEditor::GetInlineSpellCh
 
   if (mDidPreDestroy) {
     // Don't allow people to get or create the spell checker once the editor
     // is going away.
     *aInlineSpellChecker = nsnull;
     return autoCreate ? NS_ERROR_NOT_AVAILABLE : NS_OK;
   }
 
-  // We don't want to show the spell checking UI if there are no spell check dictionaries available.
-  PRBool canSpell = mozInlineSpellChecker::CanEnableInlineSpellChecking();
-  if (!canSpell) {
-    *aInlineSpellChecker = nsnull;
-    return NS_ERROR_FAILURE;
-  }
-
   nsresult rv;
   if (!mInlineSpellChecker && autoCreate) {
     mInlineSpellChecker = do_CreateInstance(MOZ_INLINESPELLCHECKER_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   if (mInlineSpellChecker) {
     rv = mInlineSpellChecker->Init(this);
@@ -1323,59 +1296,27 @@ NS_IMETHODIMP nsEditor::GetInlineSpellCh
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   NS_IF_ADDREF(*aInlineSpellChecker = mInlineSpellChecker);
 
   return NS_OK;
 }
 
-NS_IMETHODIMP nsEditor::Observe(nsISupports* aSubj, const char *aTopic,
-                                const PRUnichar *aData)
-{
-  NS_ASSERTION(!strcmp(aTopic,
-                       SPELLCHECK_DICTIONARY_UPDATE_NOTIFICATION),
-               "Unexpected observer topic");
-
-  // When mozInlineSpellChecker::CanEnableInlineSpellChecking changes
-  SyncRealTimeSpell();
-
-  // When nsIEditorSpellCheck::GetCurrentDictionary changes
-  if (mInlineSpellChecker) {
-    // if the current dictionary is no longer available, find another one
-    nsCOMPtr<nsIEditorSpellCheck> editorSpellCheck;
-    mInlineSpellChecker->GetSpellChecker(getter_AddRefs(editorSpellCheck));
-    if (editorSpellCheck) {
-      nsCOMPtr<nsISpellChecker> spellChecker;
-      editorSpellCheck->GetSpellChecker(getter_AddRefs(spellChecker));
-      spellChecker->CheckCurrentDictionary();
-    }
-
-    // update the inline spell checker to reflect the new current dictionary
-    mInlineSpellChecker->SpellCheckRange(nsnull); // causes recheck
-  }
-
-  return NS_OK;
-}
-
 NS_IMETHODIMP nsEditor::SyncRealTimeSpell()
 {
   NS_TIME_FUNCTION;
 
   PRBool enable = GetDesiredSpellCheckState();
 
-  // Initializes mInlineSpellChecker
   nsCOMPtr<nsIInlineSpellChecker> spellChecker;
   GetInlineSpellChecker(enable, getter_AddRefs(spellChecker));
 
-  if (mInlineSpellChecker) {
-    // We might have a mInlineSpellChecker even if there are no dictionaries
-    // available since we don't destroy the mInlineSpellChecker when the last
-    // dictionariy is removed, but in that case spellChecker is null
-    mInlineSpellChecker->SetEnableRealTimeSpell(enable && spellChecker);
+  if (spellChecker) {
+    spellChecker->SetEnableRealTimeSpell(enable);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP nsEditor::SetSpellcheckUserOverride(PRBool enable)
 {
   mSpellcheckCheckboxState = enable ? eTriTrue : eTriFalse;
--- a/editor/libeditor/base/nsEditor.h
+++ b/editor/libeditor/base/nsEditor.h
@@ -61,17 +61,16 @@
 #include "nsIDOMElement.h"
 #include "nsSelectionState.h"
 #include "nsIEditorSpellCheck.h"
 #include "nsIInlineSpellChecker.h"
 #include "nsIDOMEventTarget.h"
 #include "nsStubMutationObserver.h"
 #include "nsIViewManager.h"
 #include "nsCycleCollectionParticipant.h"
-#include "nsIObserver.h"
 
 class nsIDOMCharacterData;
 class nsIDOMRange;
 class nsIPresShell;
 class ChangeAttributeTxn;
 class CreateElementTxn;
 class InsertElementTxn;
 class DeleteElementTxn;
@@ -96,17 +95,16 @@ class nsIDOMNSEvent;
 /** implementation of an editor object.  it will be the controller/focal point 
  *  for the main editor services. i.e. the GUIManager, publishing, transaction 
  *  manager, event interfaces. the idea for the event interfaces is to have them 
  *  delegate the actual commands to the editor independent of the XPFE implementation.
  */
 class nsEditor : public nsIEditor,
                  public nsIEditorIMESupport,
                  public nsSupportsWeakReference,
-                 public nsIObserver,
                  public nsIPhonetic
 {
 public:
 
   enum IterDirection
   {
     kIterForward,
     kIterBackward
@@ -150,19 +148,16 @@ public:
   already_AddRefed<nsIPresShell> GetPresShell();
   void NotifyEditorObservers();
 
   /* ------------ nsIEditor methods -------------- */
   NS_DECL_NSIEDITOR
   /* ------------ nsIEditorIMESupport methods -------------- */
   NS_DECL_NSIEDITORIMESUPPORT
   
-  /* ------------ nsIObserver methods -------------- */
-  NS_DECL_NSIOBSERVER
-
   // nsIPhonetic
   NS_DECL_NSIPHONETIC
 
 public:
 
   
   NS_IMETHOD InsertTextImpl(const nsAString& aStringToInsert, 
                                nsCOMPtr<nsIDOMNode> *aInOutNode, 
--- a/editor/txtsvc/public/nsISpellChecker.h
+++ b/editor/txtsvc/public/nsISpellChecker.h
@@ -39,19 +39,19 @@
 #define nsISpellChecker_h__
 
 #include "nsISupports.h"
 #include "nsTArray.h"
 
 #define NS_SPELLCHECKER_CONTRACTID "@mozilla.org/spellchecker;1"
 
 #define NS_ISPELLCHECKER_IID                    \
-{ /* 27bff957-b486-40ae-9f5d-af0cdd211868 */    \
-0x27bff957, 0xb486, 0x40ae, \
-  { 0x9f, 0x5d, 0xaf, 0x0c, 0xdd, 0x21, 0x18, 0x68 } }
+{ /* E75AC48C-E948-452E-8DB3-30FEE29FE3D2 */    \
+0xe75ac48c, 0xe948, 0x452e, \
+  { 0x8d, 0xb3, 0x30, 0xfe, 0xe2, 0x9f, 0xe3, 0xd2 } }
 
 class nsITextServicesDocument;
 class nsString;
 
 /**
  * A generic interface for a spelling checker.
  */
 class nsISpellChecker  : public nsISupports{
@@ -141,20 +141,14 @@ public:
 
   /**
    * Tells the spellchecker to use a specific dictionary.
    * @param aDictionary a string that is in the list returned
    * by GetDictionaryList() or an empty string. If aDictionary is 
    * empty string, spellchecker will be disabled.
    */
   NS_IMETHOD SetCurrentDictionary(const nsAString &aDictionary) = 0;
-
-  /**
-   * Call this on any change in installed dictionaries to ensure that the spell
-   * checker is not using a current dictionary which is no longer available.
-   */
-  NS_IMETHOD CheckCurrentDictionary() = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsISpellChecker, NS_ISPELLCHECKER_IID)
 
 #endif // nsISpellChecker_h__
 
--- a/extensions/spellcheck/Makefile.in
+++ b/extensions/spellcheck/Makefile.in
@@ -39,13 +39,9 @@ topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= spellchecker
 DIRS		= idl locales hunspell src
 
-ifdef ENABLE_TESTS
-DIRS		+= tests
-endif
-
 include $(topsrcdir)/config/rules.mk
--- a/extensions/spellcheck/hunspell/src/Makefile.in
+++ b/extensions/spellcheck/hunspell/src/Makefile.in
@@ -66,13 +66,11 @@ CPPSRCS         += affentry.cpp \
 
 # This variable is referenced in configure.in.  Make sure to change that file
 # too if you need to change this variable.
 DEFINES = -DHUNSPELL_STATIC
 endif
 
 include $(topsrcdir)/config/rules.mk
 
-INCLUDES        += -I$(topsrcdir)/extensions/spellcheck/src
-
 ifdef MOZ_NATIVE_HUNSPELL
 CXXFLAGS += $(MOZ_HUNSPELL_CFLAGS)
 endif
--- a/extensions/spellcheck/hunspell/src/mozHunspell.cpp
+++ b/extensions/spellcheck/hunspell/src/mozHunspell.cpp
@@ -36,17 +36,16 @@
  *                 Varga Daniel
  *                 Chris Halls
  *                 Rene Engelhard
  *                 Bram Moolenaar
  *                 Dafydd Jones
  *                 Harri Pitkanen
  *                 Andras Timar
  *                 Tor Lillqvist
- *                 Jesper Kristensen (mail@jesperkristensen.dk)
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -66,18 +65,16 @@
 #include "nsIFile.h"
 #include "nsDirectoryServiceUtils.h"
 #include "nsDirectoryServiceDefs.h"
 #include "mozISpellI18NManager.h"
 #include "nsICharsetConverterManager.h"
 #include "nsUnicharUtilCIID.h"
 #include "nsUnicharUtils.h"
 #include "nsCRT.h"
-#include "mozInlineSpellChecker.h"
-#include "mozilla/Services.h"
 #include <stdlib.h>
 #include "nsIMemoryReporter.h"
 
 static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
 static NS_DEFINE_CID(kUnicharUtilCID, NS_UNICHARUTIL_CID);
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(mozHunspell)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(mozHunspell)
@@ -120,17 +117,18 @@ NS_MEMORY_REPORTER_IMPLEMENT(Hunspell,
 nsresult
 mozHunspell::Init()
 {
   if (!mDictionaries.Init())
     return NS_ERROR_OUT_OF_MEMORY;
 
   LoadDictionaryList();
 
-  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+  nsCOMPtr<nsIObserverService> obs =
+    do_GetService("@mozilla.org/observer-service;1");
   if (obs) {
     obs->AddObserver(this, "profile-do-change", PR_TRUE);
   }
 
   mHunspellReporter = new NS_MEMORY_REPORTER_NAME(Hunspell);
   NS_RegisterMemoryReporter(mHunspellReporter);
 
   return NS_OK;
@@ -144,58 +142,60 @@ mozHunspell::~mozHunspell()
   NS_UnregisterMemoryReporter(mHunspellReporter);
 }
 
 /* attribute wstring dictionary; */
 NS_IMETHODIMP mozHunspell::GetDictionary(PRUnichar **aDictionary)
 {
   NS_ENSURE_ARG_POINTER(aDictionary);
 
+  if (mDictionary.IsEmpty())
+    return NS_ERROR_NOT_INITIALIZED;
+
   *aDictionary = ToNewUnicode(mDictionary);
   return *aDictionary ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
 }
 
 /* set the Dictionary.
  * This also Loads the dictionary and initializes the converter using the dictionaries converter
  */
 NS_IMETHODIMP mozHunspell::SetDictionary(const PRUnichar *aDictionary)
 {
   NS_ENSURE_ARG_POINTER(aDictionary);
 
+  if (mDictionary.Equals(aDictionary))
+    return NS_OK;
+
   nsIFile* affFile = mDictionaries.GetWeak(nsDependentString(aDictionary));
   if (!affFile)
     return NS_ERROR_FILE_NOT_FOUND;
 
   nsCAutoString dictFileName, affFileName;
 
   // XXX This isn't really good. nsIFile->NativePath isn't safe for all
   // character sets on Windows.
   // A better way would be to QI to nsILocalFile, and get a filehandle
   // from there. Only problem is that hunspell wants a path
 
   nsresult rv = affFile->GetNativePath(affFileName);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  if (mAffixFileName.Equals(affFileName.get()))
-    return NS_OK;
-
   dictFileName = affFileName;
   PRInt32 dotPos = dictFileName.RFindChar('.');
   if (dotPos == -1)
     return NS_ERROR_FAILURE;
 
   dictFileName.SetLength(dotPos);
   dictFileName.AppendLiteral(".dic");
 
   // SetDictionary can be called multiple times, so we might have a
   // valid mHunspell instance which needs cleaned up.
   delete mHunspell;
 
   mDictionary = aDictionary;
-  mAffixFileName = affFileName;
 
   mHunspell = new Hunspell(affFileName.get(),
                          dictFileName.get());
   if (!mHunspell)
     return NS_ERROR_OUT_OF_MEMORY;
 
   nsCOMPtr<nsICharsetConverterManager> ccm =
     do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
@@ -217,23 +217,16 @@ NS_IMETHODIMP mozHunspell::SetDictionary
   if (pos == -1)
     pos = mDictionary.FindChar('_');
 
   if (pos == -1)
     mLanguage.Assign(mDictionary);
   else
     mLanguage = Substring(mDictionary, 0, pos);
 
-  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
-  if (obs) {
-    obs->NotifyObservers(nsnull,
-                         SPELLCHECK_DICTIONARY_UPDATE_NOTIFICATION,
-                         nsnull);
-  }
-
   return NS_OK;
 }
 
 /* readonly attribute wstring language; */
 NS_IMETHODIMP mozHunspell::GetLanguage(PRUnichar **aLanguage)
 {
   NS_ENSURE_ARG_POINTER(aLanguage);
 
@@ -335,37 +328,28 @@ NS_IMETHODIMP mozHunspell::GetDictionary
   }
 
   *aDictionaries = ans.dics;
   *aCount = ans.count;
 
   return NS_OK;
 }
 
-static PLDHashOperator
-FindFirstString(const nsAString& aString, nsIFile* aFile, void* aClosure)
-{
-  nsAString *dic = (nsAString*) aClosure;
-  dic->Assign(aString);
-  return PL_DHASH_STOP;
-}
-
 void
 mozHunspell::LoadDictionaryList()
 {
   mDictionaries.Clear();
 
   nsresult rv;
 
   nsCOMPtr<nsIProperties> dirSvc =
     do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
   if (!dirSvc)
     return;
 
-  // find built in dictionaries
   nsCOMPtr<nsIFile> dictDir;
   rv = dirSvc->Get(DICTIONARY_SEARCH_DIRECTORY,
                    NS_GET_IID(nsIFile), getter_AddRefs(dictDir));
   if (NS_SUCCEEDED(rv)) {
     LoadDictionariesFromDir(dictDir);
   }
   else {
     // try to load gredir/dictionaries
@@ -383,77 +367,31 @@ mozHunspell::LoadDictionaryList()
                      NS_GET_IID(nsIFile), getter_AddRefs(appDir));
     PRBool equals;
     if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(appDir->Equals(greDir, &equals)) && !equals) {
       appDir->AppendNative(NS_LITERAL_CSTRING("dictionaries"));
       LoadDictionariesFromDir(appDir);
     }
   }
 
-  // find dictionaries from extensions requiring restart
   nsCOMPtr<nsISimpleEnumerator> dictDirs;
   rv = dirSvc->Get(DICTIONARY_SEARCH_DIRECTORY_LIST,
                    NS_GET_IID(nsISimpleEnumerator), getter_AddRefs(dictDirs));
   if (NS_FAILED(rv))
     return;
 
   PRBool hasMore;
   while (NS_SUCCEEDED(dictDirs->HasMoreElements(&hasMore)) && hasMore) {
     nsCOMPtr<nsISupports> elem;
     dictDirs->GetNext(getter_AddRefs(elem));
 
     dictDir = do_QueryInterface(elem);
     if (dictDir)
       LoadDictionariesFromDir(dictDir);
   }
-
-  // find dictionaries from restartless extensions
-  for (PRUint32 i = 0; i < mDynamicDirectories.Count(); i++) {
-    LoadDictionariesFromDir(mDynamicDirectories[i]);
-  }
-
-  // Now we have finished updating the list of dictionaries, update the current
-  // dictionary and any editors which may use it.
-  mozInlineSpellChecker::UpdateCanEnableInlineSpellChecking();
-
-  // If the current dictionary has gone, try to replace it with another
-  // dictionary of the same language
-  if (!mDictionary.IsEmpty()) {
-    rv = SetDictionary(mDictionary.get());
-    if (NS_SUCCEEDED(rv))
-      return;
-  }
-
-  // If we didn't find a dictionary equal to the current dictionary or we had
-  // no current dictionary, just pick an arbitrary dictionary.
-  nsAutoString firstDictionary;
-  mDictionaries.EnumerateRead(FindFirstString, &firstDictionary);
-  if (!firstDictionary.IsEmpty()) {
-    rv = SetDictionary(firstDictionary.get());
-    if (NS_SUCCEEDED(rv))
-      return;
-  }
-
-  // If there are no dictionaries, set no current dictionary
-  if (!mDictionary.IsEmpty()) {
-    delete mHunspell;
-    mHunspell = nsnull;
-    mDictionary.AssignLiteral("");
-    mAffixFileName.AssignLiteral("");
-    mLanguage.AssignLiteral("");
-    mDecoder = nsnull;
-    mEncoder = nsnull;
-
-    nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
-    if (obs) {
-      obs->NotifyObservers(nsnull,
-                           SPELLCHECK_DICTIONARY_UPDATE_NOTIFICATION,
-                           nsnull);
-    }
-  }
 }
 
 NS_IMETHODIMP
 mozHunspell::LoadDictionariesFromDir(nsIFile* aDir)
 {
   nsresult rv;
 
   PRBool check = PR_FALSE;
@@ -599,24 +537,8 @@ mozHunspell::Observe(nsISupports* aSubj,
 {
   NS_ASSERTION(!strcmp(aTopic, "profile-do-change"),
                "Unexpected observer topic");
 
   LoadDictionaryList();
 
   return NS_OK;
 }
-
-/* void addDirectory(in nsIFile dir); */
-NS_IMETHODIMP mozHunspell::AddDirectory(nsIFile *aDir)
-{
-  mDynamicDirectories.AppendObject(aDir);
-  LoadDictionaryList();
-  return NS_OK;
-}
-
-/* void removeDirectory(in nsIFile dir); */
-NS_IMETHODIMP mozHunspell::RemoveDirectory(nsIFile *aDir)
-{
-  mDynamicDirectories.RemoveObject(aDir);
-  LoadDictionaryList();
-  return NS_OK;
-}
--- a/extensions/spellcheck/hunspell/src/mozHunspell.h
+++ b/extensions/spellcheck/hunspell/src/mozHunspell.h
@@ -36,17 +36,16 @@
  *                 Varga Daniel
  *                 Chris Halls
  *                 Rene Engelhard
  *                 Bram Moolenaar
  *                 Dafydd Jones
  *                 Harri Pitkanen
  *                 Andras Timar
  *                 Tor Lillqvist
- *                 Jesper Kristensen (mail@jesperkristensen.dk)
  * 
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -60,17 +59,16 @@
 #ifndef mozHunspell_h__
 #define mozHunspell_h__
 
 #include <hunspell.hxx>
 #include "mozISpellCheckingEngine.h"
 #include "mozIPersonalDictionary.h"
 #include "nsString.h"
 #include "nsCOMPtr.h"
-#include "nsCOMArray.h"
 #include "nsIObserver.h"
 #include "nsIUnicodeEncoder.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsInterfaceHashtable.h"
 #include "nsWeakReference.h"
 #include "nsCycleCollectionParticipant.h"
 
 #define MOZ_HUNSPELL_CONTRACTID "@mozilla.org/spellchecker/engine;1"
@@ -106,19 +104,15 @@ protected:
   nsCOMPtr<mozIPersonalDictionary> mPersonalDictionary;
   nsCOMPtr<nsIUnicodeEncoder>      mEncoder; 
   nsCOMPtr<nsIUnicodeDecoder>      mDecoder; 
 
   // Hashtable matches dictionary name to .aff file
   nsInterfaceHashtable<nsStringHashKey, nsIFile> mDictionaries;
   nsString  mDictionary;
   nsString  mLanguage;
-  nsCString mAffixFileName;
-
-  // dynamic dirs used to search for dictionaries
-  nsCOMArray<nsIFile> mDynamicDirectories;
 
   Hunspell  *mHunspell;
 
   nsIMemoryReporter* mHunspellReporter;
 };
 
 #endif
--- a/extensions/spellcheck/idl/mozISpellCheckingEngine.idl
+++ b/extensions/spellcheck/idl/mozISpellCheckingEngine.idl
@@ -15,17 +15,16 @@
  * The Original Code is mozilla.org code.
  *
  * The Initial Developer of the Original Code is
  * David Einstein.
  * Portions created by the Initial Developer are Copyright (C) 2001
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
- *   Jesper Kristensen <mail@jesperkristensen.dk>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -36,41 +35,30 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 
 interface nsIFile;
 interface mozIPersonalDictionary;
 
-[scriptable, uuid(8ba643a4-7ddc-4662-b976-7ec123843f10)]
+[scriptable, uuid(6eb307d6-3567-481a-971a-feb666b8ae72)]
 
 /**
  * This interface represents a SpellChecker.
  */
 
 interface mozISpellCheckingEngine : nsISupports {
   /**
    * The name of the current dictionary
-   *
-   * Whenever getDictionaryList is not empty, this attribute contains a value
-   * from that list. Whenever getDictionaryList is empty, this attribute
-   * contains the empty string. Setting this attribute to a value not in
-   * getDictionaryList will throw NS_ERROR_FILE_NOT_FOUND.
-   *
-   * The spellcheck engine will send a notification with
-   * "spellcheck-dictionary-update" as topic when this changes.
    */
   attribute wstring dictionary;
 
   /**
    * The language this spellchecker is using when checking
-   *
-   * The spellcheck engine will send a notification with
-   * "spellcheck-dictionary-update" as topic when this changes.
    */
   readonly attribute wstring language;
 
   /**
    * Does the engine provide its own personal dictionary?
    */
   readonly attribute boolean providesPersonalDictionary;
 
@@ -96,45 +84,26 @@ interface mozISpellCheckingEngine : nsIS
 
   /**
    * Get the list of dictionaries
    */
   void getDictionaryList([array, size_is(count)] out wstring dictionaries, out PRUint32 count);
 
   /**
    * check a word
-   *
-   * The spellcheck engine will send a notification with
-   * "spellcheck-dictionary-update" as topic when this changes.
    */
   boolean check(in wstring word);
 
   /**
    * get a list of suggestions for a misspelled word
-   *
-   * The spellcheck engine will send a notification with
-   * "spellcheck-dictionary-update" as topic when this changes.
    */
   void suggest(in wstring word,[array, size_is(count)] out wstring suggestions, out PRUint32 count);
 
   /**
    * Load dictionaries from the specified dir
    */
   void loadDictionariesFromDir(in nsIFile dir);
-
-  /**
-   * Add dictionaries from a directory to the spell checker
-   */
-  void addDirectory(in nsIFile dir);
-
-  /**
-   * Remove dictionaries from a directory from the spell checker
-   */
-  void removeDirectory(in nsIFile dir);
 };
 
 %{C++
 #define DICTIONARY_SEARCH_DIRECTORY "DictD"
 #define DICTIONARY_SEARCH_DIRECTORY_LIST "DictDL"
-
-#define SPELLCHECK_DICTIONARY_UPDATE_NOTIFICATION \
-  "spellcheck-dictionary-update"
 %}
--- a/extensions/spellcheck/src/mozInlineSpellChecker.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellChecker.cpp
@@ -595,19 +595,19 @@ nsresult mozInlineSpellChecker::Cleanup(
 //    This function can be called to see if it seems likely that we can enable
 //    spellchecking before actually creating the InlineSpellChecking objects.
 //
 //    The problem is that we can't get the dictionary list without actually
 //    creating a whole bunch of spellchecking objects. This function tries to
 //    do that and caches the result so we don't have to keep allocating those
 //    objects if there are no dictionaries or spellchecking.
 //
-//    Whenever dictionaries are added or removed at runtime, this value must be
-//    updated before an observer notification is sent out about the change, to
-//    avoid editors getting a wrong cached result.
+//    This caching will prevent adding dictionaries at runtime if we start out
+//    with no dictionaries! Installing dictionaries as extensions will require
+//    a restart anyway, so it shouldn't be a problem.
 
 PRBool // static
 mozInlineSpellChecker::CanEnableInlineSpellChecking()
 {
   nsresult rv;
   if (gCanEnableSpellChecking == SpellCheck_Uninitialized) {
     gCanEnableSpellChecking = SpellCheck_NotAvailable;
 
@@ -620,22 +620,16 @@ mozInlineSpellChecker::CanEnableInlineSp
     NS_ENSURE_SUCCESS(rv, PR_FALSE);
 
     if (canSpellCheck)
       gCanEnableSpellChecking = SpellCheck_Available;
   }
   return (gCanEnableSpellChecking == SpellCheck_Available);
 }
 
-void // static
-mozInlineSpellChecker::UpdateCanEnableInlineSpellChecking()
-{
-  gCanEnableSpellChecking = SpellCheck_Uninitialized;
-}
-
 // mozInlineSpellChecker::RegisterEventListeners
 //
 //    The inline spell checker listens to mouse events and keyboard navigation+ //    events.
 
 nsresult
 mozInlineSpellChecker::RegisterEventListeners()
 {
   nsCOMPtr<nsIEditor> editor (do_QueryReferent(mEditor));
--- a/extensions/spellcheck/src/mozInlineSpellChecker.h
+++ b/extensions/spellcheck/src/mozInlineSpellChecker.h
@@ -224,20 +224,18 @@ private:
 public:
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_NSIEDITACTIONLISTENER
   NS_DECL_NSIINLINESPELLCHECKER
   NS_DECL_NSIDOMEVENTLISTENER
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(mozInlineSpellChecker, nsIDOMEventListener)
 
-  // returns true if there are any spell checking dictionaries available
+  // returns true if it looks likely that we can enable real-time spell checking
   static PRBool CanEnableInlineSpellChecking();
-  // update the cached value whenever the list of available dictionaries changes
-  static void UpdateCanEnableInlineSpellChecking();
 
   nsresult Blur(nsIDOMEvent* aEvent);
   nsresult MouseClick(nsIDOMEvent* aMouseEvent);
   nsresult KeyPress(nsIDOMEvent* aKeyEvent);
 
   mozInlineSpellChecker();
   virtual ~mozInlineSpellChecker();
 
--- a/extensions/spellcheck/src/mozSpellChecker.cpp
+++ b/extensions/spellcheck/src/mozSpellChecker.cpp
@@ -13,17 +13,16 @@
  *
  * The Original Code is Mozilla Spellchecker Component.
  *
  * The Initial Developer of the Original Code is David Einstein.
  * Portions created by the Initial Developer are Copyright (C) 2001
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s): David Einstein Deinst@world.std.com
- *   Jesper Kristensen <mail@jesperkristensen.dk>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -73,16 +72,19 @@ mozSpellChecker::~mozSpellChecker()
 }
 
 nsresult 
 mozSpellChecker::Init()
 {
   mPersonalDictionary = do_GetService("@mozilla.org/spellchecker/personaldictionary;1");
   
   mSpellCheckingEngine = nsnull;
+  mCurrentEngineContractId = nsnull;
+  mDictionariesMap.Init();
+  InitSpellCheckDictionaryMap();
 
   return NS_OK;
 } 
 
 NS_IMETHODIMP 
 mozSpellChecker::SetDocument(nsITextServicesDocument *aDoc, PRBool aFromStartofDoc)
 {
   mTsDoc = aDoc;
@@ -300,55 +302,45 @@ mozSpellChecker::GetPersonalDictionary(n
   nsAutoString word;
   while (NS_SUCCEEDED(words->HasMore(&hasMore)) && hasMore) {
     words->GetNext(word);
     aWordList->AppendElement(word);
   }
   return NS_OK;
 }
 
+struct AppendNewStruct
+{
+  nsTArray<nsString> *dictionaryList;
+  PRBool failed;
+};
+
+static PLDHashOperator
+AppendNewString(const nsAString& aString, nsCString*, void* aClosure)
+{
+  AppendNewStruct *ans = (AppendNewStruct*) aClosure;
+
+  if (!ans->dictionaryList->AppendElement(aString))
+  {
+    ans->failed = PR_TRUE;
+    return PL_DHASH_STOP;
+  }
+
+  return PL_DHASH_NEXT;
+}
+
 NS_IMETHODIMP 
 mozSpellChecker::GetDictionaryList(nsTArray<nsString> *aDictionaryList)
 {
-  nsresult rv;
-
-  // For catching duplicates
-  nsClassHashtable<nsStringHashKey, nsCString> dictionaries;
-  dictionaries.Init();
-
-  nsCOMArray<mozISpellCheckingEngine> spellCheckingEngines;
-  rv = GetEngineList(&spellCheckingEngines);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  for (PRUint32 i = 0; i < spellCheckingEngines.Count(); i++) {
-    nsCOMPtr<mozISpellCheckingEngine> engine = spellCheckingEngines[i];
+  AppendNewStruct ans = {aDictionaryList, PR_FALSE};
 
-    PRUint32 count = 0;
-    PRUnichar **words = NULL;
-    engine->GetDictionaryList(&words, &count);
-    for (PRUint32 k = 0; k < count; k++) {
-      nsAutoString dictName;
-
-      dictName.Assign(words[k]);
+  mDictionariesMap.EnumerateRead(AppendNewString, &ans);
 
-      // Skip duplicate dictionaries. Only take the first one
-      // for each name.
-      if (dictionaries.Get(dictName, NULL))
-        continue;
-
-      dictionaries.Put(dictName, NULL);
-
-      if (!aDictionaryList->AppendElement(dictName)) {
-        NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, words);
-        return NS_ERROR_OUT_OF_MEMORY;
-      }
-    }
-
-    NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, words);
-  }
+  if (ans.failed)
+    return NS_ERROR_OUT_OF_MEMORY;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP 
 mozSpellChecker::GetCurrentDictionary(nsAString &aDictionary)
 {
   nsXPIDLString dictname;
@@ -359,97 +351,54 @@ mozSpellChecker::GetCurrentDictionary(ns
   mSpellCheckingEngine->GetDictionary(getter_Copies(dictname));
   aDictionary = dictname;
   return NS_OK;
 }
 
 NS_IMETHODIMP 
 mozSpellChecker::SetCurrentDictionary(const nsAString &aDictionary)
 {
-  mSpellCheckingEngine = nsnull;
+  nsresult rv;
+  nsCString *contractId;
 
   if (aDictionary.IsEmpty()) {
+    mCurrentEngineContractId = nsnull;
+    mSpellCheckingEngine = nsnull;
     return NS_OK;
   }
 
-  nsresult rv;
-  nsCOMArray<mozISpellCheckingEngine> spellCheckingEngines;
-  rv = GetEngineList(&spellCheckingEngines);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  for (PRUint32 i = 0; i < spellCheckingEngines.Count(); i++) {
-    nsCOMPtr<mozISpellCheckingEngine> engine = spellCheckingEngines[i];
+  if (!mDictionariesMap.Get(aDictionary, &contractId)){
+    NS_WARNING("Dictionary not found");
+    return NS_ERROR_NOT_AVAILABLE;
+  }
 
-    rv = engine->SetDictionary(PromiseFlatString(aDictionary).get());
-    if (NS_SUCCEEDED(rv)) {
-      mSpellCheckingEngine = engine;
+  if (!mCurrentEngineContractId || !mCurrentEngineContractId->Equals(*contractId)){
+    mSpellCheckingEngine = do_GetService(contractId->get(), &rv);
+    if (NS_FAILED(rv))
+      return rv;
 
-      nsCOMPtr<mozIPersonalDictionary> personalDictionary = do_GetService("@mozilla.org/spellchecker/personaldictionary;1");
-      mSpellCheckingEngine->SetPersonalDictionary(personalDictionary.get());
-
-      return NS_OK;
-    }
+    mCurrentEngineContractId = contractId;
   }
 
-  // We could not find any engine with the requested dictionary
-  return NS_ERROR_NOT_AVAILABLE;
-}
-
-NS_IMETHODIMP 
-mozSpellChecker::CheckCurrentDictionary()
-{
-  // Check if the current engine has any dictionaries available. If not,
-  // the last dictionary has just been uninstalled, and we need to stop using
-  // the engine.
-  if (mSpellCheckingEngine) {
-    nsXPIDLString dictname;
-
-    mSpellCheckingEngine->GetDictionary(getter_Copies(dictname));
-
-    // We still have a dictionary, so keep using that.
-    if (!dictname.IsEmpty()) {
-      return NS_OK;
-    }
-
-    // Our current dictionary has gone, so we cannot use the engine anymore.
-    mSpellCheckingEngine = nsnull;
+  nsresult res;
+  res = mSpellCheckingEngine->SetDictionary(PromiseFlatString(aDictionary).get());
+  if(NS_FAILED(res)){
+    NS_WARNING("Dictionary load failed");
+    return res;
   }
 
-  // We have no current engine. Pick one.
-  nsresult rv;
-  nsCOMArray<mozISpellCheckingEngine> spellCheckingEngines;
-  rv = GetEngineList(&spellCheckingEngines);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  for (PRUint32 i = 0; i < spellCheckingEngines.Count(); i++) {
-    nsCOMPtr<mozISpellCheckingEngine> engine = spellCheckingEngines[i];
-
-    nsXPIDLString dictname;
-
-    engine->GetDictionary(getter_Copies(dictname));
-
-    if (!dictname.IsEmpty()) {
-      mSpellCheckingEngine = engine;
+  mSpellCheckingEngine->SetPersonalDictionary(mPersonalDictionary);
 
-      nsCOMPtr<mozIPersonalDictionary> personalDictionary = do_GetService("@mozilla.org/spellchecker/personaldictionary;1");
-      mSpellCheckingEngine->SetPersonalDictionary(personalDictionary.get());
-
-      nsXPIDLString language;
-      nsresult rv;
-      nsCOMPtr<mozISpellI18NManager> serv = do_GetService("@mozilla.org/spellchecker/i18nmanager;1", &rv);
-      if(serv && NS_SUCCEEDED(rv)) {
-        serv->GetUtil(language.get(), getter_AddRefs(mConverter));
-      }
-
-      return NS_OK;
-    }
+  nsXPIDLString language;
+  
+  nsCOMPtr<mozISpellI18NManager> serv(do_GetService("@mozilla.org/spellchecker/i18nmanager;1", &res));
+  if(serv && NS_SUCCEEDED(res)){
+    res = serv->GetUtil(language.get(),getter_AddRefs(mConverter));
   }
-
-  // There are no dictionaries available
-  return NS_OK;
+  return res;
 }
 
 nsresult
 mozSpellChecker::SetupDoc(PRInt32 *outBlockOffset)
 {
   nsresult  rv;
 
   nsITextServicesDocument::TSDBlockSelectionStatus blockStatus;
@@ -523,20 +472,21 @@ mozSpellChecker::GetCurrentBlockIndex(ns
   } while (NS_SUCCEEDED(result) && !isDone);
   
   *outBlockIndex = blockIndex;
 
   return result;
 }
 
 nsresult
-mozSpellChecker::GetEngineList(nsCOMArray<mozISpellCheckingEngine>* aSpellCheckingEngines)
+mozSpellChecker::InitSpellCheckDictionaryMap()
 {
   nsresult rv;
   PRBool hasMoreEngines;
+  nsTArray<nsCString> contractIds;
 
   nsCOMPtr<nsICategoryManager> catMgr = do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
   if (!catMgr)
     return NS_ERROR_NULL_POINTER;
 
   nsCOMPtr<nsISimpleEnumerator> catEntries;
 
   // Get contract IDs of registrated external spell-check engines and
@@ -553,29 +503,57 @@ mozSpellChecker::GetEngineList(nsCOMArra
     if (NS_FAILED(rv))
       return rv;
 
     nsCString contractId;
     rv = entry->GetData(contractId);
     if (NS_FAILED(rv))
       return rv;
 
+    contractIds.AppendElement(contractId);
+  }
+
+  contractIds.AppendElement(NS_LITERAL_CSTRING(DEFAULT_SPELL_CHECKER));
+
+  // Retrieve dictionaries from all available spellcheckers and
+  // fill mDictionariesMap hash (only the first dictionary with the
+  // each name is used).
+  for (PRUint32 i=0;i < contractIds.Length();i++){
+    PRUint32 count,k;
+    PRUnichar **words;
+
+    const nsCString& contractId = contractIds[i];
+
     // Try to load spellchecker engine. Ignore errors silently
     // except for the last one (HunSpell).
     nsCOMPtr<mozISpellCheckingEngine> engine =
       do_GetService(contractId.get(), &rv);
-    if (NS_SUCCEEDED(rv)) {
-      aSpellCheckingEngines->AppendObject(engine);
+    if (NS_FAILED(rv)){
+      // Fail if not succeeded to load HunSpell. Ignore errors
+      // for external spellcheck engines.
+      if (i==contractIds.Length()-1){
+        return rv;
+      }
+
+      continue;
     }
-  }
+
+    engine->GetDictionaryList(&words,&count);
+    for(k=0;k<count;k++){
+      nsAutoString dictName;
 
-  // Try to load HunSpell spellchecker engine.
-  nsCOMPtr<mozISpellCheckingEngine> engine =
-    do_GetService(DEFAULT_SPELL_CHECKER, &rv);
-  if (NS_FAILED(rv)) {
-    // Fail if not succeeded to load HunSpell. Ignore errors
-    // for external spellcheck engines.
-    return rv;
+      dictName.Assign(words[k]);
+
+      nsCString dictCName = NS_ConvertUTF16toUTF8(dictName);
+
+      // Skip duplicate dictionaries. Only take the first one
+      // for each name.
+      if (mDictionariesMap.Get(dictName, NULL))
+        continue;
+
+      mDictionariesMap.Put(dictName, new nsCString(contractId));
+    }
+
+    NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, words);
   }
-  aSpellCheckingEngines->AppendObject(engine);
 
   return NS_OK;
 }
--- a/extensions/spellcheck/src/mozSpellChecker.h
+++ b/extensions/spellcheck/src/mozSpellChecker.h
@@ -15,17 +15,16 @@
  * The Original Code is Mozilla Spellchecker Component.
  *
  * The Initial Developer of the Original Code is
  * David Einstein.
  * Portions created by the Initial Developer are Copyright (C) 2001
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s): David Einstein Deinst@world.std.com
- *   Jesper Kristensen <mail@jesperkristensen.dk>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -35,17 +34,16 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef mozSpellChecker_h__
 #define mozSpellChecker_h__
 
 #include "nsCOMPtr.h"
-#include "nsCOMArray.h"
 #include "nsISpellChecker.h"
 #include "nsString.h"
 #include "nsITextServicesDocument.h"
 #include "mozIPersonalDictionary.h"
 #include "mozISpellCheckingEngine.h"
 #include "nsClassHashtable.h"
 #include "nsVoidArray.h"
 #include "nsTArray.h"
@@ -72,25 +70,29 @@ public:
 
   NS_IMETHOD AddWordToPersonalDictionary(const nsAString &aWord);
   NS_IMETHOD RemoveWordFromPersonalDictionary(const nsAString &aWord);
   NS_IMETHOD GetPersonalDictionary(nsTArray<nsString> *aWordList);
 
   NS_IMETHOD GetDictionaryList(nsTArray<nsString> *aDictionaryList);
   NS_IMETHOD GetCurrentDictionary(nsAString &aDictionary);
   NS_IMETHOD SetCurrentDictionary(const nsAString &aDictionary);
-  NS_IMETHOD CheckCurrentDictionary();
 
 protected:
   nsCOMPtr<mozISpellI18NUtil> mConverter;
   nsCOMPtr<nsITextServicesDocument> mTsDoc;
   nsCOMPtr<mozIPersonalDictionary> mPersonalDictionary;
 
+  // Hastable maps directory name to the spellchecker contract ID
+  nsClassHashtable<nsStringHashKey, nsCString> mDictionariesMap;
+
+  nsString mDictionaryName;
+  nsCString *mCurrentEngineContractId;
   nsCOMPtr<mozISpellCheckingEngine>  mSpellCheckingEngine;
   PRBool mFromStart;
 
   nsresult SetupDoc(PRInt32 *outBlockOffset);
 
   nsresult GetCurrentBlockIndex(nsITextServicesDocument *aDoc, PRInt32 *outBlockIndex);
 
-  nsresult GetEngineList(nsCOMArray<mozISpellCheckingEngine> *aDictionaryList);
+  nsresult InitSpellCheckDictionaryMap();
 };
 #endif // mozSpellChecker_h__
--- a/extensions/spellcheck/src/mozSpellCheckerFactory.cpp
+++ b/extensions/spellcheck/src/mozSpellCheckerFactory.cpp
@@ -54,17 +54,49 @@ 0x8227F019, 0xAFC7, 0x461e,             
 0x9fe5d975, 0x9bd, 0x44aa,                      \
 { 0xa0, 0x1a, 0x66, 0x40, 0x2e, 0xa2, 0x86, 0x57} }
 
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(mozHunspell, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(mozHunspellDirProvider)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(mozSpellChecker, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(mozPersonalDictionary, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(mozSpellI18NManager)
-NS_GENERIC_FACTORY_CONSTRUCTOR(mozInlineSpellChecker)
+
+// This special constructor for the inline spell checker asks the inline
+// spell checker if we can create spell checking objects at all (ie, if there
+// are any dictionaries loaded) before trying to create one. The static
+// CanEnableInlineSpellChecking caches the value so this will be faster (we
+// have to run this code for every edit box we create, as well as for every
+// right click in those edit boxes).
+static nsresult
+mozInlineSpellCheckerConstructor(nsISupports *aOuter, REFNSIID aIID,
+                                 void **aResult)
+{
+  if (! mozInlineSpellChecker::CanEnableInlineSpellChecking())
+    return NS_ERROR_FAILURE;
+
+  nsresult rv;
+
+  *aResult = NULL;
+  if (NULL != aOuter) {
+    rv = NS_ERROR_NO_AGGREGATION;
+    return rv;
+  }
+
+  mozInlineSpellChecker* inst = new mozInlineSpellChecker();
+  if (NULL == inst) {
+    rv = NS_ERROR_OUT_OF_MEMORY;
+    return rv;
+  }
+  NS_ADDREF(inst);
+  rv = inst->QueryInterface(aIID, aResult);
+  NS_RELEASE(inst);
+
+  return rv;
+}
 
 NS_DEFINE_NAMED_CID(MOZ_HUNSPELL_CID);
 NS_DEFINE_NAMED_CID(HUNSPELLDIRPROVIDER_CID);
 NS_DEFINE_NAMED_CID(NS_SPELLCHECKER_CID);
 NS_DEFINE_NAMED_CID(MOZ_PERSONALDICTIONARY_CID);
 NS_DEFINE_NAMED_CID(MOZ_SPELLI18NMANAGER_CID);
 NS_DEFINE_NAMED_CID(MOZ_INLINESPELLCHECKER_CID);
 
deleted file mode 100644
--- a/extensions/spellcheck/tests/Makefile.in
+++ /dev/null
@@ -1,48 +0,0 @@
-#
-# ***** BEGIN LICENSE BLOCK *****
-# Version: MPL 1.1/GPL 2.0/LGPL 2.1
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-# http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Original Code is mozilla.org code.
-#
-# The Initial Developer of the Original Code is
-# Netscape Communications Corporation.
-# Portions created by the Initial Developer are Copyright (C) 1998
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either of the GNU General Public License Version 2 or later (the "GPL"),
-# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-DEPTH		= ../../..
-topsrcdir	= @top_srcdir@
-srcdir		= @srcdir@
-VPATH		= @srcdir@
-relativesrcdir  = extensions/spellcheck/tests
-
-include $(DEPTH)/config/autoconf.mk
-
-DIRS		= chrome
-
-include $(topsrcdir)/config/rules.mk
deleted file mode 100644
--- a/extensions/spellcheck/tests/chrome/Makefile.in
+++ /dev/null
@@ -1,54 +0,0 @@
-#
-# ***** BEGIN LICENSE BLOCK *****
-# Version: MPL 1.1/GPL 2.0/LGPL 2.1
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-# http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Original Code is mozilla.org code.
-#
-# The Initial Developer of the Original Code is
-# Netscape Communications Corporation.
-# Portions created by the Initial Developer are Copyright (C) 1998
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either of the GNU General Public License Version 2 or later (the "GPL"),
-# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-DEPTH		= ../../../..
-topsrcdir	= @top_srcdir@
-srcdir		= @srcdir@
-VPATH		= @srcdir@
-relativesrcdir  = extensions/spellcheck/tests/chrome
-
-include $(DEPTH)/config/autoconf.mk
-
-DIRS = base map
-
-include $(topsrcdir)/config/rules.mk
-
-_TEST_FILES = 	test_add_remove_dictionaries.xul \
-				$(NULL)
-
-libs:: $(_TEST_FILES)
-	$(INSTALL) $^ $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
deleted file mode 100644
--- a/extensions/spellcheck/tests/chrome/base/Makefile.in
+++ /dev/null
@@ -1,52 +0,0 @@
-#
-# ***** BEGIN LICENSE BLOCK *****
-# Version: MPL 1.1/GPL 2.0/LGPL 2.1
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-# http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Original Code is mozilla.org code.
-#
-# The Initial Developer of the Original Code is
-# Netscape Communications Corporation.
-# Portions created by the Initial Developer are Copyright (C) 1998
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either of the GNU General Public License Version 2 or later (the "GPL"),
-# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-DEPTH		= ../../../../..
-topsrcdir	= @top_srcdir@
-srcdir		= @srcdir@
-VPATH		= @srcdir@
-relativesrcdir  = extensions/spellcheck/tests/chrome/base
-
-include $(DEPTH)/config/autoconf.mk
-include $(topsrcdir)/config/rules.mk
-
-_TEST_FILES = 	base_utf.dic \
-				base_utf.aff \
-				$(NULL)
-
-libs:: $(_TEST_FILES)
-	$(INSTALL) $^ $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
deleted file mode 100644
--- a/extensions/spellcheck/tests/chrome/base/base_utf.aff
+++ /dev/null
@@ -1,198 +0,0 @@
-# OpenOffice.org’s en_US.aff file
-# with Unicode apostrophe: ’
-
-SET UTF-8
-TRY esianrtolcdugmphbyfvkwzESIANRTOLCDUGMPHBYFVKWZ'
-
-MAXNGRAMSUGS 1
-WORDCHARS .'’
-
-PFX A Y 1
-PFX A   0     re         .
-
-PFX I Y 1
-PFX I   0     in         .
-
-PFX U Y 1
-PFX U   0     un         .
-
-PFX C Y 1
-PFX C   0     de          .
-
-PFX E Y 1
-PFX E   0     dis         .
-
-PFX F Y 1
-PFX F   0     con         .
-
-PFX K Y 1
-PFX K   0     pro         .
-
-SFX V N 2
-SFX V   e     ive        e
-SFX V   0     ive        [^e]
-
-SFX N Y 3
-SFX N   e     ion        e
-SFX N   y     ication    y 
-SFX N   0     en         [^ey] 
-
-SFX X Y 3
-SFX X   e     ions       e
-SFX X   y     ications   y
-SFX X   0     ens        [^ey]
-
-SFX H N 2
-SFX H   y     ieth       y
-SFX H   0     th         [^y] 
-
-SFX Y Y 1
-SFX Y   0     ly         .
-
-SFX G Y 2
-SFX G   e     ing        e
-SFX G   0     ing        [^e] 
-
-SFX J Y 2
-SFX J   e     ings       e
-SFX J   0     ings       [^e]
-
-SFX D Y 4
-SFX D   0     d          e
-SFX D   y     ied        [^aeiou]y
-SFX D   0     ed         [^ey]
-SFX D   0     ed         [aeiou]y
-
-SFX T N 4
-SFX T   0     st         e
-SFX T   y     iest       [^aeiou]y
-SFX T   0     est        [aeiou]y
-SFX T   0     est        [^ey]
-
-SFX R Y 4
-SFX R   0     r          e
-SFX R   y     ier        [^aeiou]y
-SFX R   0     er         [aeiou]y
-SFX R   0     er         [^ey]
-
-SFX Z Y 4
-SFX Z   0     rs         e
-SFX Z   y     iers       [^aeiou]y
-SFX Z   0     ers        [aeiou]y
-SFX Z   0     ers        [^ey]
-
-SFX S Y 4
-SFX S   y     ies        [^aeiou]y
-SFX S   0     s          [aeiou]y
-SFX S   0     es         [sxzh]
-SFX S   0     s          [^sxzhy]
-
-SFX P Y 3
-SFX P   y     iness      [^aeiou]y
-SFX P   0     ness       [aeiou]y
-SFX P   0     ness       [^y]
-
-SFX M Y 1
-SFX M   0     's         .
-
-SFX B Y 3
-SFX B   0     able       [^aeiou]
-SFX B   0     able       ee
-SFX B   e     able       [^aeiou]e
-
-SFX L Y 1
-SFX L   0     ment       .
-
-REP 88
-REP a ei
-REP ei a
-REP a ey
-REP ey a
-REP ai ie
-REP ie ai
-REP are air
-REP are ear
-REP are eir
-REP air are
-REP air ere
-REP ere air
-REP ere ear
-REP ere eir
-REP ear are
-REP ear air
-REP ear ere
-REP eir are
-REP eir ere
-REP ch te
-REP te ch
-REP ch ti
-REP ti ch
-REP ch tu
-REP tu ch
-REP ch s
-REP s ch
-REP ch k
-REP k ch
-REP f ph
-REP ph f
-REP gh f
-REP f gh
-REP i igh
-REP igh i
-REP i uy
-REP uy i
-REP i ee
-REP ee i
-REP j di
-REP di j
-REP j gg
-REP gg j
-REP j ge
-REP ge j
-REP s ti
-REP ti s
-REP s ci
-REP ci s
-REP k cc
-REP cc k
-REP k qu
-REP qu k
-REP kw qu
-REP o eau
-REP eau o
-REP o ew
-REP ew o
-REP oo ew
-REP ew oo
-REP ew ui
-REP ui ew
-REP oo ui
-REP ui oo
-REP ew u
-REP u ew
-REP oo u
-REP u oo
-REP u oe
-REP oe u
-REP u ieu
-REP ieu u
-REP ue ew
-REP ew ue
-REP uff ough
-REP oo ieu
-REP ieu oo
-REP ier ear
-REP ear ier
-REP ear air
-REP air ear
-REP w qu
-REP qu w
-REP z ss
-REP ss z
-REP shun tion
-REP shun sion
-REP shun cion
-McDonalds’sá/w
-McDonald’sszá/g3)	st:McDonald’s	po:noun_prs	is:TRANS
-McDonald’sszal/g4)	st:McDonald’s	po:noun_prs	is:INSTR
-McDonald’ssal/w
deleted file mode 100644
--- a/extensions/spellcheck/tests/chrome/base/base_utf.dic
+++ /dev/null
@@ -1,29 +0,0 @@
-28
-created/U
-create/XKVNGADS
-imply/GNSDX
-natural/PUY
-like/USPBY
-convey/BDGS
-look/GZRDS
-text
-hello
-said
-sawyer
-NASA
-rotten
-day
-tomorrow
-seven
-FAQ/SM
-can’t
-doesn’t
-etc
-won’t
-lip
-text
-horrifying
-speech
-suggest
-uncreate/V
-Hunspell
deleted file mode 100644
--- a/extensions/spellcheck/tests/chrome/map/Makefile.in
+++ /dev/null
@@ -1,52 +0,0 @@
-#
-# ***** BEGIN LICENSE BLOCK *****
-# Version: MPL 1.1/GPL 2.0/LGPL 2.1
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-# http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Original Code is mozilla.org code.
-#
-# The Initial Developer of the Original Code is
-# Netscape Communications Corporation.
-# Portions created by the Initial Developer are Copyright (C) 1998
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either of the GNU General Public License Version 2 or later (the "GPL"),
-# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-DEPTH		= ../../../../..
-topsrcdir	= @top_srcdir@
-srcdir		= @srcdir@
-VPATH		= @srcdir@
-relativesrcdir  = extensions/spellcheck/tests/chrome/map
-
-include $(DEPTH)/config/autoconf.mk
-include $(topsrcdir)/config/rules.mk
-
-_TEST_FILES = 	maputf.dic \
-				maputf.aff \
-				$(NULL)
-
-libs:: $(_TEST_FILES)
-	$(INSTALL) $^ $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
deleted file mode 100644
--- a/extensions/spellcheck/tests/chrome/map/maputf.aff
+++ /dev/null
@@ -1,11 +0,0 @@
-# With MAP suggestion, Hunspell can add missing accents to a word.
-
-SET UTF-8
-
-# switch off ngram suggestion for testing
-MAXNGRAMSUGS 0
-
-MAP 3
-MAP uúü
-MAP öóo
-MAP ß(ss)
deleted file mode 100644
--- a/extensions/spellcheck/tests/chrome/map/maputf.dic
+++ /dev/null
@@ -1,4 +0,0 @@
-3
-Frühstück
-tükörfúró
-groß
deleted file mode 100644
--- a/extensions/spellcheck/tests/chrome/test_add_remove_dictionaries.xul
+++ /dev/null
@@ -1,110 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window title="Add and remove dictionaries test"
-        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        onload="RunTest();">
-  <title>Add and remove dictionaries test</title>
-
-  <script type="application/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
-
-  <script type="application/javascript">
-  <![CDATA[
-SimpleTest.waitForExplicitFinish();
-
-function getMisspelledWords(editor) {
-  return editor.selectionController.getSelection(Components.interfaces.nsISelectionController.SELECTION_SPELLCHECK).toString();
-}
-
-function getDictionaryList(editor) {
-  var spellchecker = editor.getInlineSpellChecker(true).spellChecker;
-  var o1 = {};
-  spellchecker.GetDictionaryList(o1, {});
-  return o1.value;
-}
-
-function getCurrentDictionary(editor) {
-  var spellchecker = editor.getInlineSpellChecker(true).spellChecker;
-  return spellchecker.GetCurrentDictionary();
-}
-
-function setCurrentDictionary(editor, dictionary) {
-  var spellchecker = editor.getInlineSpellChecker(true).spellChecker;
-  spellchecker.SetCurrentDictionary(dictionary);
-}
-
-function RunTest() {
-  var editor = document.getElementById('textbox').editor;
-
-  var dir = Components.classes["@mozilla.org/file/directory_service;1"].
-            getService(Components.interfaces.nsIProperties).
-            get("CurWorkD", Components.interfaces.nsIFile);
-  dir.append("chrome");
-  dir.append("extensions");
-  dir.append("spellcheck");
-  dir.append("tests");
-  dir.append("chrome");
-
-  var hunspell = Components
-    .classes["@mozilla.org/spellchecker/engine;1"]
-    .getService(Components.interfaces.mozISpellCheckingEngine);
-
-  // install base dictionary
-  var base = dir.clone();
-  base.append("base");
-  ok(base.exists());
-  hunspell.addDirectory(base);
-
-  // install map dictionary
-  var map = dir.clone();
-  map.append("map");
-  ok(map.exists());
-  hunspell.addDirectory(map);
-
-  // test that base and map dictionaries are available
-  var dicts = getDictionaryList(editor);
-  isnot(dicts.indexOf("base_utf"), -1, "base is available");
-  isnot(dicts.indexOf("maputf"), -1, "map is available");
-
-  // select base dictionary
-  setCurrentDictionary(editor, "base_utf");
-
-  SimpleTest.executeSoon(function() {
-    // test that base dictionary is in use
-    is(getMisspelledWords(editor), "Frühstück" + "qwertyu", "base misspellings");
-    is(getCurrentDictionary(editor), "base_utf", "current dictionary");
-
-    // select map dictionary
-    setCurrentDictionary(editor, "maputf");
-
-    SimpleTest.executeSoon(function() {
-      // test that map dictionary is in use
-      is(getMisspelledWords(editor), "created" + "imply" + "tomorrow" + "qwertyu", "map misspellings");
-      is(getCurrentDictionary(editor), "maputf", "current dictionary");
-
-      // uninstall map dictionary
-      hunspell.removeDirectory(map);
-
-      SimpleTest.executeSoon(function() {
-        // test that map dictionary is not in use
-        isnot(getMisspelledWords(editor), "created" + "imply" + "tomorrow" + "qwertyu", "map misspellings");
-        isnot(getCurrentDictionary(editor), "maputf", "current dictionary");
-
-        // test that base dictionary is available and map dictionary is unavailable
-        var dicts = getDictionaryList(editor);
-        isnot(dicts.indexOf("base_utf"), -1, "base is available");
-        is(dicts.indexOf("maputf"), -1, "map is unavailable");
-
-        // uninstall base dictionary
-        hunspell.removeDirectory(base);
-
-        SimpleTest.finish();
-      });
-    });
-  });
-}
-  ]]>
-  </script>
-  <textbox id="textbox" spellcheck="true" value="created imply Frühstück tomorrow qwertyu"/>
-</window>