<http://webkit.org/b/91015> Remove BUILDING_ON / TARGETING macros in favor of system...
[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 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
39 #import <QuartzCore/CARemoteLayerServer.h>
40 #endif
41
42 @interface WKPlaceholderModalWindow : NSWindow 
43 @end
44
45 @implementation WKPlaceholderModalWindow
46
47 // Prevent NSApp from calling requestUserAttention: when the window is shown 
48 // modally, even if the app is inactive. See 6823049.
49 - (BOOL)_wantsUserAttention
50 {
51     return NO;   
52 }
53
54 @end
55
56 using namespace WebCore;
57
58 namespace WebKit {
59     
60 bool PluginProcessProxy::pluginNeedsExecutableHeap(const PluginModuleInfo& pluginInfo)
61 {
62     static bool forceNonexecutableHeapForPlugins = [[NSUserDefaults standardUserDefaults] boolForKey:@"ForceNonexecutableHeapForPlugins"];
63     if (forceNonexecutableHeapForPlugins)
64         return false;
65     
66     if (pluginInfo.bundleIdentifier == "com.apple.QuickTime Plugin.plugin")
67         return false;
68     
69     return true;
70 }
71
72 bool PluginProcessProxy::createPropertyListFile(const PluginModuleInfo& plugin)
73 {
74     NSBundle *webKit2Bundle = [NSBundle bundleWithIdentifier:@"com.apple.WebKit2"];
75     NSString *frameworksPath = [[webKit2Bundle bundlePath] stringByDeletingLastPathComponent];
76     const char* frameworkExecutablePath = [[webKit2Bundle executablePath] fileSystemRepresentation];
77     
78     NSString *processPath = [webKit2Bundle pathForAuxiliaryExecutable:@"PluginProcess.app"];
79     NSString *processAppExecutablePath = [[NSBundle bundleWithPath:processPath] executablePath];
80
81     CString pluginPathString = fileSystemRepresentation(plugin.path);
82
83     posix_spawnattr_t attr;
84     posix_spawnattr_init(&attr);
85
86     cpu_type_t cpuTypes[] = { plugin.pluginArchitecture };    
87     size_t outCount = 0;
88     posix_spawnattr_setbinpref_np(&attr, 1, cpuTypes, &outCount);
89
90     EnvironmentVariables environmentVariables;
91     
92     // To make engineering builds work, if the path is outside of /System set up
93     // DYLD_FRAMEWORK_PATH to pick up other frameworks, but don't do it for the
94     // production configuration because it involves extra file system access.
95     if (![frameworksPath hasPrefix:@"/System/"])
96         environmentVariables.appendValue("DYLD_FRAMEWORK_PATH", [frameworksPath fileSystemRepresentation], ':');
97
98     const char* args[] = { [processAppExecutablePath fileSystemRepresentation], frameworkExecutablePath, "-type", "pluginprocess", "-createPluginMIMETypesPreferences", pluginPathString.data(), 0 };
99
100     pid_t pid;
101     int result = posix_spawn(&pid, args[0], 0, &attr, const_cast<char* const*>(args), environmentVariables.environmentPointer());
102     posix_spawnattr_destroy(&attr);
103
104     if (result)
105         return false;
106     int status;
107     if (waitpid(pid, &status, 0) < 0)
108         return false;
109
110     if (!WIFEXITED(status))
111         return false;
112
113     if (WEXITSTATUS(status) != EXIT_SUCCESS)
114         return false;
115
116     return true;
117 }
118
119 void PluginProcessProxy::platformInitializePluginProcess(PluginProcessCreationParameters& parameters)
120 {
121 #if USE(ACCELERATED_COMPOSITING) && HAVE(HOSTED_CORE_ANIMATION)
122     parameters.parentProcessName = [[NSProcessInfo processInfo] processName];
123 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
124     mach_port_t renderServerPort = [[CARemoteLayerServer sharedServer] serverPort];
125 #else
126     mach_port_t renderServerPort = WKInitializeRenderServer();
127 #endif
128
129     if (renderServerPort != MACH_PORT_NULL)
130         parameters.acceleratedCompositingPort = CoreIPC::MachPort(renderServerPort, MACH_MSG_TYPE_COPY_SEND);
131 #endif
132 }
133
134 bool PluginProcessProxy::getPluginProcessSerialNumber(ProcessSerialNumber& pluginProcessSerialNumber)
135 {
136     pid_t pluginProcessPID = m_processLauncher->processIdentifier();
137     return GetProcessForPID(pluginProcessPID, &pluginProcessSerialNumber) == noErr;
138 }
139
140 void PluginProcessProxy::makePluginProcessTheFrontProcess()
141 {
142     ProcessSerialNumber pluginProcessSerialNumber;
143     if (!getPluginProcessSerialNumber(pluginProcessSerialNumber))
144         return;
145
146     SetFrontProcess(&pluginProcessSerialNumber);
147 }
148
149 void PluginProcessProxy::makeUIProcessTheFrontProcess()
150 {
151     ProcessSerialNumber processSerialNumber;
152     GetCurrentProcess(&processSerialNumber);
153     SetFrontProcess(&processSerialNumber);            
154 }
155
156 void PluginProcessProxy::setFullscreenWindowIsShowing(bool fullscreenWindowIsShowing)
157 {
158     if (m_fullscreenWindowIsShowing == fullscreenWindowIsShowing)
159         return;
160
161     m_fullscreenWindowIsShowing = fullscreenWindowIsShowing;
162     if (m_fullscreenWindowIsShowing)
163         enterFullscreen();
164     else
165         exitFullscreen();
166 }
167
168 void PluginProcessProxy::enterFullscreen()
169 {
170     // Get the current presentation options.
171     m_preFullscreenAppPresentationOptions = [NSApp presentationOptions];
172
173     // Figure out which presentation options to use.
174     unsigned presentationOptions = m_preFullscreenAppPresentationOptions & ~(NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar);
175     presentationOptions |= NSApplicationPresentationHideDock | NSApplicationPresentationHideMenuBar;
176
177     [NSApp setPresentationOptions:presentationOptions];
178     makePluginProcessTheFrontProcess();
179 }
180
181 void PluginProcessProxy::exitFullscreen()
182 {
183     // If the plug-in host is the current application then we should bring ourselves to the front when it exits full-screen mode.
184     ProcessSerialNumber frontProcessSerialNumber;
185     GetFrontProcess(&frontProcessSerialNumber);
186
187     // The UI process must be the front process in order to change the presentation mode.
188     makeUIProcessTheFrontProcess();
189     [NSApp setPresentationOptions:m_preFullscreenAppPresentationOptions];
190
191     ProcessSerialNumber pluginProcessSerialNumber;
192     if (!getPluginProcessSerialNumber(pluginProcessSerialNumber))
193         return;
194
195     // If the plug-in process was not the front process, switch back to the previous front process.
196     // (Otherwise we'll keep the UI process as the front process).
197     Boolean isPluginProcessFrontProcess;
198     SameProcess(&frontProcessSerialNumber, &pluginProcessSerialNumber, &isPluginProcessFrontProcess);
199     if (!isPluginProcessFrontProcess)
200         SetFrontProcess(&frontProcessSerialNumber);
201 }
202
203 void PluginProcessProxy::setModalWindowIsShowing(bool modalWindowIsShowing)
204 {
205     if (modalWindowIsShowing == m_modalWindowIsShowing)
206         return;
207     
208     m_modalWindowIsShowing = modalWindowIsShowing;
209     
210     if (m_modalWindowIsShowing)
211         beginModal();
212     else
213         endModal();
214 }
215
216 void PluginProcessProxy::beginModal()
217 {
218     ASSERT(!m_placeholderWindow);
219     ASSERT(!m_activationObserver);
220     
221     m_placeholderWindow.adoptNS([[WKPlaceholderModalWindow alloc] initWithContentRect:NSMakeRect(0, 0, 1, 1) styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES]);
222     [m_placeholderWindow.get() setReleasedWhenClosed:NO];
223     
224     m_activationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationWillBecomeActiveNotification object:NSApp queue:nil
225                                                                          usingBlock:^(NSNotification *){ applicationDidBecomeActive(); }];
226
227     // The call to -[NSApp runModalForWindow:] below will run a nested run loop, and if the plug-in process
228     // crashes the PluginProcessProxy object can be destroyed. Protect against this here.
229     RefPtr<PluginProcessProxy> protect(this);
230
231     [NSApp runModalForWindow:m_placeholderWindow.get()];
232     
233     [m_placeholderWindow.get() orderOut:nil];
234     m_placeholderWindow = nullptr;
235 }
236
237 void PluginProcessProxy::endModal()
238 {
239     ASSERT(m_placeholderWindow);
240     ASSERT(m_activationObserver);
241     
242     [[NSNotificationCenter defaultCenter] removeObserver:m_activationObserver.get()];
243     m_activationObserver = nullptr;
244     
245     [NSApp stopModal];
246
247     makeUIProcessTheFrontProcess();
248 }
249     
250 void PluginProcessProxy::applicationDidBecomeActive()
251 {
252     makePluginProcessTheFrontProcess();
253 }
254
255
256 } // namespace WebKit
257
258 #endif // ENABLE(PLUGIN_PROCESS)