• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "PluginProcessShim.h"
27
28#import <AppKit/AppKit.h>
29#import <Carbon/Carbon.h>
30#import <WebKitSystemInterface.h>
31#import <stdio.h>
32#import <objc/objc-runtime.h>
33
34#define DYLD_INTERPOSE(_replacement,_replacee) \
35    __attribute__((used)) static struct{ const void* replacement; const void* replacee; } _interpose_##_replacee \
36    __attribute__ ((section ("__DATA,__interpose"))) = { (const void*)(unsigned long)&_replacement, (const void*)(unsigned long)&_replacee };
37
38namespace WebKit {
39
40extern "C" void WebKitPluginProcessShimInitialize(const PluginProcessShimCallbacks& callbacks);
41
42static PluginProcessShimCallbacks pluginProcessShimCallbacks;
43
44static IMP NSApplication_RunModalForWindow;
45static unsigned modalCount = 0;
46
47static void beginModal()
48{
49    // Make sure to make ourselves the front process
50    ProcessSerialNumber psn;
51    GetCurrentProcess(&psn);
52    SetFrontProcess(&psn);
53
54    if (!modalCount++)
55        pluginProcessShimCallbacks.setModal(true);
56}
57
58static void endModal()
59{
60    if (!--modalCount)
61        pluginProcessShimCallbacks.setModal(false);
62}
63
64static NSInteger shim_NSApplication_RunModalForWindow(id self, SEL _cmd, NSWindow* window)
65{
66    beginModal();
67    NSInteger result = ((NSInteger (*)(id, SEL, NSWindow *))NSApplication_RunModalForWindow)(self, _cmd, window);
68    endModal();
69
70    return result;
71}
72
73#ifndef __LP64__
74static void shimDebugger(void)
75{
76    if (!pluginProcessShimCallbacks.shouldCallRealDebugger())
77        return;
78
79    Debugger();
80}
81
82static UInt32 shimGetCurrentEventButtonState()
83{
84    return pluginProcessShimCallbacks.getCurrentEventButtonState();
85}
86
87static Boolean shimIsWindowActive(WindowRef window)
88{
89    bool result;
90    if (pluginProcessShimCallbacks.isWindowActive(window, result))
91        return result;
92
93    return IsWindowActive(window);
94}
95
96static void shimModalDialog(ModalFilterUPP modalFilter, DialogItemIndex *itemHit)
97{
98    beginModal();
99    ModalDialog(modalFilter, itemHit);
100    endModal();
101}
102
103static DialogItemIndex shimAlert(SInt16 alertID, ModalFilterUPP modalFilter)
104{
105    beginModal();
106    DialogItemIndex index = Alert(alertID, modalFilter);
107    endModal();
108
109    return index;
110}
111
112static void shimShowWindow(WindowRef window)
113{
114    pluginProcessShimCallbacks.carbonWindowShown(window);
115    ShowWindow(window);
116}
117
118static void shimHideWindow(WindowRef window)
119{
120    pluginProcessShimCallbacks.carbonWindowHidden(window);
121    HideWindow(window);
122}
123
124DYLD_INTERPOSE(shimDebugger, Debugger);
125DYLD_INTERPOSE(shimGetCurrentEventButtonState, GetCurrentEventButtonState);
126DYLD_INTERPOSE(shimIsWindowActive, IsWindowActive);
127DYLD_INTERPOSE(shimModalDialog, ModalDialog);
128DYLD_INTERPOSE(shimAlert, Alert);
129DYLD_INTERPOSE(shimShowWindow, ShowWindow);
130DYLD_INTERPOSE(shimHideWindow, HideWindow);
131
132#endif
133
134__attribute__((visibility("default")))
135void WebKitPluginProcessShimInitialize(const PluginProcessShimCallbacks& callbacks)
136{
137    pluginProcessShimCallbacks = callbacks;
138
139    // Override -[NSApplication runModalForWindow:]
140    Method runModalForWindowMethod = class_getInstanceMethod(objc_getClass("NSApplication"), @selector(runModalForWindow:));
141    NSApplication_RunModalForWindow = method_setImplementation(runModalForWindowMethod, reinterpret_cast<IMP>(shim_NSApplication_RunModalForWindow));
142
143    NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
144
145    // Track when any Cocoa window is about to be be shown.
146    id orderOnScreenObserver = [defaultCenter addObserverForName:WKWindowWillOrderOnScreenNotification()
147                                                          object:nil
148                                                           queue:nil
149                                                           usingBlock:^(NSNotification *notification) { pluginProcessShimCallbacks.cocoaWindowShown([notification object]); }];
150    // Track when any cocoa window is about to be hidden.
151    id orderOffScreenObserver = [defaultCenter addObserverForName:WKWindowWillOrderOffScreenNotification()
152                                                           object:nil
153                                                            queue:nil
154                                                       usingBlock:^(NSNotification *notification) { pluginProcessShimCallbacks.cocoaWindowHidden([notification object]); }];
155
156    // Leak the two observers so that they observe notifications for the lifetime of the process.
157    CFRetain(orderOnScreenObserver);
158    CFRetain(orderOffScreenObserver);
159}
160
161} // namespace WebKit
162