Home | History | Annotate | Download | only in mac
      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 "PluginProcess.h"
     28 
     29 #if ENABLE(PLUGIN_PROCESS)
     30 
     31 #import "NetscapePlugin.h"
     32 #import "PluginProcessShim.h"
     33 #import "PluginProcessProxyMessages.h"
     34 #import "PluginProcessCreationParameters.h"
     35 #import <WebCore/LocalizedStrings.h>
     36 #import <WebKitSystemInterface.h>
     37 #import <dlfcn.h>
     38 #import <wtf/HashSet.h>
     39 
     40 namespace WebKit {
     41 
     42 class FullscreenWindowTracker {
     43     WTF_MAKE_NONCOPYABLE(FullscreenWindowTracker);
     44 
     45 public:
     46     FullscreenWindowTracker() { }
     47 
     48     template<typename T> void windowShown(T window);
     49     template<typename T> void windowHidden(T window);
     50 
     51 private:
     52     typedef HashSet<void*> WindowSet;
     53     WindowSet m_windows;
     54 };
     55 
     56 static bool rectCoversAnyScreen(NSRect rect)
     57 {
     58     for (NSScreen *screen in [NSScreen screens]) {
     59         if (NSContainsRect(rect, [screen frame]))
     60             return YES;
     61     }
     62     return NO;
     63 }
     64 
     65 #ifndef NP_NO_CARBON
     66 static bool windowCoversAnyScreen(WindowRef window)
     67 {
     68     HIRect bounds;
     69     HIWindowGetBounds(window, kWindowStructureRgn, kHICoordSpaceScreenPixel, &bounds);
     70 
     71     // Convert to Cocoa-style screen coordinates that use a Y offset relative to the zeroth screen's origin.
     72     bounds.origin.y = NSHeight([[[NSScreen screens] objectAtIndex:0] frame]) - CGRectGetMaxY(bounds);
     73 
     74     return rectCoversAnyScreen(NSRectFromCGRect(bounds));
     75 }
     76 #endif
     77 
     78 static bool windowCoversAnyScreen(NSWindow* window)
     79 {
     80     return rectCoversAnyScreen([window frame]);
     81 }
     82 
     83 template<typename T> void FullscreenWindowTracker::windowShown(T window)
     84 {
     85     // If this window is already visible then there is nothing to do.
     86     WindowSet::iterator it = m_windows.find(window);
     87     if (it != m_windows.end())
     88         return;
     89 
     90     // If the window is not full-screen then we're not interested in it.
     91     if (!windowCoversAnyScreen(window))
     92         return;
     93 
     94     bool windowSetWasEmpty = m_windows.isEmpty();
     95 
     96     m_windows.add(window);
     97 
     98     // If this is the first full screen window to be shown, notify the UI process.
     99     if (windowSetWasEmpty)
    100         PluginProcess::shared().setFullscreenWindowIsShowing(true);
    101 }
    102 
    103 template<typename T> void FullscreenWindowTracker::windowHidden(T window)
    104 {
    105     // If this is not a window that we're tracking then there is nothing to do.
    106     WindowSet::iterator it = m_windows.find(window);
    107     if (it == m_windows.end())
    108         return;
    109 
    110     m_windows.remove(it);
    111 
    112     // If this was the last full screen window that was visible, notify the UI process.
    113     if (m_windows.isEmpty())
    114         PluginProcess::shared().setFullscreenWindowIsShowing(false);
    115 }
    116 
    117 static FullscreenWindowTracker& fullscreenWindowTracker()
    118 {
    119     DEFINE_STATIC_LOCAL(FullscreenWindowTracker, fullscreenWindowTracker, ());
    120     return fullscreenWindowTracker;
    121 }
    122 
    123 static bool isUserbreakSet = false;
    124 
    125 static void initShouldCallRealDebugger()
    126 {
    127     char* var = getenv("USERBREAK");
    128 
    129     if (var)
    130         isUserbreakSet = atoi(var);
    131 }
    132 
    133 static bool shouldCallRealDebugger()
    134 {
    135     static pthread_once_t shouldCallRealDebuggerOnce = PTHREAD_ONCE_INIT;
    136     pthread_once(&shouldCallRealDebuggerOnce, initShouldCallRealDebugger);
    137 
    138     return isUserbreakSet;
    139 }
    140 
    141 static bool isWindowActive(WindowRef windowRef, bool& result)
    142 {
    143 #ifndef NP_NO_CARBON
    144     if (NetscapePlugin* plugin = NetscapePlugin::netscapePluginFromWindow(windowRef)) {
    145         result = plugin->isWindowActive();
    146         return true;
    147     }
    148 #endif
    149     return false;
    150 }
    151 
    152 static UInt32 getCurrentEventButtonState()
    153 {
    154 #ifndef NP_NO_CARBON
    155     return NetscapePlugin::buttonState();
    156 #else
    157     ASSERT_NOT_REACHED();
    158     return 0;
    159 #endif
    160 }
    161 
    162 static void cocoaWindowShown(NSWindow *window)
    163 {
    164     fullscreenWindowTracker().windowShown(window);
    165 }
    166 
    167 static void cocoaWindowHidden(NSWindow *window)
    168 {
    169     fullscreenWindowTracker().windowHidden(window);
    170 }
    171 
    172 static void carbonWindowShown(WindowRef window)
    173 {
    174 #ifndef NP_NO_CARBON
    175     fullscreenWindowTracker().windowShown(window);
    176 #endif
    177 }
    178 
    179 static void carbonWindowHidden(WindowRef window)
    180 {
    181 #ifndef NP_NO_CARBON
    182     fullscreenWindowTracker().windowHidden(window);
    183 #endif
    184 }
    185 
    186 static void setModal(bool modalWindowIsShowing)
    187 {
    188     PluginProcess::shared().setModalWindowIsShowing(modalWindowIsShowing);
    189 }
    190 
    191 void PluginProcess::initializeShim()
    192 {
    193     const PluginProcessShimCallbacks callbacks = {
    194         shouldCallRealDebugger,
    195         isWindowActive,
    196         getCurrentEventButtonState,
    197         cocoaWindowShown,
    198         cocoaWindowHidden,
    199         carbonWindowShown,
    200         carbonWindowHidden,
    201         setModal,
    202     };
    203 
    204     PluginProcessShimInitializeFunc initFunc = reinterpret_cast<PluginProcessShimInitializeFunc>(dlsym(RTLD_DEFAULT, "WebKitPluginProcessShimInitialize"));
    205     initFunc(callbacks);
    206 }
    207 
    208 void PluginProcess::setModalWindowIsShowing(bool modalWindowIsShowing)
    209 {
    210     m_connection->send(Messages::PluginProcessProxy::SetModalWindowIsShowing(modalWindowIsShowing), 0);
    211 }
    212 
    213 void PluginProcess::setFullscreenWindowIsShowing(bool fullscreenWindowIsShowing)
    214 {
    215     m_connection->send(Messages::PluginProcessProxy::SetFullscreenWindowIsShowing(fullscreenWindowIsShowing), 0);
    216 }
    217 
    218 void PluginProcess::platformInitialize(const PluginProcessCreationParameters& parameters)
    219 {
    220     m_compositingRenderServerPort = parameters.acceleratedCompositingPort.port();
    221 
    222     NSString *applicationName = [NSString stringWithFormat:WEB_UI_STRING("%@ (%@ Internet plug-in)",
    223                                                                      "visible name of the plug-in host process. The first argument is the plug-in name "
    224                                                                      "and the second argument is the application name."),
    225                                  [[(NSString *)parameters.pluginPath lastPathComponent] stringByDeletingPathExtension],
    226                                  (NSString *)parameters.parentProcessName];
    227 
    228     WKSetVisibleApplicationName((CFStringRef)applicationName);
    229 }
    230 
    231 } // namespace WebKit
    232 
    233 #endif // ENABLE(PLUGIN_PROCESS)
    234