Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "MiniShmChild.h"
9 #include <limits>
10 #include <sstream>
12 namespace mozilla {
13 namespace plugins {
15 MiniShmChild::MiniShmChild()
16 : mParentEvent(nullptr),
17 mParentGuard(nullptr),
18 mChildEvent(nullptr),
19 mChildGuard(nullptr),
20 mFileMapping(nullptr),
21 mRegWait(nullptr),
22 mView(nullptr),
23 mTimeout(INFINITE)
24 {}
26 MiniShmChild::~MiniShmChild()
27 {
28 if (mRegWait) {
29 ::UnregisterWaitEx(mRegWait, INVALID_HANDLE_VALUE);
30 }
31 if (mParentGuard) {
32 // Try to avoid shutting down while the parent's event handler is running.
33 ::WaitForSingleObject(mParentGuard, mTimeout);
34 ::CloseHandle(mParentGuard);
35 }
36 if (mParentEvent) {
37 ::CloseHandle(mParentEvent);
38 }
39 if (mChildEvent) {
40 ::CloseHandle(mChildEvent);
41 }
42 if (mChildGuard) {
43 ::CloseHandle(mChildGuard);
44 }
45 if (mView) {
46 ::UnmapViewOfFile(mView);
47 }
48 if (mFileMapping) {
49 ::CloseHandle(mFileMapping);
50 }
51 }
53 nsresult
54 MiniShmChild::Init(MiniShmObserver* aObserver, const std::wstring& aCookie,
55 const DWORD aTimeout)
56 {
57 if (aCookie.empty() || !aTimeout) {
58 return NS_ERROR_ILLEGAL_VALUE;
59 }
60 if (mFileMapping) {
61 return NS_ERROR_ALREADY_INITIALIZED;
62 }
63 std::wistringstream iss(aCookie);
64 HANDLE mapHandle = nullptr;
65 iss >> mapHandle;
66 if (!iss) {
67 return NS_ERROR_ILLEGAL_VALUE;
68 }
69 ScopedMappedFileView view(::MapViewOfFile(mapHandle,
70 FILE_MAP_WRITE,
71 0, 0, 0));
72 if (!view.IsValid()) {
73 return NS_ERROR_FAILURE;
74 }
75 MEMORY_BASIC_INFORMATION memInfo = {0};
76 SIZE_T querySize = ::VirtualQuery(view, &memInfo, sizeof(memInfo));
77 unsigned int mappingSize = 0;
78 if (querySize) {
79 if (memInfo.RegionSize <= std::numeric_limits<unsigned int>::max()) {
80 mappingSize = static_cast<unsigned int>(memInfo.RegionSize);
81 }
82 }
83 if (!querySize || !mappingSize) {
84 return NS_ERROR_FAILURE;
85 }
86 nsresult rv = SetView(view, mappingSize, true);
87 if (NS_FAILED(rv)) {
88 return rv;
89 }
91 const MiniShmInit* initStruct = nullptr;
92 rv = GetReadPtr(initStruct);
93 if (NS_FAILED(rv)) {
94 return rv;
95 }
96 if (!initStruct->mParentEvent || !initStruct->mParentGuard ||
97 !initStruct->mChildEvent || !initStruct->mChildGuard) {
98 return NS_ERROR_FAILURE;
99 }
100 rv = SetGuard(initStruct->mParentGuard, aTimeout);
101 if (NS_FAILED(rv)) {
102 return rv;
103 }
104 if (!::RegisterWaitForSingleObject(&mRegWait,
105 initStruct->mChildEvent,
106 &SOnEvent,
107 this,
108 INFINITE,
109 WT_EXECUTEDEFAULT)) {
110 return NS_ERROR_FAILURE;
111 }
113 MiniShmInitComplete* initCompleteStruct = nullptr;
114 rv = GetWritePtrInternal(initCompleteStruct);
115 if (NS_FAILED(rv)) {
116 ::UnregisterWaitEx(mRegWait, INVALID_HANDLE_VALUE);
117 mRegWait = nullptr;
118 return NS_ERROR_FAILURE;
119 }
121 initCompleteStruct->mSucceeded = true;
123 // We must set the member variables before we signal the event
124 mFileMapping = mapHandle;
125 mView = view.Take();
126 mParentEvent = initStruct->mParentEvent;
127 mParentGuard = initStruct->mParentGuard;
128 mChildEvent = initStruct->mChildEvent;
129 mChildGuard = initStruct->mChildGuard;
130 SetObserver(aObserver);
131 mTimeout = aTimeout;
133 rv = Send();
134 if (NS_FAILED(rv)) {
135 initCompleteStruct->mSucceeded = false;
136 mFileMapping = nullptr;
137 view.Set(mView);
138 mView = nullptr;
139 mParentEvent = nullptr;
140 mParentGuard = nullptr;
141 mChildEvent = nullptr;
142 mChildGuard = nullptr;
143 ::UnregisterWaitEx(mRegWait, INVALID_HANDLE_VALUE);
144 mRegWait = nullptr;
145 return rv;
146 }
148 OnConnect();
149 return NS_OK;
150 }
152 nsresult
153 MiniShmChild::Send()
154 {
155 if (!mParentEvent) {
156 return NS_ERROR_NOT_INITIALIZED;
157 }
158 if (!::SetEvent(mParentEvent)) {
159 return NS_ERROR_FAILURE;
160 }
161 return NS_OK;
162 }
164 void
165 MiniShmChild::OnEvent()
166 {
167 MiniShmBase::OnEvent();
168 ::SetEvent(mChildGuard);
169 }
171 } // namespace plugins
172 } // namespace mozilla