зеркало из https://github.com/mozilla/gecko-dev.git
Bug 880864 - User dictionary (persdict.dat) read on main thread. r=Ehsan,r=mayhemer
This commit is contained in:
Родитель
79a37b2311
Коммит
bc9c36d0be
|
@ -17,6 +17,8 @@
|
|||
#include "nsNetUtil.h"
|
||||
#include "nsStringEnumerator.h"
|
||||
#include "nsUnicharInputStream.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#define MOZ_PERSONAL_DICT_NAME "persdict.dat"
|
||||
|
||||
|
@ -47,8 +49,33 @@ NS_INTERFACE_MAP_END
|
|||
|
||||
NS_IMPL_CYCLE_COLLECTION_1(mozPersonalDictionary, mEncoder)
|
||||
|
||||
class mozPersonalDictionaryLoader MOZ_FINAL : public nsRunnable
|
||||
{
|
||||
public:
|
||||
mozPersonalDictionaryLoader(mozPersonalDictionary *dict) : mDict(dict)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
mDict->SyncLoad();
|
||||
|
||||
// Release refptr on the mainthread
|
||||
NS_DispatchToMainThread(this);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<mozPersonalDictionary> mDict;
|
||||
};
|
||||
|
||||
mozPersonalDictionary::mozPersonalDictionary()
|
||||
: mDirty(false)
|
||||
: mDirty(false),
|
||||
mIsLoaded(false),
|
||||
mMonitor("mozPersonalDictionary::mMonitor")
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -69,39 +96,99 @@ nsresult mozPersonalDictionary::Init()
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
Load();
|
||||
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void Load (); */
|
||||
void mozPersonalDictionary::WaitForLoad()
|
||||
{
|
||||
if (mIsLoaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
mozilla::MonitorAutoLock mon(mMonitor);
|
||||
|
||||
if (!mIsLoaded) {
|
||||
mon.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP mozPersonalDictionary::Load()
|
||||
{
|
||||
nsresult rv;
|
||||
mozilla::MonitorAutoLock mon(mMonitor);
|
||||
|
||||
if (mIsLoaded) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIRunnable> runnable = new mozPersonalDictionaryLoader(this);
|
||||
|
||||
rv = target->Dispatch(runnable, NS_DISPATCH_NORMAL);
|
||||
return rv;
|
||||
}
|
||||
|
||||
void mozPersonalDictionary::SyncLoad()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
mozilla::MonitorAutoLock mon(mMonitor);
|
||||
|
||||
if (mIsLoaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
SyncLoadInternal();
|
||||
mIsLoaded = true;
|
||||
mon.Notify();
|
||||
}
|
||||
|
||||
void mozPersonalDictionary::SyncLoadInternal()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
//FIXME Deinst -- get dictionary name from prefs;
|
||||
nsresult res;
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIFile> theFile;
|
||||
bool dictExists;
|
||||
|
||||
res = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(theFile));
|
||||
if(NS_FAILED(res)) return res;
|
||||
if(!theFile)return NS_ERROR_FAILURE;
|
||||
res = theFile->Append(NS_LITERAL_STRING(MOZ_PERSONAL_DICT_NAME));
|
||||
if(NS_FAILED(res)) return res;
|
||||
res = theFile->Exists(&dictExists);
|
||||
if(NS_FAILED(res)) return res;
|
||||
rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(theFile));
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!theFile) {
|
||||
return;
|
||||
}
|
||||
|
||||
rv = theFile->Append(NS_LITERAL_STRING(MOZ_PERSONAL_DICT_NAME));
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
rv = theFile->Exists(&dictExists);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dictExists) {
|
||||
// Nothing is really wrong...
|
||||
return NS_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
nsCOMPtr<nsIInputStream> inStream;
|
||||
NS_NewLocalFileInputStream(getter_AddRefs(inStream), theFile);
|
||||
|
||||
nsCOMPtr<nsIUnicharInputStream> convStream;
|
||||
res = nsSimpleUnicharStreamFactory::GetInstance()->
|
||||
rv = nsSimpleUnicharStreamFactory::GetInstance()->
|
||||
CreateInstanceFromUTF8Stream(inStream, getter_AddRefs(convStream));
|
||||
if(NS_FAILED(res)) return res;
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we're rereading to get rid of the old data -- we shouldn't have any, but...
|
||||
mDictionaryTable.Clear();
|
||||
|
||||
|
@ -123,8 +210,6 @@ NS_IMETHODIMP mozPersonalDictionary::Load()
|
|||
}
|
||||
} while(!done);
|
||||
mDirty = false;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// A little helper function to add the key to the list.
|
||||
|
@ -143,6 +228,7 @@ NS_IMETHODIMP mozPersonalDictionary::Save()
|
|||
nsCOMPtr<nsIFile> theFile;
|
||||
nsresult res;
|
||||
|
||||
WaitForLoad();
|
||||
if(!mDirty) return NS_OK;
|
||||
|
||||
//FIXME Deinst -- get dictionary name from prefs;
|
||||
|
@ -188,6 +274,8 @@ NS_IMETHODIMP mozPersonalDictionary::GetWordList(nsIStringEnumerator **aWords)
|
|||
NS_ENSURE_ARG_POINTER(aWords);
|
||||
*aWords = nullptr;
|
||||
|
||||
WaitForLoad();
|
||||
|
||||
nsTArray<nsString> *array = new nsTArray<nsString>(mDictionaryTable.Count());
|
||||
if (!array)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
@ -205,6 +293,8 @@ NS_IMETHODIMP mozPersonalDictionary::Check(const char16_t *aWord, const char16_t
|
|||
NS_ENSURE_ARG_POINTER(aWord);
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
|
||||
WaitForLoad();
|
||||
|
||||
*aResult = (mDictionaryTable.GetEntry(aWord) || mIgnoreTable.GetEntry(aWord));
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -212,6 +302,8 @@ NS_IMETHODIMP mozPersonalDictionary::Check(const char16_t *aWord, const char16_t
|
|||
/* void AddWord (in wstring word); */
|
||||
NS_IMETHODIMP mozPersonalDictionary::AddWord(const char16_t *aWord, const char16_t *aLang)
|
||||
{
|
||||
WaitForLoad();
|
||||
|
||||
mDictionaryTable.PutEntry(aWord);
|
||||
mDirty = true;
|
||||
return NS_OK;
|
||||
|
@ -220,6 +312,8 @@ NS_IMETHODIMP mozPersonalDictionary::AddWord(const char16_t *aWord, const char16
|
|||
/* void RemoveWord (in wstring word); */
|
||||
NS_IMETHODIMP mozPersonalDictionary::RemoveWord(const char16_t *aWord, const char16_t *aLang)
|
||||
{
|
||||
WaitForLoad();
|
||||
|
||||
mDictionaryTable.RemoveEntry(aWord);
|
||||
mDirty = true;
|
||||
return NS_OK;
|
||||
|
@ -237,6 +331,8 @@ NS_IMETHODIMP mozPersonalDictionary::IgnoreWord(const char16_t *aWord)
|
|||
/* void EndSession (); */
|
||||
NS_IMETHODIMP mozPersonalDictionary::EndSession()
|
||||
{
|
||||
WaitForLoad();
|
||||
|
||||
Save(); // save any custom words at the end of a spell check session
|
||||
mIgnoreTable.Clear();
|
||||
return NS_OK;
|
||||
|
@ -264,7 +360,9 @@ NS_IMETHODIMP mozPersonalDictionary::GetCorrection(const char16_t *word, char16_
|
|||
NS_IMETHODIMP mozPersonalDictionary::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *aData)
|
||||
{
|
||||
if (!nsCRT::strcmp(aTopic, "profile-do-change")) {
|
||||
Load(); // load automatically clears out the existing dictionary table
|
||||
WaitForLoad();
|
||||
mIsLoaded = false;
|
||||
Load(); // load automatically clears out the existing dictionary table
|
||||
} else if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
|
||||
Save();
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "nsCRT.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include <mozilla/Monitor.h>
|
||||
|
||||
#define MOZ_PERSONALDICTIONARY_CONTRACTID "@mozilla.org/spellchecker/personaldictionary;1"
|
||||
#define MOZ_PERSONALDICTIONARY_CID \
|
||||
|
@ -24,6 +25,8 @@
|
|||
0X7EF52EAF, 0XB7E1, 0X462B, \
|
||||
{ 0X87, 0XE2, 0X5D, 0X1D, 0XBA, 0XCA, 0X90, 0X48 } }
|
||||
|
||||
class mozPersonalDictionaryLoader;
|
||||
|
||||
class mozPersonalDictionary : public mozIPersonalDictionary,
|
||||
public nsIObserver,
|
||||
public nsSupportsWeakReference
|
||||
|
@ -40,10 +43,30 @@ public:
|
|||
nsresult Init();
|
||||
|
||||
protected:
|
||||
bool mDirty; /* has the dictionary been modified */
|
||||
/* has the dictionary been modified */
|
||||
bool mDirty;
|
||||
|
||||
/* true if the dictionary has been loaded from disk */
|
||||
bool mIsLoaded;
|
||||
|
||||
mozilla::Monitor mMonitor;
|
||||
nsTHashtable<nsUnicharPtrHashKey> mDictionaryTable;
|
||||
nsTHashtable<nsUnicharPtrHashKey> mIgnoreTable;
|
||||
nsCOMPtr<nsIUnicodeEncoder> mEncoder; /*Encoder to use to compare with spellchecker word */
|
||||
|
||||
/*Encoder to use to compare with spellchecker word */
|
||||
nsCOMPtr<nsIUnicodeEncoder> mEncoder;
|
||||
|
||||
private:
|
||||
/* wait for the asynchronous load of the dictionary to be completed */
|
||||
void WaitForLoad();
|
||||
|
||||
/* enter the monitor before starting a synchronous load off the main-thread */
|
||||
void SyncLoad();
|
||||
|
||||
/* perform a synchronous load of the dictionary from disk */
|
||||
void SyncLoadInternal();
|
||||
|
||||
friend class mozPersonalDictionaryLoader;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче