|
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/. */ |
|
6 |
|
7 #include "MiniShmParent.h" |
|
8 |
|
9 #include "base/scoped_handle.h" |
|
10 |
|
11 #include <sstream> |
|
12 |
|
13 namespace mozilla { |
|
14 namespace plugins { |
|
15 |
|
16 // static |
|
17 const unsigned int MiniShmParent::kDefaultMiniShmSectionSize = 0x1000; |
|
18 |
|
19 MiniShmParent::MiniShmParent() |
|
20 : mSectionSize(0), |
|
21 mParentEvent(nullptr), |
|
22 mParentGuard(nullptr), |
|
23 mChildEvent(nullptr), |
|
24 mChildGuard(nullptr), |
|
25 mRegWait(nullptr), |
|
26 mFileMapping(nullptr), |
|
27 mView(nullptr), |
|
28 mIsConnected(false), |
|
29 mTimeout(INFINITE) |
|
30 { |
|
31 } |
|
32 |
|
33 MiniShmParent::~MiniShmParent() |
|
34 { |
|
35 CleanUp(); |
|
36 } |
|
37 |
|
38 void |
|
39 MiniShmParent::CleanUp() |
|
40 { |
|
41 if (mRegWait) { |
|
42 ::UnregisterWaitEx(mRegWait, INVALID_HANDLE_VALUE); |
|
43 mRegWait = nullptr; |
|
44 } |
|
45 if (mParentEvent) { |
|
46 ::CloseHandle(mParentEvent); |
|
47 mParentEvent = nullptr; |
|
48 } |
|
49 if (mParentGuard) { |
|
50 ::CloseHandle(mParentGuard); |
|
51 mParentGuard = nullptr; |
|
52 } |
|
53 if (mChildEvent) { |
|
54 ::CloseHandle(mChildEvent); |
|
55 mChildEvent = nullptr; |
|
56 } |
|
57 if (mChildGuard) { |
|
58 ::CloseHandle(mChildGuard); |
|
59 mChildGuard = nullptr; |
|
60 } |
|
61 if (mView) { |
|
62 ::UnmapViewOfFile(mView); |
|
63 mView = nullptr; |
|
64 } |
|
65 if (mFileMapping) { |
|
66 ::CloseHandle(mFileMapping); |
|
67 mFileMapping = nullptr; |
|
68 } |
|
69 } |
|
70 |
|
71 nsresult |
|
72 MiniShmParent::Init(MiniShmObserver* aObserver, const DWORD aTimeout, |
|
73 const unsigned int aSectionSize) |
|
74 { |
|
75 if (!aObserver || !aSectionSize || (aSectionSize % 0x1000) || !aTimeout) { |
|
76 return NS_ERROR_ILLEGAL_VALUE; |
|
77 } |
|
78 if (mFileMapping) { |
|
79 return NS_ERROR_ALREADY_INITIALIZED; |
|
80 } |
|
81 SECURITY_ATTRIBUTES securityAttributes = {sizeof(securityAttributes), |
|
82 nullptr, |
|
83 TRUE}; |
|
84 ScopedHandle parentEvent(::CreateEvent(&securityAttributes, |
|
85 FALSE, |
|
86 FALSE, |
|
87 nullptr)); |
|
88 if (!parentEvent.IsValid()) { |
|
89 return NS_ERROR_FAILURE; |
|
90 } |
|
91 ScopedHandle parentGuard(::CreateEvent(&securityAttributes, |
|
92 FALSE, |
|
93 TRUE, |
|
94 nullptr)); |
|
95 if (!parentGuard.IsValid()) { |
|
96 return NS_ERROR_FAILURE; |
|
97 } |
|
98 ScopedHandle childEvent(::CreateEvent(&securityAttributes, |
|
99 FALSE, |
|
100 FALSE, |
|
101 nullptr)); |
|
102 if (!childEvent.IsValid()) { |
|
103 return NS_ERROR_FAILURE; |
|
104 } |
|
105 ScopedHandle childGuard(::CreateEvent(&securityAttributes, |
|
106 FALSE, |
|
107 TRUE, |
|
108 nullptr)); |
|
109 if (!childGuard.IsValid()) { |
|
110 return NS_ERROR_FAILURE; |
|
111 } |
|
112 ScopedHandle mapping(::CreateFileMapping(INVALID_HANDLE_VALUE, |
|
113 &securityAttributes, |
|
114 PAGE_READWRITE, |
|
115 0, |
|
116 aSectionSize, |
|
117 nullptr)); |
|
118 if (!mapping.IsValid()) { |
|
119 return NS_ERROR_FAILURE; |
|
120 } |
|
121 ScopedMappedFileView view(::MapViewOfFile(mapping, |
|
122 FILE_MAP_WRITE, |
|
123 0, 0, 0)); |
|
124 if (!view.IsValid()) { |
|
125 return NS_ERROR_FAILURE; |
|
126 } |
|
127 nsresult rv = SetView(view, aSectionSize, false); |
|
128 NS_ENSURE_SUCCESS(rv, rv); |
|
129 rv = SetGuard(childGuard, aTimeout); |
|
130 NS_ENSURE_SUCCESS(rv, rv); |
|
131 |
|
132 MiniShmInit* initStruct = nullptr; |
|
133 rv = GetWritePtrInternal(initStruct); |
|
134 NS_ENSURE_SUCCESS(rv, rv); |
|
135 initStruct->mParentEvent = parentEvent; |
|
136 initStruct->mParentGuard = parentGuard; |
|
137 initStruct->mChildEvent = childEvent; |
|
138 initStruct->mChildGuard = childGuard; |
|
139 |
|
140 if (!::RegisterWaitForSingleObject(&mRegWait, |
|
141 parentEvent, |
|
142 &SOnEvent, |
|
143 this, |
|
144 INFINITE, |
|
145 WT_EXECUTEDEFAULT)) { |
|
146 return NS_ERROR_FAILURE; |
|
147 } |
|
148 |
|
149 mParentEvent = parentEvent.Take(); |
|
150 mParentGuard = parentGuard.Take(); |
|
151 mChildEvent = childEvent.Take(); |
|
152 mChildGuard = childGuard.Take(); |
|
153 mFileMapping = mapping.Take(); |
|
154 mView = view.Take(); |
|
155 mSectionSize = aSectionSize; |
|
156 SetObserver(aObserver); |
|
157 mTimeout = aTimeout; |
|
158 return NS_OK; |
|
159 } |
|
160 |
|
161 nsresult |
|
162 MiniShmParent::GetCookie(std::wstring& cookie) |
|
163 { |
|
164 if (!mFileMapping) { |
|
165 return NS_ERROR_NOT_INITIALIZED; |
|
166 } |
|
167 std::wostringstream oss; |
|
168 oss << mFileMapping; |
|
169 if (!oss) { |
|
170 return NS_ERROR_FAILURE; |
|
171 } |
|
172 cookie = oss.str(); |
|
173 return NS_OK; |
|
174 } |
|
175 |
|
176 nsresult |
|
177 MiniShmParent::Send() |
|
178 { |
|
179 if (!mChildEvent) { |
|
180 return NS_ERROR_NOT_INITIALIZED; |
|
181 } |
|
182 if (!::SetEvent(mChildEvent)) { |
|
183 return NS_ERROR_FAILURE; |
|
184 } |
|
185 return NS_OK; |
|
186 } |
|
187 |
|
188 bool |
|
189 MiniShmParent::IsConnected() const |
|
190 { |
|
191 return mIsConnected; |
|
192 } |
|
193 |
|
194 void |
|
195 MiniShmParent::OnEvent() |
|
196 { |
|
197 if (mIsConnected) { |
|
198 MiniShmBase::OnEvent(); |
|
199 } else { |
|
200 FinalizeConnection(); |
|
201 } |
|
202 ::SetEvent(mParentGuard); |
|
203 } |
|
204 |
|
205 void |
|
206 MiniShmParent::FinalizeConnection() |
|
207 { |
|
208 const MiniShmInitComplete* initCompleteStruct = nullptr; |
|
209 nsresult rv = GetReadPtr(initCompleteStruct); |
|
210 mIsConnected = NS_SUCCEEDED(rv) && initCompleteStruct->mSucceeded; |
|
211 if (mIsConnected) { |
|
212 OnConnect(); |
|
213 } |
|
214 } |
|
215 |
|
216 } // namespace plugins |
|
217 } // namespace mozilla |
|
218 |