Bug 1657573: Change libhunspell's file access code to use function pointers r=froydnj

Differential Revision: https://phabricator.services.mozilla.com/D86173
This commit is contained in:
shravanrn 2020-08-10 15:29:25 +00:00
Родитель f4905cc23b
Коммит 571754630f
11 изменённых файлов: 319 добавлений и 74 удалений

Просмотреть файл

@ -6,7 +6,7 @@
UNIFIED_SOURCES += [
'mozHunspell.cpp',
'mozHunspellFileMgr.cpp',
'mozHunspellFileMgrHost.cpp',
'RemoteSpellCheckEngineChild.cpp',
'RemoteSpellCheckEngineParent.cpp',
]

Просмотреть файл

@ -58,6 +58,8 @@
******* END LICENSE BLOCK *******/
#include "mozHunspell.h"
#include "mozHunspellFileMgrGlue.h"
#include "mozHunspellFileMgrHost.h"
#include "nsReadableUtils.h"
#include "nsString.h"
#include "nsIObserverService.h"
@ -183,6 +185,9 @@ mozHunspell::SetDictionary(const nsAString& aDictionary) {
mDictionary = aDictionary;
mAffixFileName = affFileName;
RegisterHunspellCallbacks(
mozHunspellCallbacks::CreateFilemgr, mozHunspellCallbacks::GetLine,
mozHunspellCallbacks::GetLineNum, mozHunspellCallbacks::DestructFilemgr);
mHunspell = new Hunspell(affFileName.get(), dictFileName.get());
if (!mHunspell) return NS_ERROR_OUT_OF_MEMORY;

Просмотреть файл

@ -1,59 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozHunspellFileMgr.h"
#include "mozilla/DebugOnly.h"
#include "nsContentUtils.h"
#include "nsILoadInfo.h"
#include "nsNetUtil.h"
using namespace mozilla;
FileMgr::FileMgr(const char* aFilename, const char* aKey) {
DebugOnly<Result<Ok, nsresult>> result = Open(nsDependentCString(aFilename));
NS_WARNING_ASSERTION(result.value.isOk(), "Failed to open Hunspell file");
}
Result<Ok, nsresult> FileMgr::Open(const nsACString& aPath) {
nsCOMPtr<nsIURI> uri;
MOZ_TRY(NS_NewURI(getter_AddRefs(uri), aPath));
nsCOMPtr<nsIChannel> channel;
MOZ_TRY(NS_NewChannel(
getter_AddRefs(channel), uri, nsContentUtils::GetSystemPrincipal(),
nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_INHERITS_SEC_CONTEXT,
nsIContentPolicy::TYPE_OTHER));
MOZ_TRY(channel->Open(getter_AddRefs(mStream)));
return Ok();
}
Result<Ok, nsresult> FileMgr::ReadLine(nsACString& aLine) {
if (!mStream) {
return Err(NS_ERROR_NOT_INITIALIZED);
}
bool ok;
MOZ_TRY(NS_ReadLine(mStream.get(), &mLineBuffer, aLine, &ok));
if (!ok) {
mStream = nullptr;
}
mLineNum++;
return Ok();
}
bool FileMgr::getline(std::string& aResult) {
nsAutoCString line;
auto res = ReadLine(line);
if (res.isErr()) {
return false;
}
aResult.assign(line.BeginReading(), line.Length());
return true;
}

Просмотреть файл

@ -0,0 +1,37 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozHunspellFileMgrGlue_h
#define mozHunspellFileMgrGlue_h
#include <stdint.h>
#if defined(__cplusplus)
extern "C" {
#endif
typedef uint32_t(hunspell_create_filemgr_t)(const char* aFilename,
const char* aKey);
typedef bool(hunspell_get_line_t)(uint32_t aFd, char** aLinePtr);
typedef int(hunspell_get_line_num_t)(uint32_t aFd);
typedef void(hunspell_destruct_filemgr_t)(uint32_t aFd);
void RegisterHunspellCallbacks(
hunspell_create_filemgr_t* aHunspellCreateFilemgr,
hunspell_get_line_t* aHunspellGetLine,
hunspell_get_line_num_t* aHunspellGetLine_num,
hunspell_destruct_filemgr_t* aHunspellDestructFilemgr);
extern hunspell_create_filemgr_t* moz_glue_hunspell_create_filemgr;
extern hunspell_get_line_t* moz_glue_hunspell_get_line;
extern hunspell_get_line_num_t* moz_glue_hunspell_get_line_num;
extern hunspell_destruct_filemgr_t* moz_glue_hunspell_destruct_filemgr;
#if defined(__cplusplus)
}
#endif
#endif

Просмотреть файл

@ -0,0 +1,138 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <limits>
#include "mozHunspellFileMgrHost.h"
#include "mozilla/DebugOnly.h"
#include "nsContentUtils.h"
#include "nsILoadInfo.h"
#include "nsNetUtil.h"
using namespace mozilla;
mozHunspellFileMgrHost::mozHunspellFileMgrHost(const char* aFilename,
const char* aKey) {
DebugOnly<Result<Ok, nsresult>> result = Open(nsDependentCString(aFilename));
NS_WARNING_ASSERTION(result.value.isOk(), "Failed to open Hunspell file");
}
Result<Ok, nsresult> mozHunspellFileMgrHost::Open(const nsACString& aPath) {
nsCOMPtr<nsIURI> uri;
MOZ_TRY(NS_NewURI(getter_AddRefs(uri), aPath));
nsCOMPtr<nsIChannel> channel;
MOZ_TRY(NS_NewChannel(
getter_AddRefs(channel), uri, nsContentUtils::GetSystemPrincipal(),
nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_INHERITS_SEC_CONTEXT,
nsIContentPolicy::TYPE_OTHER));
MOZ_TRY(channel->Open(getter_AddRefs(mStream)));
return Ok();
}
Result<Ok, nsresult> mozHunspellFileMgrHost::ReadLine(nsACString& aLine) {
if (!mStream) {
return Err(NS_ERROR_NOT_INITIALIZED);
}
bool ok;
MOZ_TRY(NS_ReadLine(mStream.get(), &mLineBuffer, aLine, &ok));
if (!ok) {
mStream = nullptr;
}
mLineNum++;
return Ok();
}
bool mozHunspellFileMgrHost::GetLine(std::string& aResult) {
nsAutoCString line;
auto res = ReadLine(line);
if (res.isErr()) {
return false;
}
aResult.assign(line.BeginReading(), line.Length());
return true;
}
/* static */
uint32_t mozHunspellCallbacks::sCurrentFreshId = 0;
/* static */
mozilla::detail::StaticRWLock mozHunspellCallbacks::sFileMgrMapLock;
/* static */
std::map<uint32_t, std::unique_ptr<mozHunspellFileMgrHost>>
mozHunspellCallbacks::sFileMgrMap;
/* static */
uint32_t mozHunspellCallbacks::CreateFilemgr(const char* aFilename,
const char* aKey) {
mozilla::detail::StaticAutoWriteLock lock(sFileMgrMapLock);
uint32_t freshId = GetFreshId();
sFileMgrMap[freshId] = std::unique_ptr<mozHunspellFileMgrHost>(
new mozHunspellFileMgrHost(aFilename, aKey));
return freshId;
}
/* static */
uint32_t mozHunspellCallbacks::GetFreshId() {
// i is uint64_t to prevent overflow during loop increment which would cause
// an infinite loop
for (uint64_t i = sCurrentFreshId; i < std::numeric_limits<uint32_t>::max();
i++) {
auto it = sFileMgrMap.find(i);
if (it == sFileMgrMap.end()) {
// set sCurrentFreshId to the next (possibly) available id
sCurrentFreshId = i + 1;
return static_cast<uint32_t>(i);
}
}
MOZ_CRASH("Ran out of unique file ids for hunspell dictionaries");
}
/* static */
mozHunspellFileMgrHost& mozHunspellCallbacks::GetMozHunspellFileMgrHost(
uint32_t aFd) {
mozilla::detail::StaticAutoReadLock lock(sFileMgrMapLock);
auto iter = sFileMgrMap.find(aFd);
MOZ_RELEASE_ASSERT(iter != sFileMgrMap.end());
return *(iter->second.get());
}
/* static */
bool mozHunspellCallbacks::GetLine(uint32_t aFd, char** aLinePtr) {
mozHunspellFileMgrHost& inst =
mozHunspellCallbacks::GetMozHunspellFileMgrHost(aFd);
std::string line;
bool ok = inst.GetLine(line);
if (ok) {
*aLinePtr = static_cast<char*>(malloc(line.size() + 1));
strcpy(*aLinePtr, line.c_str());
} else {
*aLinePtr = nullptr;
}
return ok;
}
/* static */
int mozHunspellCallbacks::GetLineNum(uint32_t aFd) {
mozHunspellFileMgrHost& inst =
mozHunspellCallbacks::GetMozHunspellFileMgrHost(aFd);
int num = inst.GetLineNum();
return num;
}
/* static */
void mozHunspellCallbacks::DestructFilemgr(uint32_t aFd) {
mozilla::detail::StaticAutoWriteLock lock(sFileMgrMapLock);
auto iter = sFileMgrMap.find(aFd);
if (iter != sFileMgrMap.end()) {
sFileMgrMap.erase(iter);
}
}

Просмотреть файл

@ -0,0 +1,83 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozHunspellFileMgrHost_h
#define mozHunspellFileMgrHost_h
#include <map>
#include <memory>
#include <mutex>
#include <stdint.h>
#include <string>
#include "mozilla/Result.h"
#include "mozilla/ResultExtensions.h"
#include "mozilla/RWLock.h"
#include "nsIInputStream.h"
#include "nsReadLine.h"
namespace mozilla {
class mozHunspellFileMgrHost final {
public:
/**
* aFilename must be a local file/jar URI for the file to load.
*
* aKey is the decription key for encrypted Hunzip files, and is
* unsupported. The argument is there solely for compatibility.
*/
explicit mozHunspellFileMgrHost(const char* aFilename,
const char* aKey = nullptr);
~mozHunspellFileMgrHost() = default;
bool GetLine(std::string& aResult);
int GetLineNum() const { return mLineNum; }
private:
mozilla::Result<mozilla::Ok, nsresult> Open(const nsACString& aPath);
mozilla::Result<mozilla::Ok, nsresult> ReadLine(nsACString& aLine);
int mLineNum = 0;
nsCOMPtr<nsIInputStream> mStream;
nsLineBuffer<char> mLineBuffer;
};
class mozHunspellCallbacks {
public:
// APIs invoked by the sandboxed hunspell file manager
static uint32_t CreateFilemgr(const char* aFilename, const char* aKey);
static bool GetLine(uint32_t aFd, char** aLinePtr);
static int GetLineNum(uint32_t aFd);
static void DestructFilemgr(uint32_t aFd);
private:
/**
* sFileMgrMap holds a map between unique uint32_t
* integers and mozHunspellFileMgrHost instances
*/
static std::map<uint32_t, std::unique_ptr<mozHunspellFileMgrHost>>
sFileMgrMap;
/**
* Reader-writer lock for the sFileMgrMap
*/
static mozilla::detail::StaticRWLock sFileMgrMapLock;
/**
* Tracks the next possibly unused id for sFileMgrMap
*/
static uint32_t sCurrentFreshId;
/**
* Returns an unused id for sFileMgrMap
*/
static uint32_t GetFreshId();
/**
* Returns the mozHunspellFileMgrHost for the given uint32_t id
*/
static mozHunspellFileMgrHost& GetMozHunspellFileMgrHost(uint32_t aFd);
};
} // namespace mozilla
#endif

Просмотреть файл

@ -0,0 +1,44 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozHunspellFileMgrSandbox.h"
#include "mozHunspellFileMgrGlue.h"
FileMgr::FileMgr(const char* aFilename, const char* aKey) : mFd(0) {
mFd = moz_glue_hunspell_create_filemgr(aFilename, aKey);
}
bool FileMgr::getline(std::string& aResult) {
char* line = nullptr;
bool ok = moz_glue_hunspell_get_line(mFd, &line);
if (ok && line) {
aResult = line;
free(line);
}
return ok;
}
int FileMgr::getlinenum() const { return moz_glue_hunspell_get_line_num(mFd); }
FileMgr::~FileMgr() { moz_glue_hunspell_destruct_filemgr(mFd); }
// Glue code to set global callbacks
hunspell_create_filemgr_t* moz_glue_hunspell_create_filemgr = nullptr;
hunspell_get_line_t* moz_glue_hunspell_get_line = nullptr;
hunspell_get_line_num_t* moz_glue_hunspell_get_line_num = nullptr;
hunspell_destruct_filemgr_t* moz_glue_hunspell_destruct_filemgr = nullptr;
void RegisterHunspellCallbacks(
hunspell_create_filemgr_t* aHunspellCreateFilemgr,
hunspell_get_line_t* aHunspellGetLine,
hunspell_get_line_num_t* aHunspellGetLine_num,
hunspell_destruct_filemgr_t* aHunspellDestructFilemgr) {
moz_glue_hunspell_create_filemgr = aHunspellCreateFilemgr;
moz_glue_hunspell_get_line = aHunspellGetLine;
moz_glue_hunspell_get_line_num = aHunspellGetLine_num;
moz_glue_hunspell_destruct_filemgr = aHunspellDestructFilemgr;
}

Просмотреть файл

@ -4,10 +4,11 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozHunspellFileMgr_h
#define mozHunspellFileMgr_h
#ifndef mozHunspellFileMgrSandbox_h
#define mozHunspellFileMgrSandbox_h
#include <string>
#include <stdint.h>
#include "mozilla/Result.h"
#include "mozilla/ResultExtensions.h"
@ -25,21 +26,16 @@ class FileMgr final {
* unsupported. The argument is there solely for compatibility.
*/
explicit FileMgr(const char* aFilename, const char* aKey = nullptr);
~FileMgr() = default;
~FileMgr();
// Note: The nonstandard naming conventions of these methods are necessary for
// Hunspell compatibility.
bool getline(std::string& aLine);
int getlinenum() const { return mLineNum; }
int getlinenum() const;
private:
mozilla::Result<mozilla::Ok, nsresult> Open(const nsACString& aPath);
mozilla::Result<mozilla::Ok, nsresult> ReadLine(nsACString& aLine);
int mLineNum = 0;
nsCOMPtr<nsIInputStream> mStream;
nsLineBuffer<char> mLineBuffer;
// opaque file descriptor got from the host application
uint32_t mFd;
};
#endif // mozHunspellFileMgr_h
#endif // mozHunspellFileMgrSandbox_h

Просмотреть файл

@ -154,7 +154,7 @@ diff --git a/extensions/spellcheck/hunspell/src/filemgr.hxx b/extensions/spellch
- private:
- FileMgr(const FileMgr&);
- FileMgr& operator=(const FileMgr&);
+#include "mozHunspellFileMgr.h"
+#include "mozHunspellFileMgrSandbox.h"
- protected:
- std::ifstream fin;

Просмотреть файл

@ -72,6 +72,6 @@
#ifndef FILEMGR_HXX_
#define FILEMGR_HXX_
#include "mozHunspellFileMgr.h"
#include "mozHunspellFileMgrSandbox.h"
#endif

Просмотреть файл

@ -5,6 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
UNIFIED_SOURCES += [
'../glue/mozHunspellFileMgrSandbox.cpp',
'affentry.cxx',
'affixmgr.cxx',
'csutil.cxx',