|
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
2 * vim: sw=4 ts=4 et : |
|
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 "mozilla/ipc/IOThreadChild.h" |
|
8 #include "mozilla/plugins/PluginProcessChild.h" |
|
9 |
|
10 #include "prlink.h" |
|
11 |
|
12 #include "base/command_line.h" |
|
13 #include "base/string_util.h" |
|
14 #include "chrome/common/chrome_switches.h" |
|
15 |
|
16 #if defined(XP_MACOSX) |
|
17 #include "nsCocoaFeatures.h" |
|
18 // An undocumented CoreGraphics framework method, present in the same form |
|
19 // since at least OS X 10.5. |
|
20 extern "C" CGError CGSSetDebugOptions(int options); |
|
21 #endif |
|
22 |
|
23 #ifdef XP_WIN |
|
24 #include <objbase.h> |
|
25 bool ShouldProtectPluginCurrentDirectory(char16ptr_t pluginFilePath); |
|
26 #endif |
|
27 |
|
28 using mozilla::ipc::IOThreadChild; |
|
29 |
|
30 #ifdef OS_WIN |
|
31 #include "nsSetDllDirectory.h" |
|
32 #include <algorithm> |
|
33 |
|
34 namespace { |
|
35 |
|
36 std::size_t caseInsensitiveFind(std::string aHaystack, std::string aNeedle) { |
|
37 std::transform(aHaystack.begin(), aHaystack.end(), aHaystack.begin(), ::tolower); |
|
38 std::transform(aNeedle.begin(), aNeedle.end(), aNeedle.begin(), ::tolower); |
|
39 return aHaystack.find(aNeedle); |
|
40 } |
|
41 |
|
42 } |
|
43 #endif |
|
44 |
|
45 namespace mozilla { |
|
46 namespace plugins { |
|
47 |
|
48 |
|
49 bool |
|
50 PluginProcessChild::Init() |
|
51 { |
|
52 #if defined(XP_MACOSX) |
|
53 // Remove the trigger for "dyld interposing" that we added in |
|
54 // GeckoChildProcessHost::PerformAsyncLaunchInternal(), in the host |
|
55 // process just before we were launched. Dyld interposing will still |
|
56 // happen in our process (the plugin child process). But we don't want |
|
57 // it to happen in any processes that the plugin might launch from our |
|
58 // process. |
|
59 nsCString interpose(PR_GetEnv("DYLD_INSERT_LIBRARIES")); |
|
60 if (!interpose.IsEmpty()) { |
|
61 // If we added the path to libplugin_child_interpose.dylib to an |
|
62 // existing DYLD_INSERT_LIBRARIES, we appended it to the end, after a |
|
63 // ":" path seperator. |
|
64 int32_t lastSeparatorPos = interpose.RFind(":"); |
|
65 int32_t lastTriggerPos = interpose.RFind("libplugin_child_interpose.dylib"); |
|
66 bool needsReset = false; |
|
67 if (lastTriggerPos != -1) { |
|
68 if (lastSeparatorPos == -1) { |
|
69 interpose.Truncate(); |
|
70 needsReset = true; |
|
71 } else if (lastTriggerPos > lastSeparatorPos) { |
|
72 interpose.SetLength(lastSeparatorPos); |
|
73 needsReset = true; |
|
74 } |
|
75 } |
|
76 if (needsReset) { |
|
77 nsCString setInterpose("DYLD_INSERT_LIBRARIES="); |
|
78 if (!interpose.IsEmpty()) { |
|
79 setInterpose.Append(interpose); |
|
80 } |
|
81 // Values passed to PR_SetEnv() must be seperately allocated. |
|
82 char* setInterposePtr = strdup(setInterpose.get()); |
|
83 PR_SetEnv(setInterposePtr); |
|
84 } |
|
85 } |
|
86 #endif |
|
87 |
|
88 #ifdef XP_WIN |
|
89 // Drag-and-drop needs OleInitialize to be called, and Silverlight depends |
|
90 // on the host calling CoInitialize (which is called by OleInitialize). |
|
91 ::OleInitialize(nullptr); |
|
92 #endif |
|
93 |
|
94 // Certain plugins, such as flash, steal the unhandled exception filter |
|
95 // thus we never get crash reports when they fault. This call fixes it. |
|
96 message_loop()->set_exception_restoration(true); |
|
97 |
|
98 std::string pluginFilename; |
|
99 |
|
100 #if defined(OS_POSIX) |
|
101 // NB: need to be very careful in ensuring that the first arg |
|
102 // (after the binary name) here is indeed the plugin module path. |
|
103 // Keep in sync with dom/plugins/PluginModuleParent. |
|
104 std::vector<std::string> values = CommandLine::ForCurrentProcess()->argv(); |
|
105 NS_ABORT_IF_FALSE(values.size() >= 2, "not enough args"); |
|
106 |
|
107 pluginFilename = UnmungePluginDsoPath(values[1]); |
|
108 |
|
109 #elif defined(OS_WIN) |
|
110 std::vector<std::wstring> values = |
|
111 CommandLine::ForCurrentProcess()->GetLooseValues(); |
|
112 NS_ABORT_IF_FALSE(values.size() >= 1, "not enough loose args"); |
|
113 |
|
114 if (ShouldProtectPluginCurrentDirectory(values[0].c_str())) { |
|
115 SanitizeEnvironmentVariables(); |
|
116 SetDllDirectory(L""); |
|
117 } |
|
118 |
|
119 pluginFilename = WideToUTF8(values[0]); |
|
120 #else |
|
121 # error Sorry |
|
122 #endif |
|
123 |
|
124 if (NS_FAILED(nsRegion::InitStatic())) { |
|
125 NS_ERROR("Could not initialize nsRegion"); |
|
126 return false; |
|
127 } |
|
128 |
|
129 bool retval = mPlugin.Init(pluginFilename, ParentHandle(), |
|
130 IOThreadChild::message_loop(), |
|
131 IOThreadChild::channel()); |
|
132 #if defined(XP_MACOSX) |
|
133 if (nsCocoaFeatures::OnYosemiteOrLater()) { |
|
134 // Explicitly turn off CGEvent logging. This works around bug 1092855. |
|
135 // If there are already CGEvents in the log, turning off logging also |
|
136 // causes those events to be written to disk. But at this point no |
|
137 // CGEvents have yet been processed. CGEvents are events (usually |
|
138 // input events) pulled from the WindowServer. An option of 0x80000008 |
|
139 // turns on CGEvent logging. |
|
140 CGSSetDebugOptions(0x80000007); |
|
141 } |
|
142 #endif |
|
143 return retval; |
|
144 } |
|
145 |
|
146 void |
|
147 PluginProcessChild::CleanUp() |
|
148 { |
|
149 #ifdef XP_WIN |
|
150 ::OleUninitialize(); |
|
151 #endif |
|
152 nsRegion::ShutdownStatic(); |
|
153 } |
|
154 |
|
155 } // namespace plugins |
|
156 } // namespace mozilla |