gecko-dev/dom/plugins/ipc/MiniShmParent.cpp

179 строки
4.8 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=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 "MiniShmParent.h"
#include "base/scoped_handle.h"
#include <sstream>
namespace mozilla {
namespace plugins {
// static
const unsigned int MiniShmParent::kDefaultMiniShmSectionSize = 0x1000;
MiniShmParent::MiniShmParent()
: mSectionSize(0),
mParentEvent(nullptr),
mParentGuard(nullptr),
mChildEvent(nullptr),
mChildGuard(nullptr),
mRegWait(nullptr),
mFileMapping(nullptr),
mView(nullptr),
mIsConnected(false),
mTimeout(INFINITE) {}
MiniShmParent::~MiniShmParent() { CleanUp(); }
void MiniShmParent::CleanUp() {
if (mRegWait) {
::UnregisterWaitEx(mRegWait, INVALID_HANDLE_VALUE);
mRegWait = nullptr;
}
if (mParentEvent) {
::CloseHandle(mParentEvent);
mParentEvent = nullptr;
}
if (mParentGuard) {
::CloseHandle(mParentGuard);
mParentGuard = nullptr;
}
if (mChildEvent) {
::CloseHandle(mChildEvent);
mChildEvent = nullptr;
}
if (mChildGuard) {
::CloseHandle(mChildGuard);
mChildGuard = nullptr;
}
if (mView) {
::UnmapViewOfFile(mView);
mView = nullptr;
}
if (mFileMapping) {
::CloseHandle(mFileMapping);
mFileMapping = nullptr;
}
}
nsresult MiniShmParent::Init(MiniShmObserver* aObserver, const DWORD aTimeout,
const unsigned int aSectionSize) {
if (!aObserver || !aSectionSize || (aSectionSize % 0x1000) || !aTimeout) {
return NS_ERROR_ILLEGAL_VALUE;
}
if (mFileMapping) {
return NS_ERROR_ALREADY_INITIALIZED;
}
SECURITY_ATTRIBUTES securityAttributes = {sizeof(securityAttributes), nullptr,
TRUE};
ScopedHandle parentEvent(
::CreateEvent(&securityAttributes, FALSE, FALSE, nullptr));
if (!parentEvent.IsValid()) {
return NS_ERROR_FAILURE;
}
ScopedHandle parentGuard(
::CreateEvent(&securityAttributes, FALSE, TRUE, nullptr));
if (!parentGuard.IsValid()) {
return NS_ERROR_FAILURE;
}
ScopedHandle childEvent(
::CreateEvent(&securityAttributes, FALSE, FALSE, nullptr));
if (!childEvent.IsValid()) {
return NS_ERROR_FAILURE;
}
ScopedHandle childGuard(
::CreateEvent(&securityAttributes, FALSE, TRUE, nullptr));
if (!childGuard.IsValid()) {
return NS_ERROR_FAILURE;
}
ScopedHandle mapping(::CreateFileMapping(INVALID_HANDLE_VALUE,
&securityAttributes, PAGE_READWRITE,
0, aSectionSize, nullptr));
if (!mapping.IsValid()) {
return NS_ERROR_FAILURE;
}
ScopedMappedFileView view(::MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0));
if (!view.IsValid()) {
return NS_ERROR_FAILURE;
}
nsresult rv = SetView(view, aSectionSize, false);
NS_ENSURE_SUCCESS(rv, rv);
rv = SetGuard(childGuard, aTimeout);
NS_ENSURE_SUCCESS(rv, rv);
MiniShmInit* initStruct = nullptr;
rv = GetWritePtrInternal(initStruct);
NS_ENSURE_SUCCESS(rv, rv);
initStruct->mParentEvent = parentEvent;
initStruct->mParentGuard = parentGuard;
initStruct->mChildEvent = childEvent;
initStruct->mChildGuard = childGuard;
if (!::RegisterWaitForSingleObject(&mRegWait, parentEvent, &SOnEvent, this,
INFINITE, WT_EXECUTEDEFAULT)) {
return NS_ERROR_FAILURE;
}
mParentEvent = parentEvent.Take();
mParentGuard = parentGuard.Take();
mChildEvent = childEvent.Take();
mChildGuard = childGuard.Take();
mFileMapping = mapping.Take();
mView = view.Take();
mSectionSize = aSectionSize;
SetObserver(aObserver);
mTimeout = aTimeout;
return NS_OK;
}
nsresult MiniShmParent::GetCookie(std::wstring& cookie) {
if (!mFileMapping) {
return NS_ERROR_NOT_INITIALIZED;
}
std::wostringstream oss;
oss << mFileMapping;
if (!oss) {
return NS_ERROR_FAILURE;
}
cookie = oss.str();
return NS_OK;
}
nsresult MiniShmParent::Send() {
if (!mChildEvent) {
return NS_ERROR_NOT_INITIALIZED;
}
if (!::SetEvent(mChildEvent)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
bool MiniShmParent::IsConnected() const { return mIsConnected; }
void MiniShmParent::OnEvent() {
if (mIsConnected) {
MiniShmBase::OnEvent();
} else {
FinalizeConnection();
}
::SetEvent(mParentGuard);
}
void MiniShmParent::FinalizeConnection() {
const MiniShmInitComplete* initCompleteStruct = nullptr;
nsresult rv = GetReadPtr(initCompleteStruct);
mIsConnected = NS_SUCCEEDED(rv) && initCompleteStruct->mSucceeded;
if (mIsConnected) {
OnConnect();
}
}
} // namespace plugins
} // namespace mozilla