Line data Source code
1 : /* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- */
2 : /* vim: set sw=2 ts=8 et 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 "PluginMessageUtils.h"
8 : #include "nsIRunnable.h"
9 : #include "nsThreadUtils.h"
10 :
11 : #include "PluginInstanceParent.h"
12 : #include "PluginInstanceChild.h"
13 : #include "PluginScriptableObjectParent.h"
14 : #include "PluginScriptableObjectChild.h"
15 :
16 : using std::string;
17 :
18 : using mozilla::ipc::MessageChannel;
19 :
20 : namespace {
21 :
22 0 : class DeferNPObjectReleaseRunnable : public mozilla::Runnable
23 : {
24 : public:
25 0 : DeferNPObjectReleaseRunnable(const NPNetscapeFuncs* f, NPObject* o)
26 0 : : Runnable("DeferNPObjectReleaseRunnable")
27 : , mFuncs(f)
28 0 : , mObject(o)
29 : {
30 0 : NS_ASSERTION(o, "no release null objects");
31 0 : }
32 :
33 : NS_IMETHOD Run();
34 :
35 : private:
36 : const NPNetscapeFuncs* mFuncs;
37 : NPObject* mObject;
38 : };
39 :
40 : NS_IMETHODIMP
41 0 : DeferNPObjectReleaseRunnable::Run()
42 : {
43 0 : mFuncs->releaseobject(mObject);
44 0 : return NS_OK;
45 : }
46 :
47 : } // namespace
48 :
49 : namespace mozilla {
50 : namespace plugins {
51 :
52 0 : NPRemoteWindow::NPRemoteWindow() :
53 : window(0), x(0), y(0), width(0), height(0), type(NPWindowTypeDrawable)
54 : #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
55 : , visualID(0)
56 0 : , colormap(0)
57 : #endif /* XP_UNIX */
58 : #if defined(XP_MACOSX)
59 : ,contentsScaleFactor(1.0)
60 : #endif
61 : {
62 0 : clipRect.top = 0;
63 0 : clipRect.left = 0;
64 0 : clipRect.bottom = 0;
65 0 : clipRect.right = 0;
66 0 : }
67 :
68 : ipc::RacyInterruptPolicy
69 0 : MediateRace(const MessageChannel::MessageInfo& parent,
70 : const MessageChannel::MessageInfo& child)
71 : {
72 0 : switch (parent.type()) {
73 : case PPluginInstance::Msg_Paint__ID:
74 : case PPluginInstance::Msg_NPP_SetWindow__ID:
75 : case PPluginInstance::Msg_NPP_HandleEvent_Shmem__ID:
76 : case PPluginInstance::Msg_NPP_HandleEvent_IOSurface__ID:
77 : // our code relies on the frame list not changing during paints and
78 : // reflows
79 0 : return ipc::RIPParentWins;
80 :
81 : default:
82 0 : return ipc::RIPChildWins;
83 : }
84 : }
85 :
86 : #if defined(OS_LINUX) || defined(OS_SOLARIS)
87 : static string
88 0 : ReplaceAll(const string& haystack, const string& needle, const string& with)
89 : {
90 0 : string munged = haystack;
91 0 : string::size_type i = 0;
92 :
93 0 : while (string::npos != (i = munged.find(needle, i))) {
94 0 : munged.replace(i, needle.length(), with);
95 0 : i += with.length();
96 : }
97 :
98 0 : return munged;
99 : }
100 : #endif
101 :
102 : string
103 0 : MungePluginDsoPath(const string& path)
104 : {
105 : #if defined(OS_LINUX) || defined(OS_SOLARIS)
106 : // https://bugzilla.mozilla.org/show_bug.cgi?id=519601
107 0 : return ReplaceAll(path, "netscape", "netsc@pe");
108 : #else
109 : return path;
110 : #endif
111 : }
112 :
113 : string
114 0 : UnmungePluginDsoPath(const string& munged)
115 : {
116 : #if defined(OS_LINUX) || defined(OS_SOLARIS)
117 0 : return ReplaceAll(munged, "netsc@pe", "netscape");
118 : #else
119 : return munged;
120 : #endif
121 : }
122 :
123 :
124 : LogModule*
125 0 : GetPluginLog()
126 : {
127 : static LazyLogModule sLog("IPCPlugins");
128 0 : return sLog;
129 : }
130 :
131 : void
132 0 : DeferNPObjectLastRelease(const NPNetscapeFuncs* f, NPObject* o)
133 : {
134 0 : if (!o)
135 0 : return;
136 :
137 0 : if (o->referenceCount > 1) {
138 0 : f->releaseobject(o);
139 0 : return;
140 : }
141 :
142 0 : NS_DispatchToCurrentThread(new DeferNPObjectReleaseRunnable(f, o));
143 : }
144 :
145 0 : void DeferNPVariantLastRelease(const NPNetscapeFuncs* f, NPVariant* v)
146 : {
147 0 : if (!NPVARIANT_IS_OBJECT(*v)) {
148 0 : f->releasevariantvalue(v);
149 0 : return;
150 : }
151 0 : DeferNPObjectLastRelease(f, v->value.objectValue);
152 0 : VOID_TO_NPVARIANT(*v);
153 : }
154 :
155 : #ifdef XP_WIN
156 : void
157 : OpenFileNameIPC::CopyFromOfn(LPOPENFILENAMEW aLpofn)
158 : {
159 : mHwndOwner = nullptr;
160 :
161 : // Filter is double-NULL terminated. mFilter should include the double-NULL.
162 : mHasFilter = aLpofn->lpstrFilter != nullptr;
163 : if (mHasFilter) {
164 : uint32_t dNullIdx = 0;
165 : while (aLpofn->lpstrFilter[dNullIdx] != L'\0' ||
166 : aLpofn->lpstrFilter[dNullIdx+1] != L'\0') {
167 : dNullIdx++;
168 : }
169 : mFilter.assign(aLpofn->lpstrFilter, dNullIdx+2);
170 : }
171 : mHasCustomFilter = aLpofn->lpstrCustomFilter != nullptr;
172 : if (mHasCustomFilter) {
173 : mCustomFilterIn = std::wstring(aLpofn->lpstrCustomFilter);
174 : mNMaxCustFilterOut =
175 : aLpofn->nMaxCustFilter - (wcslen(aLpofn->lpstrCustomFilter) + 1);
176 : }
177 : else {
178 : mNMaxCustFilterOut = 0;
179 : }
180 : mFilterIndex = aLpofn->nFilterIndex;
181 : mFile = std::wstring(aLpofn->lpstrFile);
182 : mNMaxFile = aLpofn->nMaxFile;
183 : mNMaxFileTitle =
184 : aLpofn->lpstrFileTitle != nullptr ? aLpofn->nMaxFileTitle : 0;
185 : mHasInitialDir = aLpofn->lpstrInitialDir != nullptr;
186 : if (mHasInitialDir) {
187 : mInitialDir = std::wstring(aLpofn->lpstrInitialDir);
188 : }
189 : mHasTitle = aLpofn->lpstrTitle != nullptr;
190 : if (mHasTitle) {
191 : mTitle = std::wstring(aLpofn->lpstrTitle);
192 : }
193 : mHasDefExt = aLpofn->lpstrDefExt != nullptr;
194 : if (mHasDefExt) {
195 : mDefExt = std::wstring(aLpofn->lpstrDefExt);
196 : }
197 :
198 : mFlags = aLpofn->Flags;
199 : // If the user sets OFN_ALLOWMULTISELECT then we require OFN_EXPLORER
200 : // as well. Without OFN_EXPLORER, the method has ancient legacy
201 : // behavior that we don't support.
202 : MOZ_ASSERT((mFlags & OFN_EXPLORER) || !(mFlags & OFN_ALLOWMULTISELECT));
203 :
204 : // We ignore any visual customization and callbacks that the user set.
205 : mFlags &= ~(OFN_ENABLEHOOK | OFN_ENABLETEMPLATEHANDLE | OFN_ENABLETEMPLATE);
206 :
207 : mFlagsEx = aLpofn->FlagsEx;
208 : }
209 :
210 : void
211 : OpenFileNameIPC::AddToOfn(LPOPENFILENAMEW aLpofn) const
212 : {
213 : aLpofn->lStructSize = sizeof(OPENFILENAMEW);
214 : aLpofn->hwndOwner = mHwndOwner;
215 : if (mHasFilter) {
216 : memcpy(const_cast<LPWSTR>(aLpofn->lpstrFilter),
217 : mFilter.data(), mFilter.size() * sizeof(wchar_t));
218 : }
219 : if (mHasCustomFilter) {
220 : aLpofn->nMaxCustFilter = mCustomFilterIn.size() + 1 + mNMaxCustFilterOut;
221 : wcscpy(aLpofn->lpstrCustomFilter, mCustomFilterIn.c_str());
222 : memset(aLpofn->lpstrCustomFilter + mCustomFilterIn.size() + 1, 0,
223 : mNMaxCustFilterOut * sizeof(wchar_t));
224 : }
225 : else {
226 : aLpofn->nMaxCustFilter = 0;
227 : }
228 : aLpofn->nFilterIndex = mFilterIndex;
229 : wcscpy(aLpofn->lpstrFile, mFile.c_str());
230 : aLpofn->nMaxFile = mNMaxFile;
231 : aLpofn->nMaxFileTitle = mNMaxFileTitle;
232 : if (mHasInitialDir) {
233 : wcscpy(const_cast<LPWSTR>(aLpofn->lpstrInitialDir), mInitialDir.c_str());
234 : }
235 : if (mHasTitle) {
236 : wcscpy(const_cast<LPWSTR>(aLpofn->lpstrTitle), mTitle.c_str());
237 : }
238 : aLpofn->Flags = mFlags; /* TODO: Consider adding OFN_NOCHANGEDIR */
239 : if (mHasDefExt) {
240 : wcscpy(const_cast<LPWSTR>(aLpofn->lpstrDefExt), mDefExt.c_str());
241 : }
242 : aLpofn->FlagsEx = mFlagsEx;
243 : }
244 :
245 : void
246 : OpenFileNameIPC::AllocateOfnStrings(LPOPENFILENAMEW aLpofn) const
247 : {
248 : if (mHasFilter) {
249 : // mFilter is double-NULL terminated and it includes the double-NULL in its length.
250 : aLpofn->lpstrFilter =
251 : static_cast<LPCTSTR>(moz_xmalloc(sizeof(wchar_t) * (mFilter.size())));
252 : }
253 : if (mHasCustomFilter) {
254 : aLpofn->lpstrCustomFilter =
255 : static_cast<LPTSTR>(moz_xmalloc(sizeof(wchar_t) * (mCustomFilterIn.size() + 1) + mNMaxCustFilterOut));
256 : }
257 : aLpofn->lpstrFile =
258 : static_cast<LPTSTR>(moz_xmalloc(sizeof(wchar_t) * mNMaxFile));
259 : if (mNMaxFileTitle > 0) {
260 : aLpofn->lpstrFileTitle =
261 : static_cast<LPTSTR>(moz_xmalloc(sizeof(wchar_t) * mNMaxFileTitle));
262 : }
263 : if (mHasInitialDir) {
264 : aLpofn->lpstrInitialDir =
265 : static_cast<LPCTSTR>(moz_xmalloc(sizeof(wchar_t) * (mInitialDir.size() + 1)));
266 : }
267 : if (mHasTitle) {
268 : aLpofn->lpstrTitle =
269 : static_cast<LPCTSTR>(moz_xmalloc(sizeof(wchar_t) * (mTitle.size() + 1)));
270 : }
271 : if (mHasDefExt) {
272 : aLpofn->lpstrDefExt =
273 : static_cast<LPCTSTR>(moz_xmalloc(sizeof(wchar_t) * (mDefExt.size() + 1)));
274 : }
275 : }
276 :
277 : void
278 : OpenFileNameIPC::FreeOfnStrings(LPOPENFILENAMEW aLpofn) const
279 : {
280 : if (aLpofn->lpstrFilter) {
281 : free(const_cast<LPWSTR>(aLpofn->lpstrFilter));
282 : }
283 : if (aLpofn->lpstrCustomFilter) {
284 : free(aLpofn->lpstrCustomFilter);
285 : }
286 : if (aLpofn->lpstrFile) {
287 : free(aLpofn->lpstrFile);
288 : }
289 : if (aLpofn->lpstrFileTitle) {
290 : free(aLpofn->lpstrFileTitle);
291 : }
292 : if (aLpofn->lpstrInitialDir) {
293 : free(const_cast<LPWSTR>(aLpofn->lpstrInitialDir));
294 : }
295 : if (aLpofn->lpstrTitle) {
296 : free(const_cast<LPWSTR>(aLpofn->lpstrTitle));
297 : }
298 : if (aLpofn->lpstrDefExt) {
299 : free(const_cast<LPWSTR>(aLpofn->lpstrDefExt));
300 : }
301 : }
302 :
303 : void
304 : OpenFileNameRetIPC::CopyFromOfn(LPOPENFILENAMEW aLpofn)
305 : {
306 : if (aLpofn->lpstrCustomFilter != nullptr) {
307 : mCustomFilterOut =
308 : std::wstring(aLpofn->lpstrCustomFilter + wcslen(aLpofn->lpstrCustomFilter) + 1);
309 : }
310 : mFile.assign(aLpofn->lpstrFile, aLpofn->nMaxFile);
311 : if (aLpofn->lpstrFileTitle != nullptr) {
312 : mFileTitle.assign(aLpofn->lpstrFileTitle, wcslen(aLpofn->lpstrFileTitle) + 1);
313 : }
314 : mFileOffset = aLpofn->nFileOffset;
315 : mFileExtension = aLpofn->nFileExtension;
316 : }
317 :
318 : void
319 : OpenFileNameRetIPC::AddToOfn(LPOPENFILENAMEW aLpofn) const
320 : {
321 : if (aLpofn->lpstrCustomFilter) {
322 : LPWSTR secondString =
323 : aLpofn->lpstrCustomFilter + wcslen(aLpofn->lpstrCustomFilter) + 1;
324 : const wchar_t* customFilterOut = mCustomFilterOut.c_str();
325 : MOZ_ASSERT(wcslen(aLpofn->lpstrCustomFilter) + 1 +
326 : wcslen(customFilterOut) + 1 + 1 <= aLpofn->nMaxCustFilter);
327 : wcscpy(secondString, customFilterOut);
328 : secondString[wcslen(customFilterOut) + 1] = L'\0'; // terminated with two NULLs
329 : }
330 : MOZ_ASSERT(mFile.size() <= aLpofn->nMaxFile);
331 : memcpy(aLpofn->lpstrFile,
332 : mFile.data(), mFile.size() * sizeof(wchar_t));
333 : if (aLpofn->lpstrFileTitle != nullptr) {
334 : MOZ_ASSERT(mFileTitle.size() + 1 < aLpofn->nMaxFileTitle);
335 : wcscpy(aLpofn->lpstrFileTitle, mFileTitle.c_str());
336 : }
337 : aLpofn->nFileOffset = mFileOffset;
338 : aLpofn->nFileExtension = mFileExtension;
339 : }
340 : #endif // XP_WIN
341 :
342 : } // namespace plugins
343 : } // namespace mozilla
|