Hang beneath PluginProcessProxy::createPropertyListFile() when using a thin build
[WebKit-https.git] / Source / WebKit2 / UIProcess / Plugins / mac / PluginProcessProxyMac.mm
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "PluginProcessProxy.h"
28
29 #if ENABLE(PLUGIN_PROCESS)
30
31 #import "EnvironmentVariables.h"
32 #import "PluginProcessCreationParameters.h"
33 #import "WebKitSystemInterface.h"
34 #import <WebCore/FileSystem.h>
35 #import <spawn.h>
36 #import <wtf/text/CString.h>
37
38 @interface WKPlaceholderModalWindow : NSWindow 
39 @end
40
41 @implementation WKPlaceholderModalWindow
42
43 // Prevent NSApp from calling requestUserAttention: when the window is shown 
44 // modally, even if the app is inactive. See 6823049.
45 - (BOOL)_wantsUserAttention
46 {
47     return NO;   
48 }
49
50 @end
51
52 using namespace WebCore;
53
54 namespace WebKit {
55     
56 bool PluginProcessProxy::pluginNeedsExecutableHeap(const PluginModuleInfo& pluginInfo)
57 {
58     static bool forceNonexecutableHeapForPlugins = [[NSUserDefaults standardUserDefaults] boolForKey:@"ForceNonexecutableHeapForPlugins"];
59     if (forceNonexecutableHeapForPlugins)
60         return false;
61     
62     if (pluginInfo.bundleIdentifier == "com.apple.QuickTime Plugin.plugin")
63         return false;
64     
65     return true;
66 }
67
68 bool PluginProcessProxy::createPropertyListFile(const PluginModuleInfo& plugin)
69 {
70     NSBundle *webKit2Bundle = [NSBundle bundleWithIdentifier:@"com.apple.WebKit2"];
71     NSString *frameworksPath = [[webKit2Bundle bundlePath] stringByDeletingLastPathComponent];
72     const char* frameworkExecutablePath = [[webKit2Bundle executablePath] fileSystemRepresentation];
73     
74     NSString *processPath = [webKit2Bundle pathForAuxiliaryExecutable:@"PluginProcess.app"];
75     NSString *processAppExecutablePath = [[NSBundle bundleWithPath:processPath] executablePath];
76
77     CString pluginPathString = fileSystemRepresentation(plugin.path);
78
79     posix_spawnattr_t attr;
80     posix_spawnattr_init(&attr);
81
82     cpu_type_t cpuTypes[] = { plugin.pluginArchitecture };    
83     size_t outCount = 0;
84     posix_spawnattr_setbinpref_np(&attr, 1, cpuTypes, &outCount);
85
86     EnvironmentVariables environmentVariables;
87     
88     // To make engineering builds work, if the path is outside of /System set up
89     // DYLD_FRAMEWORK_PATH to pick up other frameworks, but don't do it for the
90     // production configuration because it involves extra file system access.
91     if (![frameworksPath hasPrefix:@"/System/"])
92         environmentVariables.appendValue("DYLD_FRAMEWORK_PATH", [frameworksPath fileSystemRepresentation], ':');
93
94     const char* args[] = { [processAppExecutablePath fileSystemRepresentation], frameworkExecutablePath, "-type", "pluginprocess", "-createPluginMIMETypesPreferences", pluginPathString.data(), 0 };
95
96     pid_t pid;
97     int result = posix_spawn(&pid, args[0], 0, &attr, const_cast<char* const*>(args), environmentVariables.environmentPointer());
98     posix_spawnattr_destroy(&attr);
99
100     if (result)
101         return false;
102     int status;
103     if (waitpid(pid, &status, 0) < 0)
104         return false;
105
106     if (!WIFEXITED(status))
107         return false;
108
109     if (WEXITSTATUS(status) != EXIT_SUCCESS)
110         return false;
111
112     return true;
113 }
114
115 void PluginProcessProxy::platformInitializePluginProcess(PluginProcessCreationParameters& parameters)
116 {
117 #if USE(ACCELERATED_COMPOSITING) && HAVE(HOSTED_CORE_ANIMATION)
118     parameters.parentProcessName = [[NSProcessInfo processInfo] processName];
119     mach_port_t renderServerPort = WKInitializeRenderServer();
120     if (renderServerPort != MACH_PORT_NULL)
121         parameters.acceleratedCompositingPort = CoreIPC::MachPort(renderServerPort, MACH_MSG_TYPE_COPY_SEND);
122 #endif
123 }
124
125 bool PluginProcessProxy::getPluginProcessSerialNumber(ProcessSerialNumber& pluginProcessSerialNumber)
126 {
127     pid_t pluginProcessPID = m_processLauncher->processIdentifier();
128     return GetProcessForPID(pluginProcessPID, &pluginProcessSerialNumber) == noErr;
129 }
130
131 void PluginProcessProxy::makePluginProcessTheFrontProcess()
132 {
133     ProcessSerialNumber pluginProcessSerialNumber;
134     if (!getPluginProcessSerialNumber(pluginProcessSerialNumber))
135         return;
136
137     SetFrontProcess(&pluginProcessSerialNumber);
138 }
139
140 void PluginProcessProxy::makeUIProcessTheFrontProcess()
141 {
142     ProcessSerialNumber processSerialNumber;
143     GetCurrentProcess(&processSerialNumber);
144     SetFrontProcess(&processSerialNumber);            
145 }
146
147 void PluginProcessProxy::setFullscreenWindowIsShowing(bool fullscreenWindowIsShowing)
148 {
149     if (m_fullscreenWindowIsShowing == fullscreenWindowIsShowing)
150         return;
151
152     m_fullscreenWindowIsShowing = fullscreenWindowIsShowing;
153     if (m_fullscreenWindowIsShowing)
154         enterFullscreen();
155     else
156         exitFullscreen();
157 }
158
159 void PluginProcessProxy::enterFullscreen()
160 {
161     // Get the current presentation options.
162     m_preFullscreenAppPresentationOptions = [NSApp presentationOptions];
163
164     // Figure out which presentation options to use.
165     unsigned presentationOptions = m_preFullscreenAppPresentationOptions & ~(NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar);
166     presentationOptions |= NSApplicationPresentationHideDock | NSApplicationPresentationHideMenuBar;
167
168     [NSApp setPresentationOptions:presentationOptions];
169     makePluginProcessTheFrontProcess();
170 }
171
172 void PluginProcessProxy::exitFullscreen()
173 {
174     // If the plug-in host is the current application then we should bring ourselves to the front when it exits full-screen mode.
175     ProcessSerialNumber frontProcessSerialNumber;
176     GetFrontProcess(&frontProcessSerialNumber);
177
178     // The UI process must be the front process in order to change the presentation mode.
179     makeUIProcessTheFrontProcess();
180     [NSApp setPresentationOptions:m_preFullscreenAppPresentationOptions];
181
182     ProcessSerialNumber pluginProcessSerialNumber;
183     if (!getPluginProcessSerialNumber(pluginProcessSerialNumber))
184         return;
185
186     // If the plug-in process was not the front process, switch back to the previous front process.
187     // (Otherwise we'll keep the UI process as the front process).
188     Boolean isPluginProcessFrontProcess;
189     SameProcess(&frontProcessSerialNumber, &pluginProcessSerialNumber, &isPluginProcessFrontProcess);
190     if (!isPluginProcessFrontProcess)
191         SetFrontProcess(&frontProcessSerialNumber);
192 }
193
194 void PluginProcessProxy::setModalWindowIsShowing(bool modalWindowIsShowing)
195 {
196     if (modalWindowIsShowing == m_modalWindowIsShowing) 
197         return;
198     
199     m_modalWindowIsShowing = modalWindowIsShowing;
200     
201     if (m_modalWindowIsShowing)
202         beginModal();
203     else
204         endModal();
205 }
206
207 void PluginProcessProxy::beginModal()
208 {
209     ASSERT(!m_placeholderWindow);
210     ASSERT(!m_activationObserver);
211     
212     m_placeholderWindow.adoptNS([[WKPlaceholderModalWindow alloc] initWithContentRect:NSMakeRect(0, 0, 1, 1) styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES]);
213     [m_placeholderWindow.get() setReleasedWhenClosed:NO];
214     
215     m_activationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationWillBecomeActiveNotification object:NSApp queue:nil
216                                                                          usingBlock:^(NSNotification *){ applicationDidBecomeActive(); }];
217     
218     [NSApp runModalForWindow:m_placeholderWindow.get()];
219     
220     [m_placeholderWindow.get() orderOut:nil];
221     m_placeholderWindow = nullptr;
222 }
223
224 void PluginProcessProxy::endModal()
225 {
226     ASSERT(m_placeholderWindow);
227     ASSERT(m_activationObserver);
228     
229     [[NSNotificationCenter defaultCenter] removeObserver:m_activationObserver.get()];
230     m_activationObserver = nullptr;
231     
232     [NSApp stopModal];
233
234     makeUIProcessTheFrontProcess();
235 }
236     
237 void PluginProcessProxy::applicationDidBecomeActive()
238 {
239     makePluginProcessTheFrontProcess();
240 }
241
242
243 } // namespace WebKit
244
245 #endif // ENABLE(PLUGIN_PROCESS)