зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1626076 - Make it possible to use DataStorage on socket process r=keeler,dragana,necko-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D68877
This commit is contained in:
Родитель
2550d855b2
Коммит
85532d60f8
|
@ -65,6 +65,7 @@ include ClientIPCTypes;
|
|||
include HangTypes;
|
||||
include PrefsTypes;
|
||||
include NeckoChannelParams;
|
||||
include PSMIPCTypes;
|
||||
|
||||
#if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
|
||||
include protocol PSandboxTesting;
|
||||
|
@ -89,7 +90,6 @@ using mozilla::LayoutDeviceIntPoint from "Units.h";
|
|||
using struct LookAndFeelInt from "mozilla/widget/WidgetMessageUtils.h";
|
||||
using class mozilla::dom::MessagePort from "mozilla/dom/MessagePort.h";
|
||||
using class mozilla::dom::ipc::StructuredCloneData from "mozilla/dom/ipc/StructuredCloneData.h";
|
||||
using mozilla::DataStorageType from "ipc/DataStorageIPCUtils.h";
|
||||
using mozilla::OriginAttributes from "mozilla/ipc/BackgroundUtils.h";
|
||||
using struct mozilla::layers::TextureFactoryIdentifier from "mozilla/layers/CompositorTypes.h";
|
||||
using mozilla::layers::CompositorOptions from "mozilla/layers/CompositorOptions.h";
|
||||
|
@ -169,17 +169,6 @@ struct SystemFontListEntry {
|
|||
};
|
||||
#endif
|
||||
|
||||
struct DataStorageItem {
|
||||
nsCString key;
|
||||
nsCString value;
|
||||
DataStorageType type;
|
||||
};
|
||||
|
||||
struct DataStorageEntry {
|
||||
DataStorageItem[] items;
|
||||
nsString filename;
|
||||
};
|
||||
|
||||
struct ClipboardCapabilities {
|
||||
bool supportsSelectionClipboard;
|
||||
bool supportsFindClipboard;
|
||||
|
|
|
@ -35,3 +35,5 @@ with Files('**'):
|
|||
BUG_COMPONENT = ('Core', 'Networking')
|
||||
|
||||
include('/tools/fuzzing/libfuzzer-config.mozbuild')
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
|
|
@ -703,6 +703,29 @@ nsFileOutputStream::Init(nsIFile* file, int32_t ioFlags, int32_t perm,
|
|||
mBehaviorFlags & nsIFileOutputStream::DEFER_OPEN);
|
||||
}
|
||||
|
||||
nsresult nsFileOutputStream::InitWithFileDescriptor(
|
||||
const mozilla::ipc::FileDescriptor& aFd) {
|
||||
NS_ENSURE_TRUE(mFD == nullptr, NS_ERROR_ALREADY_INITIALIZED);
|
||||
NS_ENSURE_TRUE(mState == eUnitialized || mState == eClosed,
|
||||
NS_ERROR_ALREADY_INITIALIZED);
|
||||
|
||||
if (aFd.IsValid()) {
|
||||
auto rawFD = aFd.ClonePlatformHandle();
|
||||
PRFileDesc* fileDesc = PR_ImportFile(PROsfd(rawFD.release()));
|
||||
if (!fileDesc) {
|
||||
NS_WARNING("Failed to import file handle!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
mFD = fileDesc;
|
||||
mState = eOpened;
|
||||
} else {
|
||||
mState = eError;
|
||||
mErrorValue = NS_ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFileOutputStream::Preallocate(int64_t aLength) {
|
||||
if (!mFD) {
|
||||
|
|
|
@ -20,6 +20,12 @@
|
|||
#include "nsReadLine.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
class FileDescriptor;
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class nsFileStreamBase : public nsISeekableStream, public nsIFileMetadata {
|
||||
|
@ -195,6 +201,7 @@ class nsFileOutputStream : public nsFileStreamBase, public nsIFileOutputStream {
|
|||
NS_FORWARD_NSIOUTPUTSTREAM(nsFileStreamBase::)
|
||||
|
||||
static nsresult Create(nsISupports* aOuter, REFNSIID aIID, void** aResult);
|
||||
nsresult InitWithFileDescriptor(const mozilla::ipc::FileDescriptor& aFd);
|
||||
|
||||
protected:
|
||||
virtual ~nsFileOutputStream() = default;
|
||||
|
|
|
@ -151,6 +151,22 @@ nsresult NS_NewLocalFileOutputStream(nsIOutputStream** result, nsIFile* file,
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsresult NS_NewLocalFileOutputStream(nsIOutputStream** result,
|
||||
const mozilla::ipc::FileDescriptor& fd) {
|
||||
nsCOMPtr<nsIFileOutputStream> out;
|
||||
nsFileOutputStream::Create(nullptr, NS_GET_IID(nsIFileOutputStream),
|
||||
getter_AddRefs(out));
|
||||
|
||||
nsresult rv =
|
||||
static_cast<nsFileOutputStream*>(out.get())->InitWithFileDescriptor(fd);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
out.forget(result);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult net_EnsureIOService(nsIIOService** ios, nsCOMPtr<nsIIOService>& grip) {
|
||||
nsresult rv = NS_OK;
|
||||
if (!*ios) {
|
||||
|
|
|
@ -61,6 +61,11 @@ class ClientInfo;
|
|||
class PerformanceStorage;
|
||||
class ServiceWorkerDescriptor;
|
||||
} // namespace dom
|
||||
|
||||
namespace ipc {
|
||||
class FileDescriptor;
|
||||
} // namespace ipc
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
template <class>
|
||||
|
@ -462,6 +467,9 @@ nsresult NS_NewLocalFileOutputStream(nsIOutputStream** result, nsIFile* file,
|
|||
int32_t ioFlags = -1, int32_t perm = -1,
|
||||
int32_t behaviorFlags = 0);
|
||||
|
||||
nsresult NS_NewLocalFileOutputStream(nsIOutputStream** result,
|
||||
const mozilla::ipc::FileDescriptor& fd);
|
||||
|
||||
// returns a file output stream which can be QI'ed to nsISafeOutputStream.
|
||||
nsresult NS_NewAtomicFileOutputStream(nsIOutputStream** result, nsIFile* file,
|
||||
int32_t ioFlags = -1, int32_t perm = -1,
|
||||
|
|
|
@ -1220,7 +1220,7 @@ void AltSvcCache::ClearAltServiceMappings() {
|
|||
nsresult AltSvcCache::GetAltSvcCacheKeys(nsTArray<nsCString>& value) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (gHttpHandler->AllowAltSvc() && mStorage) {
|
||||
nsTArray<mozilla::dom::DataStorageItem> items;
|
||||
nsTArray<mozilla::psm::DataStorageItem> items;
|
||||
mStorage->GetAll(&items);
|
||||
|
||||
for (const auto& item : items) {
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/dom/PContent.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/FileUtils.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StaticMutex.h"
|
||||
|
@ -29,6 +30,11 @@
|
|||
#include "nsPrintfCString.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "private/pprio.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
# include "nsILocalFileWin.h"
|
||||
#endif
|
||||
|
||||
// NB: Read DataStorage.h first.
|
||||
|
||||
|
@ -77,7 +83,7 @@ static mozilla::StaticAutoPtr<DataStorageSharedThread> gDataStorageSharedThread;
|
|||
static bool gDataStorageSharedThreadShutDown = false;
|
||||
|
||||
nsresult DataStorageSharedThread::Initialize() {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(XRE_IsParentProcess() || XRE_IsSocketProcess());
|
||||
mozilla::StaticMutexAutoLock lock(sDataStorageSharedThreadMutex);
|
||||
|
||||
// If this happens, we initialized a DataStorage after shutdown notifications
|
||||
|
@ -100,7 +106,7 @@ nsresult DataStorageSharedThread::Initialize() {
|
|||
}
|
||||
|
||||
nsresult DataStorageSharedThread::Shutdown() {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(XRE_IsParentProcess() || XRE_IsSocketProcess());
|
||||
mozilla::StaticMutexAutoLock lock(sDataStorageSharedThreadMutex);
|
||||
|
||||
if (!gDataStorageSharedThread || gDataStorageSharedThreadShutDown) {
|
||||
|
@ -132,7 +138,7 @@ nsresult DataStorageSharedThread::Shutdown() {
|
|||
}
|
||||
|
||||
nsresult DataStorageSharedThread::Dispatch(nsIRunnable* event) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(XRE_IsParentProcess() || XRE_IsSocketProcess());
|
||||
mozilla::StaticMutexAutoLock lock(sDataStorageSharedThreadMutex);
|
||||
if (gDataStorageSharedThreadShutDown || !gDataStorageSharedThread ||
|
||||
!gDataStorageSharedThread->mThread) {
|
||||
|
@ -233,11 +239,11 @@ void DataStorage::GetAllFileNames(nsTArray<nsString>& aItems) {
|
|||
|
||||
// static
|
||||
void DataStorage::GetAllChildProcessData(
|
||||
nsTArray<mozilla::dom::DataStorageEntry>& aEntries) {
|
||||
nsTArray<mozilla::psm::DataStorageEntry>& aEntries) {
|
||||
nsTArray<nsString> storageFiles;
|
||||
GetAllFileNames(storageFiles);
|
||||
for (auto& file : storageFiles) {
|
||||
dom::DataStorageEntry entry;
|
||||
psm::DataStorageEntry entry;
|
||||
entry.filename() = file;
|
||||
RefPtr<DataStorage> storage = DataStorage::GetFromRawFileName(file);
|
||||
if (!storage->mInitCalled) {
|
||||
|
@ -255,7 +261,7 @@ void DataStorage::GetAllChildProcessData(
|
|||
|
||||
// static
|
||||
void DataStorage::SetCachedStorageEntries(
|
||||
const nsTArray<mozilla::dom::DataStorageEntry>& aEntries) {
|
||||
const nsTArray<mozilla::psm::DataStorageEntry>& aEntries) {
|
||||
MOZ_ASSERT(XRE_IsContentProcess());
|
||||
|
||||
// Make sure to initialize all DataStorage classes.
|
||||
|
@ -266,10 +272,10 @@ void DataStorage::SetCachedStorageEntries(
|
|||
// (currently 3). There is a comment in the DataStorageList.h header
|
||||
// about updating the algorithm here to something more fancy if the list
|
||||
// of DataStorage items grows some day.
|
||||
nsTArray<dom::DataStorageEntry> entries;
|
||||
nsTArray<psm::DataStorageEntry> entries;
|
||||
#define DATA_STORAGE(_) \
|
||||
{ \
|
||||
dom::DataStorageEntry entry; \
|
||||
psm::DataStorageEntry entry; \
|
||||
entry.filename() = NS_LITERAL_STRING(#_ ".txt"); \
|
||||
for (auto& e : aEntries) { \
|
||||
if (entry.filename().Equals(e.filename())) { \
|
||||
|
@ -299,8 +305,8 @@ size_t DataStorage::SizeOfIncludingThis(
|
|||
return aMallocSizeOf(this) + sizeOfExcludingThis;
|
||||
}
|
||||
|
||||
nsresult DataStorage::Init(
|
||||
const nsTArray<mozilla::dom::DataStorageItem>* aItems) {
|
||||
nsresult DataStorage::Init(const nsTArray<DataStorageItem>* aItems,
|
||||
mozilla::ipc::FileDescriptor aWriteFd) {
|
||||
// Don't access the observer service or preferences off the main thread.
|
||||
if (!NS_IsMainThread()) {
|
||||
MOZ_ASSERT_UNREACHABLE("DataStorage::Init called off main thread");
|
||||
|
@ -339,11 +345,20 @@ nsresult DataStorage::Init(
|
|||
return rv;
|
||||
}
|
||||
} else {
|
||||
// In the child process, we use the data passed to us by the parent process
|
||||
// to initialize.
|
||||
MOZ_ASSERT(XRE_IsContentProcess());
|
||||
// In the child process and socket process, we use the data passed to us by
|
||||
// the parent process to initialize.
|
||||
MOZ_ASSERT(XRE_IsContentProcess() || XRE_IsSocketProcess());
|
||||
MOZ_ASSERT(aItems);
|
||||
|
||||
if (XRE_IsSocketProcess() && aWriteFd.IsValid()) {
|
||||
rv = DataStorageSharedThread::Initialize();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mWriteFd = aWriteFd;
|
||||
}
|
||||
|
||||
for (auto& item : *aItems) {
|
||||
Entry entry;
|
||||
entry.mValue = item.value();
|
||||
|
@ -384,6 +399,87 @@ nsresult DataStorage::Init(
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
class DataStorage::Opener : public Runnable {
|
||||
public:
|
||||
explicit Opener(
|
||||
nsIFile* aFile,
|
||||
std::function<void(mozilla::ipc::FileDescriptor&&)>&& aResolver)
|
||||
: Runnable("DataStorage::Opener"),
|
||||
mFile(aFile),
|
||||
mResolver(std::move(aResolver)) {
|
||||
MOZ_ASSERT(mFile);
|
||||
}
|
||||
~Opener() = default;
|
||||
|
||||
private:
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
void ResolveFD();
|
||||
|
||||
nsCOMPtr<nsIFile> mFile;
|
||||
std::function<void(mozilla::ipc::FileDescriptor&&)> mResolver;
|
||||
mozilla::ipc::FileDescriptor mFd;
|
||||
};
|
||||
|
||||
void DataStorage::Opener::ResolveFD() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
mResolver(std::move(mFd));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DataStorage::Opener::Run() {
|
||||
AutoFDClose prFileDesc;
|
||||
nsresult rv;
|
||||
|
||||
#if defined(XP_WIN)
|
||||
nsCOMPtr<nsILocalFileWin> winFile = do_QueryInterface(mFile, &rv);
|
||||
MOZ_ASSERT(winFile);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = winFile->OpenNSPRFileDescShareDelete(
|
||||
PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0664, &prFileDesc.rwget());
|
||||
}
|
||||
#else
|
||||
rv = mFile->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0664,
|
||||
&prFileDesc.rwget());
|
||||
#endif /* XP_WIN */
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mFd = mozilla::ipc::FileDescriptor(
|
||||
mozilla::ipc::FileDescriptor::PlatformHandleType(
|
||||
PR_FileDesc2NativeHandle(prFileDesc)));
|
||||
}
|
||||
|
||||
RefPtr<Opener> self = this;
|
||||
rv = NS_DispatchToMainThread(
|
||||
NS_NewRunnableFunction("DataStorage::Opener::ResolveFD",
|
||||
[self]() { self->ResolveFD(); }),
|
||||
NS_DISPATCH_NORMAL);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult DataStorage::AsyncTakeFileDesc(
|
||||
std::function<void(mozilla::ipc::FileDescriptor&&)>&& aResolver) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
||||
WaitForReady();
|
||||
MutexAutoLock lock(mMutex);
|
||||
if (!mBackingFile) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
RefPtr<Opener> job(new Opener(mBackingFile, std::move(aResolver)));
|
||||
nsresult rv = DataStorageSharedThread::Dispatch(job);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mBackingFile = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class DataStorage::Reader : public Runnable {
|
||||
public:
|
||||
explicit Reader(DataStorage* aDataStorage)
|
||||
|
@ -676,7 +772,7 @@ DataStorage::DataStorageTable& DataStorage::GetTableForType(
|
|||
}
|
||||
|
||||
void DataStorage::ReadAllFromTable(DataStorageType aType,
|
||||
nsTArray<dom::DataStorageItem>* aItems,
|
||||
nsTArray<DataStorageItem>* aItems,
|
||||
const MutexAutoLock& aProofOfLock) {
|
||||
for (auto iter = GetTableForType(aType, aProofOfLock).Iter(); !iter.Done();
|
||||
iter.Next()) {
|
||||
|
@ -687,7 +783,7 @@ void DataStorage::ReadAllFromTable(DataStorageType aType,
|
|||
}
|
||||
}
|
||||
|
||||
void DataStorage::GetAll(nsTArray<dom::DataStorageItem>* aItems) {
|
||||
void DataStorage::GetAll(nsTArray<DataStorageItem>* aItems) {
|
||||
WaitForReady();
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
|
@ -820,23 +916,40 @@ void DataStorage::Remove(const nsCString& aKey, DataStorageType aType) {
|
|||
});
|
||||
}
|
||||
|
||||
class DataStorage::Writer : public Runnable {
|
||||
class DataStorage::Writer final : public Runnable {
|
||||
public:
|
||||
Writer(nsCString& aData, DataStorage* aDataStorage)
|
||||
: Runnable("DataStorage::Writer"),
|
||||
mData(aData),
|
||||
mDataStorage(aDataStorage) {}
|
||||
|
||||
private:
|
||||
protected:
|
||||
NS_DECL_NSIRUNNABLE
|
||||
nsresult CreateOutputStream(nsIOutputStream** aResult);
|
||||
|
||||
nsCString mData;
|
||||
RefPtr<DataStorage> mDataStorage;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
DataStorage::Writer::Run() {
|
||||
nsresult DataStorage::Writer::CreateOutputStream(nsIOutputStream** aResult) {
|
||||
nsresult rv;
|
||||
|
||||
if (XRE_IsSocketProcess()) {
|
||||
mozilla::ipc::FileDescriptor fd;
|
||||
{
|
||||
MutexAutoLock lock(mDataStorage->mMutex);
|
||||
fd = mDataStorage->mWriteFd;
|
||||
}
|
||||
|
||||
if (!fd.IsValid()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
return NS_NewLocalFileOutputStream(aResult, fd);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
||||
// Concurrent operations on nsIFile objects are not guaranteed to be safe,
|
||||
// so we clone the file while holding the lock and then release the lock.
|
||||
// At that point, we can safely operate on the clone.
|
||||
|
@ -853,13 +966,23 @@ DataStorage::Writer::Run() {
|
|||
}
|
||||
}
|
||||
|
||||
return NS_NewLocalFileOutputStream(aResult, file,
|
||||
PR_CREATE_FILE | PR_TRUNCATE | PR_WRONLY);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DataStorage::Writer::Run() {
|
||||
nsCOMPtr<nsIOutputStream> outputStream;
|
||||
rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), file,
|
||||
PR_CREATE_FILE | PR_TRUNCATE | PR_WRONLY);
|
||||
nsresult rv = CreateOutputStream(getter_AddRefs(outputStream));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// When the output stream is null, it means we don't have a profile.
|
||||
if (!outputStream) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
const char* ptr = mData.get();
|
||||
int32_t remaining = mData.Length();
|
||||
uint32_t written = 0;
|
||||
|
@ -885,9 +1008,9 @@ DataStorage::Writer::Run() {
|
|||
}
|
||||
|
||||
nsresult DataStorage::AsyncWriteData(const MutexAutoLock& /*aProofOfLock*/) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(XRE_IsParentProcess() || XRE_IsSocketProcess());
|
||||
|
||||
if (mShuttingDown || !mBackingFile) {
|
||||
if (mShuttingDown || (!mBackingFile && !mWriteFd.IsValid())) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -921,7 +1044,7 @@ nsresult DataStorage::Clear() {
|
|||
mTemporaryDataTable.Clear();
|
||||
mPrivateDataTable.Clear();
|
||||
|
||||
if (XRE_IsParentProcess()) {
|
||||
if (XRE_IsParentProcess() || XRE_IsSocketProcess()) {
|
||||
// Asynchronously clear the file. This is similar to the permission manager
|
||||
// in that it doesn't wait to synchronously remove the data from its backing
|
||||
// storage either.
|
||||
|
@ -941,7 +1064,7 @@ nsresult DataStorage::Clear() {
|
|||
|
||||
/* static */
|
||||
void DataStorage::TimerCallback(nsITimer* aTimer, void* aClosure) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(XRE_IsParentProcess() || XRE_IsSocketProcess());
|
||||
|
||||
RefPtr<DataStorage> aDataStorage = (DataStorage*)aClosure;
|
||||
MutexAutoLock lock(aDataStorage->mMutex);
|
||||
|
@ -951,7 +1074,7 @@ void DataStorage::TimerCallback(nsITimer* aTimer, void* aClosure) {
|
|||
// We only initialize the timer on the worker thread because it's not safe
|
||||
// to mix what threads are operating on the timer.
|
||||
nsresult DataStorage::AsyncSetTimer(const MutexAutoLock& /*aProofOfLock*/) {
|
||||
if (mShuttingDown || !XRE_IsParentProcess()) {
|
||||
if (mShuttingDown || (!XRE_IsParentProcess() && !XRE_IsSocketProcess())) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -967,7 +1090,7 @@ nsresult DataStorage::AsyncSetTimer(const MutexAutoLock& /*aProofOfLock*/) {
|
|||
|
||||
void DataStorage::SetTimer() {
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(XRE_IsParentProcess() || XRE_IsSocketProcess());
|
||||
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
|
@ -1001,7 +1124,7 @@ void DataStorage::NotifyObservers(const char* aTopic) {
|
|||
|
||||
nsresult DataStorage::DispatchShutdownTimer(
|
||||
const MutexAutoLock& /*aProofOfLock*/) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(XRE_IsParentProcess() || XRE_IsSocketProcess());
|
||||
|
||||
nsCOMPtr<nsIRunnable> job = NewRunnableMethod(
|
||||
"DataStorage::ShutdownTimer", this, &DataStorage::ShutdownTimer);
|
||||
|
@ -1013,7 +1136,7 @@ nsresult DataStorage::DispatchShutdownTimer(
|
|||
}
|
||||
|
||||
void DataStorage::ShutdownTimer() {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(XRE_IsParentProcess() || XRE_IsSocketProcess());
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MutexAutoLock lock(mMutex);
|
||||
nsresult rv = mTimer->Cancel();
|
||||
|
@ -1039,7 +1162,7 @@ DataStorage::Observe(nsISupports* /*aSubject*/, const char* aTopic,
|
|||
mPrivateDataTable.Clear();
|
||||
}
|
||||
|
||||
if (!XRE_IsParentProcess()) {
|
||||
if (!XRE_IsParentProcess() && !XRE_IsSocketProcess()) {
|
||||
if (strcmp(aTopic, "xpcom-shutdown-threads") == 0) {
|
||||
sDataStorages->Clear();
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#define mozilla_DataStorage_h
|
||||
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/ipc/FileDescriptor.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
|
@ -26,9 +27,12 @@ class DataStorageMemoryReporter;
|
|||
|
||||
namespace dom {
|
||||
class ContentChild;
|
||||
} // namespace dom
|
||||
|
||||
namespace psm {
|
||||
class DataStorageEntry;
|
||||
class DataStorageItem;
|
||||
} // namespace dom
|
||||
} // namespace psm
|
||||
|
||||
/**
|
||||
* DataStorage is a threadsafe, generic, narrow string-based hash map that
|
||||
|
@ -101,7 +105,7 @@ enum class DataStorageClass {
|
|||
};
|
||||
|
||||
class DataStorage : public nsIObserver {
|
||||
typedef dom::DataStorageItem DataStorageItem;
|
||||
typedef psm::DataStorageItem DataStorageItem;
|
||||
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
@ -112,10 +116,22 @@ class DataStorage : public nsIObserver {
|
|||
static already_AddRefed<DataStorage> Get(DataStorageClass aFilename);
|
||||
|
||||
// Initializes the DataStorage. Must be called before using.
|
||||
// aItems is used in the content process to initialize a cache of the items
|
||||
// received from the parent process over IPC. nullptr must be passed for the
|
||||
// parent process.
|
||||
nsresult Init(const nsTArray<mozilla::dom::DataStorageItem>* aItems);
|
||||
// aItems is used in the content process and the socket process to initialize
|
||||
// a cache of the items received from the parent process over IPC. nullptr
|
||||
// must be passed for the parent process.
|
||||
// aWriteFd is only used in the socket process for now. The FileDesc is opened
|
||||
// in parent process and send to socket process. The data storage instance in
|
||||
// socket process will use this FD to write data to the backing file.
|
||||
nsresult Init(
|
||||
const nsTArray<mozilla::psm::DataStorageItem>* aItems,
|
||||
mozilla::ipc::FileDescriptor aWriteFd = mozilla::ipc::FileDescriptor());
|
||||
|
||||
// This function is used to create the file descriptor asynchronously. The FD
|
||||
// will be sent via the callback. Note that after this call, mBackingFile will
|
||||
// be nulled to prevent parent process to access the file.
|
||||
nsresult AsyncTakeFileDesc(
|
||||
std::function<void(mozilla::ipc::FileDescriptor&&)>&& aResolver);
|
||||
|
||||
// Given a key and a type of data, returns a value. Returns an empty string if
|
||||
// the key is not present for that type of data. If Get is called before the
|
||||
// "data-storage-ready" event is observed, it will block. NB: It is not
|
||||
|
@ -136,14 +152,14 @@ class DataStorage : public nsIObserver {
|
|||
|
||||
// Read all child process data that we know about.
|
||||
static void GetAllChildProcessData(
|
||||
nsTArray<mozilla::dom::DataStorageEntry>& aEntries);
|
||||
nsTArray<mozilla::psm::DataStorageEntry>& aEntries);
|
||||
|
||||
// Read all of the data items.
|
||||
void GetAll(nsTArray<DataStorageItem>* aItems);
|
||||
|
||||
// Set the cached copy of our DataStorage entries in the content process.
|
||||
static void SetCachedStorageEntries(
|
||||
const nsTArray<mozilla::dom::DataStorageEntry>& aEntries);
|
||||
const nsTArray<mozilla::psm::DataStorageEntry>& aEntries);
|
||||
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
|
||||
|
@ -160,6 +176,7 @@ class DataStorage : public nsIObserver {
|
|||
|
||||
class Writer;
|
||||
class Reader;
|
||||
class Opener;
|
||||
|
||||
class Entry {
|
||||
public:
|
||||
|
@ -230,6 +247,8 @@ class DataStorage : public nsIObserver {
|
|||
|
||||
const nsString mFilename;
|
||||
|
||||
mozilla::ipc::FileDescriptor mWriteFd;
|
||||
|
||||
static StaticAutoPtr<DataStorages> sDataStorages;
|
||||
};
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
* 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/. */
|
||||
|
||||
using mozilla::DataStorageType from "ipc/DataStorageIPCUtils.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace psm {
|
||||
|
||||
|
@ -17,5 +19,16 @@ struct DelegatedCredentialInfoArg {
|
|||
uint32_t authKeyBits;
|
||||
};
|
||||
|
||||
struct DataStorageItem {
|
||||
nsCString key;
|
||||
nsCString value;
|
||||
DataStorageType type;
|
||||
};
|
||||
|
||||
struct DataStorageEntry {
|
||||
DataStorageItem[] items;
|
||||
nsString filename;
|
||||
};
|
||||
|
||||
} // namespace psm
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -1791,11 +1791,11 @@ nsSiteSecurityService::Enumerate(uint32_t aType,
|
|||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsTArray<mozilla::dom::DataStorageItem> items;
|
||||
nsTArray<mozilla::psm::DataStorageItem> items;
|
||||
mSiteStateStorage->GetAll(&items);
|
||||
|
||||
nsCOMArray<nsISiteSecurityState> states;
|
||||
for (const mozilla::dom::DataStorageItem& item : items) {
|
||||
for (const mozilla::psm::DataStorageItem& item : items) {
|
||||
if (!StringEndsWith(item.key(), keySuffix)) {
|
||||
// The key does not end with correct suffix, so is not the type we want.
|
||||
continue;
|
||||
|
|
Загрузка…
Ссылка в новой задаче