summaryrefslogtreecommitdiff
path: root/dom/plugins/ipc/PluginInterposeOSX.mm
diff options
context:
space:
mode:
Diffstat (limited to 'dom/plugins/ipc/PluginInterposeOSX.mm')
-rw-r--r--dom/plugins/ipc/PluginInterposeOSX.mm1158
1 files changed, 0 insertions, 1158 deletions
diff --git a/dom/plugins/ipc/PluginInterposeOSX.mm b/dom/plugins/ipc/PluginInterposeOSX.mm
deleted file mode 100644
index bf24d2b0d8..0000000000
--- a/dom/plugins/ipc/PluginInterposeOSX.mm
+++ /dev/null
@@ -1,1158 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-// vim:set ts=2 sts=2 sw=2 et cin:
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "base/basictypes.h"
-#include "nsCocoaUtils.h"
-#include "PluginModuleChild.h"
-#include "nsDebug.h"
-#include "PluginInterposeOSX.h"
-#include <set>
-#import <AppKit/AppKit.h>
-#import <objc/runtime.h>
-#import <Carbon/Carbon.h>
-
-using namespace mozilla::plugins;
-
-namespace mac_plugin_interposing {
-
-int32_t NSCursorInfo::mNativeCursorsSupported = -1;
-
-// This constructor may be called from the browser process or the plugin
-// process.
-NSCursorInfo::NSCursorInfo()
- : mType(TypeArrow)
- , mHotSpot(nsPoint(0, 0))
- , mCustomImageData(NULL)
- , mCustomImageDataLength(0)
-{
-}
-
-NSCursorInfo::NSCursorInfo(NSCursor* aCursor)
- : mType(TypeArrow)
- , mHotSpot(nsPoint(0, 0))
- , mCustomImageData(NULL)
- , mCustomImageDataLength(0)
-{
- // This constructor is only ever called from the plugin process, so the
- // following is safe.
- if (!GetNativeCursorsSupported()) {
- return;
- }
-
- NSPoint hotSpotCocoa = [aCursor hotSpot];
- mHotSpot = nsPoint(hotSpotCocoa.x, hotSpotCocoa.y);
-
- Class nsCursorClass = [NSCursor class];
- if ([aCursor isEqual:[NSCursor arrowCursor]]) {
- mType = TypeArrow;
- } else if ([aCursor isEqual:[NSCursor closedHandCursor]]) {
- mType = TypeClosedHand;
- } else if ([aCursor isEqual:[NSCursor crosshairCursor]]) {
- mType = TypeCrosshair;
- } else if ([aCursor isEqual:[NSCursor disappearingItemCursor]]) {
- mType = TypeDisappearingItem;
- } else if ([aCursor isEqual:[NSCursor IBeamCursor]]) {
- mType = TypeIBeam;
- } else if ([aCursor isEqual:[NSCursor openHandCursor]]) {
- mType = TypeOpenHand;
- } else if ([aCursor isEqual:[NSCursor pointingHandCursor]]) {
- mType = TypePointingHand;
- } else if ([aCursor isEqual:[NSCursor resizeDownCursor]]) {
- mType = TypeResizeDown;
- } else if ([aCursor isEqual:[NSCursor resizeLeftCursor]]) {
- mType = TypeResizeLeft;
- } else if ([aCursor isEqual:[NSCursor resizeLeftRightCursor]]) {
- mType = TypeResizeLeftRight;
- } else if ([aCursor isEqual:[NSCursor resizeRightCursor]]) {
- mType = TypeResizeRight;
- } else if ([aCursor isEqual:[NSCursor resizeUpCursor]]) {
- mType = TypeResizeUp;
- } else if ([aCursor isEqual:[NSCursor resizeUpDownCursor]]) {
- mType = TypeResizeUpDown;
- // The following cursor types are only supported on OS X 10.6 and up.
- } else if ([nsCursorClass respondsToSelector:@selector(contextualMenuCursor)] &&
- [aCursor isEqual:[nsCursorClass performSelector:@selector(contextualMenuCursor)]]) {
- mType = TypeContextualMenu;
- } else if ([nsCursorClass respondsToSelector:@selector(dragCopyCursor)] &&
- [aCursor isEqual:[nsCursorClass performSelector:@selector(dragCopyCursor)]]) {
- mType = TypeDragCopy;
- } else if ([nsCursorClass respondsToSelector:@selector(dragLinkCursor)] &&
- [aCursor isEqual:[nsCursorClass performSelector:@selector(dragLinkCursor)]]) {
- mType = TypeDragLink;
- } else if ([nsCursorClass respondsToSelector:@selector(operationNotAllowedCursor)] &&
- [aCursor isEqual:[nsCursorClass performSelector:@selector(operationNotAllowedCursor)]]) {
- mType = TypeNotAllowed;
- } else {
- NSImage* image = [aCursor image];
- NSArray* reps = image ? [image representations] : nil;
- NSUInteger repsCount = reps ? [reps count] : 0;
- if (!repsCount) {
- // If we have a custom cursor with no image representations, assume we
- // need a transparent cursor.
- mType = TypeTransparent;
- } else {
- CGImageRef cgImage = nil;
- // XXX We don't know how to deal with a cursor that doesn't have a
- // bitmap image representation. For now we fall back to an arrow
- // cursor.
- for (NSUInteger i = 0; i < repsCount; ++i) {
- id rep = [reps objectAtIndex:i];
- if ([rep isKindOfClass:[NSBitmapImageRep class]]) {
- cgImage = [(NSBitmapImageRep*)rep CGImage];
- break;
- }
- }
- if (cgImage) {
- CFMutableDataRef data = ::CFDataCreateMutable(kCFAllocatorDefault, 0);
- if (data) {
- CGImageDestinationRef dest = ::CGImageDestinationCreateWithData(data,
- kUTTypePNG,
- 1,
- NULL);
- if (dest) {
- ::CGImageDestinationAddImage(dest, cgImage, NULL);
- if (::CGImageDestinationFinalize(dest)) {
- uint32_t dataLength = (uint32_t) ::CFDataGetLength(data);
- mCustomImageData = (uint8_t*) moz_xmalloc(dataLength);
- ::CFDataGetBytes(data, ::CFRangeMake(0, dataLength), mCustomImageData);
- mCustomImageDataLength = dataLength;
- mType = TypeCustom;
- }
- ::CFRelease(dest);
- }
- ::CFRelease(data);
- }
- }
- if (!mCustomImageData) {
- mType = TypeArrow;
- }
- }
- }
-}
-
-NSCursorInfo::NSCursorInfo(const Cursor* aCursor)
- : mType(TypeArrow)
- , mHotSpot(nsPoint(0, 0))
- , mCustomImageData(NULL)
- , mCustomImageDataLength(0)
-{
- // This constructor is only ever called from the plugin process, so the
- // following is safe.
- if (!GetNativeCursorsSupported()) {
- return;
- }
-
- mHotSpot = nsPoint(aCursor->hotSpot.h, aCursor->hotSpot.v);
-
- int width = 16, height = 16;
- int bytesPerPixel = 4;
- int rowBytes = width * bytesPerPixel;
- int bitmapSize = height * rowBytes;
-
- bool isTransparent = true;
-
- uint8_t* bitmap = (uint8_t*) moz_xmalloc(bitmapSize);
- // The way we create 'bitmap' is largely "borrowed" from Chrome's
- // WebCursor::InitFromCursor().
- for (int y = 0; y < height; ++y) {
- unsigned short data = aCursor->data[y];
- unsigned short mask = aCursor->mask[y];
- // Change 'data' and 'mask' from big-endian to little-endian, but output
- // big-endian data below.
- data = ((data << 8) & 0xFF00) | ((data >> 8) & 0x00FF);
- mask = ((mask << 8) & 0xFF00) | ((mask >> 8) & 0x00FF);
- // It'd be nice to use a gray-scale bitmap. But
- // CGBitmapContextCreateImage() (used below) won't work with one that also
- // has alpha values.
- for (int x = 0; x < width; ++x) {
- int offset = (y * rowBytes) + (x * bytesPerPixel);
- // Color value
- if (data & 0x8000) {
- bitmap[offset] = 0x0;
- bitmap[offset + 1] = 0x0;
- bitmap[offset + 2] = 0x0;
- } else {
- bitmap[offset] = 0xFF;
- bitmap[offset + 1] = 0xFF;
- bitmap[offset + 2] = 0xFF;
- }
- // Mask value
- if (mask & 0x8000) {
- bitmap[offset + 3] = 0xFF;
- isTransparent = false;
- } else {
- bitmap[offset + 3] = 0x0;
- }
- data <<= 1;
- mask <<= 1;
- }
- }
-
- if (isTransparent) {
- // If aCursor is transparent, we don't need to serialize custom cursor
- // data over IPC.
- mType = TypeTransparent;
- } else {
- CGColorSpaceRef color = ::CGColorSpaceCreateDeviceRGB();
- if (color) {
- CGContextRef context =
- ::CGBitmapContextCreate(bitmap,
- width,
- height,
- 8,
- rowBytes,
- color,
- kCGImageAlphaPremultipliedLast |
- kCGBitmapByteOrder32Big);
- if (context) {
- CGImageRef image = ::CGBitmapContextCreateImage(context);
- if (image) {
- ::CFMutableDataRef data = ::CFDataCreateMutable(kCFAllocatorDefault, 0);
- if (data) {
- CGImageDestinationRef dest =
- ::CGImageDestinationCreateWithData(data,
- kUTTypePNG,
- 1,
- NULL);
- if (dest) {
- ::CGImageDestinationAddImage(dest, image, NULL);
- if (::CGImageDestinationFinalize(dest)) {
- uint32_t dataLength = (uint32_t) ::CFDataGetLength(data);
- mCustomImageData = (uint8_t*) moz_xmalloc(dataLength);
- ::CFDataGetBytes(data,
- ::CFRangeMake(0, dataLength),
- mCustomImageData);
- mCustomImageDataLength = dataLength;
- mType = TypeCustom;
- }
- ::CFRelease(dest);
- }
- ::CFRelease(data);
- }
- ::CGImageRelease(image);
- }
- ::CGContextRelease(context);
- }
- ::CGColorSpaceRelease(color);
- }
- }
-
- free(bitmap);
-}
-
-NSCursorInfo::~NSCursorInfo()
-{
- if (mCustomImageData) {
- free(mCustomImageData);
- }
-}
-
-NSCursor* NSCursorInfo::GetNSCursor() const
-{
- NSCursor* retval = nil;
-
- Class nsCursorClass = [NSCursor class];
- switch(mType) {
- case TypeArrow:
- retval = [NSCursor arrowCursor];
- break;
- case TypeClosedHand:
- retval = [NSCursor closedHandCursor];
- break;
- case TypeCrosshair:
- retval = [NSCursor crosshairCursor];
- break;
- case TypeDisappearingItem:
- retval = [NSCursor disappearingItemCursor];
- break;
- case TypeIBeam:
- retval = [NSCursor IBeamCursor];
- break;
- case TypeOpenHand:
- retval = [NSCursor openHandCursor];
- break;
- case TypePointingHand:
- retval = [NSCursor pointingHandCursor];
- break;
- case TypeResizeDown:
- retval = [NSCursor resizeDownCursor];
- break;
- case TypeResizeLeft:
- retval = [NSCursor resizeLeftCursor];
- break;
- case TypeResizeLeftRight:
- retval = [NSCursor resizeLeftRightCursor];
- break;
- case TypeResizeRight:
- retval = [NSCursor resizeRightCursor];
- break;
- case TypeResizeUp:
- retval = [NSCursor resizeUpCursor];
- break;
- case TypeResizeUpDown:
- retval = [NSCursor resizeUpDownCursor];
- break;
- // The following four cursor types are only supported on OS X 10.6 and up.
- case TypeContextualMenu: {
- if ([nsCursorClass respondsToSelector:@selector(contextualMenuCursor)]) {
- retval = [nsCursorClass performSelector:@selector(contextualMenuCursor)];
- }
- break;
- }
- case TypeDragCopy: {
- if ([nsCursorClass respondsToSelector:@selector(dragCopyCursor)]) {
- retval = [nsCursorClass performSelector:@selector(dragCopyCursor)];
- }
- break;
- }
- case TypeDragLink: {
- if ([nsCursorClass respondsToSelector:@selector(dragLinkCursor)]) {
- retval = [nsCursorClass performSelector:@selector(dragLinkCursor)];
- }
- break;
- }
- case TypeNotAllowed: {
- if ([nsCursorClass respondsToSelector:@selector(operationNotAllowedCursor)]) {
- retval = [nsCursorClass performSelector:@selector(operationNotAllowedCursor)];
- }
- break;
- }
- case TypeTransparent:
- retval = GetTransparentCursor();
- break;
- default:
- break;
- }
-
- if (!retval && mCustomImageData && mCustomImageDataLength) {
- CGDataProviderRef provider = ::CGDataProviderCreateWithData(NULL,
- (const void*)mCustomImageData,
- mCustomImageDataLength,
- NULL);
- if (provider) {
- CGImageRef cgImage = ::CGImageCreateWithPNGDataProvider(provider,
- NULL,
- false,
- kCGRenderingIntentDefault);
- if (cgImage) {
- NSBitmapImageRep* rep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage];
- if (rep) {
- NSImage* image = [[NSImage alloc] init];
- if (image) {
- [image addRepresentation:rep];
- retval = [[[NSCursor alloc] initWithImage:image
- hotSpot:NSMakePoint(mHotSpot.x, mHotSpot.y)]
- autorelease];
- [image release];
- }
- [rep release];
- }
- ::CGImageRelease(cgImage);
- }
- ::CFRelease(provider);
- }
- }
-
- // Fall back to an arrow cursor if need be.
- if (!retval) {
- retval = [NSCursor arrowCursor];
- }
-
- return retval;
-}
-
-// Get a transparent cursor with the appropriate hot spot. We need one if
-// (for example) we have a custom cursor with no image data.
-NSCursor* NSCursorInfo::GetTransparentCursor() const
-{
- NSCursor* retval = nil;
-
- int width = 16, height = 16;
- int bytesPerPixel = 2;
- int rowBytes = width * bytesPerPixel;
- int dataSize = height * rowBytes;
-
- uint8_t* data = (uint8_t*) moz_xmalloc(dataSize);
- for (int y = 0; y < height; ++y) {
- for (int x = 0; x < width; ++x) {
- int offset = (y * rowBytes) + (x * bytesPerPixel);
- data[offset] = 0x7E; // Arbitrary gray-scale value
- data[offset + 1] = 0; // Alpha value to make us transparent
- }
- }
-
- NSBitmapImageRep* imageRep =
- [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
- pixelsWide:width
- pixelsHigh:height
- bitsPerSample:8
- samplesPerPixel:2
- hasAlpha:YES
- isPlanar:NO
- colorSpaceName:NSCalibratedWhiteColorSpace
- bytesPerRow:rowBytes
- bitsPerPixel:16]
- autorelease];
- if (imageRep) {
- uint8_t* repDataPtr = [imageRep bitmapData];
- if (repDataPtr) {
- memcpy(repDataPtr, data, dataSize);
- NSImage *image =
- [[[NSImage alloc] initWithSize:NSMakeSize(width, height)]
- autorelease];
- if (image) {
- [image addRepresentation:imageRep];
- retval =
- [[[NSCursor alloc] initWithImage:image
- hotSpot:NSMakePoint(mHotSpot.x, mHotSpot.y)]
- autorelease];
- }
- }
- }
-
- free(data);
-
- // Fall back to an arrow cursor if (for some reason) the above code failed.
- if (!retval) {
- retval = [NSCursor arrowCursor];
- }
-
- return retval;
-}
-
-NSCursorInfo::Type NSCursorInfo::GetType() const
-{
- return mType;
-}
-
-const char* NSCursorInfo::GetTypeName() const
-{
- switch(mType) {
- case TypeCustom:
- return "TypeCustom";
- case TypeArrow:
- return "TypeArrow";
- case TypeClosedHand:
- return "TypeClosedHand";
- case TypeContextualMenu:
- return "TypeContextualMenu";
- case TypeCrosshair:
- return "TypeCrosshair";
- case TypeDisappearingItem:
- return "TypeDisappearingItem";
- case TypeDragCopy:
- return "TypeDragCopy";
- case TypeDragLink:
- return "TypeDragLink";
- case TypeIBeam:
- return "TypeIBeam";
- case TypeNotAllowed:
- return "TypeNotAllowed";
- case TypeOpenHand:
- return "TypeOpenHand";
- case TypePointingHand:
- return "TypePointingHand";
- case TypeResizeDown:
- return "TypeResizeDown";
- case TypeResizeLeft:
- return "TypeResizeLeft";
- case TypeResizeLeftRight:
- return "TypeResizeLeftRight";
- case TypeResizeRight:
- return "TypeResizeRight";
- case TypeResizeUp:
- return "TypeResizeUp";
- case TypeResizeUpDown:
- return "TypeResizeUpDown";
- case TypeTransparent:
- return "TypeTransparent";
- default:
- break;
- }
- return "TypeUnknown";
-}
-
-nsPoint NSCursorInfo::GetHotSpot() const
-{
- return mHotSpot;
-}
-
-uint8_t* NSCursorInfo::GetCustomImageData() const
-{
- return mCustomImageData;
-}
-
-uint32_t NSCursorInfo::GetCustomImageDataLength() const
-{
- return mCustomImageDataLength;
-}
-
-void NSCursorInfo::SetType(Type aType)
-{
- mType = aType;
-}
-
-void NSCursorInfo::SetHotSpot(nsPoint aHotSpot)
-{
- mHotSpot = aHotSpot;
-}
-
-void NSCursorInfo::SetCustomImageData(uint8_t* aData, uint32_t aDataLength)
-{
- if (mCustomImageData) {
- free(mCustomImageData);
- }
- if (aDataLength) {
- mCustomImageData = (uint8_t*) moz_xmalloc(aDataLength);
- memcpy(mCustomImageData, aData, aDataLength);
- } else {
- mCustomImageData = NULL;
- }
- mCustomImageDataLength = aDataLength;
-}
-
-// This should never be called from the browser process -- only from the
-// plugin process.
-bool NSCursorInfo::GetNativeCursorsSupported()
-{
- if (mNativeCursorsSupported == -1) {
- ENSURE_PLUGIN_THREAD(false);
- PluginModuleChild *pmc = PluginModuleChild::GetChrome();
- if (pmc) {
- bool result = pmc->GetNativeCursorsSupported();
- if (result) {
- mNativeCursorsSupported = 1;
- } else {
- mNativeCursorsSupported = 0;
- }
- }
- }
- return (mNativeCursorsSupported == 1);
-}
-
-} // namespace mac_plugin_interposing
-
-namespace mac_plugin_interposing {
-namespace parent {
-
-// Tracks plugin windows currently visible.
-std::set<uint32_t> plugin_visible_windows_set_;
-// Tracks full screen windows currently visible.
-std::set<uint32_t> plugin_fullscreen_windows_set_;
-// Tracks modal windows currently visible.
-std::set<uint32_t> plugin_modal_windows_set_;
-
-void OnPluginShowWindow(uint32_t window_id,
- CGRect window_bounds,
- bool modal) {
- plugin_visible_windows_set_.insert(window_id);
-
- if (modal)
- plugin_modal_windows_set_.insert(window_id);
-
- CGRect main_display_bounds = ::CGDisplayBounds(CGMainDisplayID());
-
- if (CGRectEqualToRect(window_bounds, main_display_bounds) &&
- (plugin_fullscreen_windows_set_.find(window_id) ==
- plugin_fullscreen_windows_set_.end())) {
- plugin_fullscreen_windows_set_.insert(window_id);
-
- nsCocoaUtils::HideOSChromeOnScreen(true);
- }
-}
-
-static void ActivateProcess(pid_t pid) {
- ProcessSerialNumber process;
- OSStatus status = ::GetProcessForPID(pid, &process);
-
- if (status == noErr) {
- SetFrontProcess(&process);
- } else {
- NS_WARNING("Unable to get process for pid.");
- }
-}
-
-// Must be called on the UI thread.
-// If plugin_pid is -1, the browser will be the active process on return,
-// otherwise that process will be given focus back before this function returns.
-static void ReleasePluginFullScreen(pid_t plugin_pid) {
- // Releasing full screen only works if we are the frontmost process; grab
- // focus, but give it back to the plugin process if requested.
- ActivateProcess(base::GetCurrentProcId());
-
- nsCocoaUtils::HideOSChromeOnScreen(false);
-
- if (plugin_pid != -1) {
- ActivateProcess(plugin_pid);
- }
-}
-
-void OnPluginHideWindow(uint32_t window_id, pid_t aPluginPid) {
- bool had_windows = !plugin_visible_windows_set_.empty();
- plugin_visible_windows_set_.erase(window_id);
- bool browser_needs_activation = had_windows &&
- plugin_visible_windows_set_.empty();
-
- plugin_modal_windows_set_.erase(window_id);
- if (plugin_fullscreen_windows_set_.find(window_id) !=
- plugin_fullscreen_windows_set_.end()) {
- plugin_fullscreen_windows_set_.erase(window_id);
- pid_t plugin_pid = browser_needs_activation ? -1 : aPluginPid;
- browser_needs_activation = false;
- ReleasePluginFullScreen(plugin_pid);
- }
-
- if (browser_needs_activation) {
- ActivateProcess(getpid());
- }
-}
-
-void OnSetCursor(const NSCursorInfo& cursorInfo)
-{
- NSCursor* aCursor = cursorInfo.GetNSCursor();
- if (aCursor) {
- [aCursor set];
- }
-}
-
-void OnShowCursor(bool show)
-{
- if (show) {
- [NSCursor unhide];
- } else {
- [NSCursor hide];
- }
-}
-
-void OnPushCursor(const NSCursorInfo& cursorInfo)
-{
- NSCursor* aCursor = cursorInfo.GetNSCursor();
- if (aCursor) {
- [aCursor push];
- }
-}
-
-void OnPopCursor()
-{
- [NSCursor pop];
-}
-
-} // namespace parent
-} // namespace mac_plugin_interposing
-
-namespace mac_plugin_interposing {
-namespace child {
-
-// TODO(stuartmorgan): Make this an IPC to order the plugin process above the
-// browser process only if the browser is current frontmost.
-void FocusPluginProcess() {
- ProcessSerialNumber this_process, front_process;
- if ((GetCurrentProcess(&this_process) != noErr) ||
- (GetFrontProcess(&front_process) != noErr)) {
- return;
- }
-
- Boolean matched = false;
- if ((SameProcess(&this_process, &front_process, &matched) == noErr) &&
- !matched) {
- SetFrontProcess(&this_process);
- }
-}
-
-void NotifyBrowserOfPluginShowWindow(uint32_t window_id, CGRect bounds,
- bool modal) {
- ENSURE_PLUGIN_THREAD_VOID();
-
- PluginModuleChild *pmc = PluginModuleChild::GetChrome();
- if (pmc)
- pmc->PluginShowWindow(window_id, modal, bounds);
-}
-
-void NotifyBrowserOfPluginHideWindow(uint32_t window_id, CGRect bounds) {
- ENSURE_PLUGIN_THREAD_VOID();
-
- PluginModuleChild *pmc = PluginModuleChild::GetChrome();
- if (pmc)
- pmc->PluginHideWindow(window_id);
-}
-
-void NotifyBrowserOfSetCursor(NSCursorInfo& aCursorInfo)
-{
- ENSURE_PLUGIN_THREAD_VOID();
- PluginModuleChild *pmc = PluginModuleChild::GetChrome();
- if (pmc) {
- pmc->SetCursor(aCursorInfo);
- }
-}
-
-void NotifyBrowserOfShowCursor(bool show)
-{
- ENSURE_PLUGIN_THREAD_VOID();
- PluginModuleChild *pmc = PluginModuleChild::GetChrome();
- if (pmc) {
- pmc->ShowCursor(show);
- }
-}
-
-void NotifyBrowserOfPushCursor(NSCursorInfo& aCursorInfo)
-{
- ENSURE_PLUGIN_THREAD_VOID();
- PluginModuleChild *pmc = PluginModuleChild::GetChrome();
- if (pmc) {
- pmc->PushCursor(aCursorInfo);
- }
-}
-
-void NotifyBrowserOfPopCursor()
-{
- ENSURE_PLUGIN_THREAD_VOID();
- PluginModuleChild *pmc = PluginModuleChild::GetChrome();
- if (pmc) {
- pmc->PopCursor();
- }
-}
-
-struct WindowInfo {
- uint32_t window_id;
- CGRect bounds;
- explicit WindowInfo(NSWindow* aWindow) {
- NSInteger window_num = [aWindow windowNumber];
- window_id = window_num > 0 ? window_num : 0;
- bounds = NSRectToCGRect([aWindow frame]);
- }
-};
-
-static void OnPluginWindowClosed(const WindowInfo& window_info) {
- if (window_info.window_id == 0)
- return;
- mac_plugin_interposing::child::NotifyBrowserOfPluginHideWindow(window_info.window_id,
- window_info.bounds);
-}
-
-static void OnPluginWindowShown(const WindowInfo& window_info, BOOL is_modal) {
- // The window id is 0 if it has never been shown (including while it is the
- // process of being shown for the first time); when that happens, we'll catch
- // it in _setWindowNumber instead.
- static BOOL s_pending_display_is_modal = NO;
- if (window_info.window_id == 0) {
- if (is_modal)
- s_pending_display_is_modal = YES;
- return;
- }
- if (s_pending_display_is_modal) {
- is_modal = YES;
- s_pending_display_is_modal = NO;
- }
- mac_plugin_interposing::child::NotifyBrowserOfPluginShowWindow(
- window_info.window_id, window_info.bounds, is_modal);
-}
-
-static BOOL OnSetCursor(NSCursorInfo &aInfo)
-{
- if (NSCursorInfo::GetNativeCursorsSupported()) {
- NotifyBrowserOfSetCursor(aInfo);
- return YES;
- }
- return NO;
-}
-
-static BOOL OnHideCursor()
-{
- if (NSCursorInfo::GetNativeCursorsSupported()) {
- NotifyBrowserOfShowCursor(NO);
- return YES;
- }
- return NO;
-}
-
-static BOOL OnUnhideCursor()
-{
- if (NSCursorInfo::GetNativeCursorsSupported()) {
- NotifyBrowserOfShowCursor(YES);
- return YES;
- }
- return NO;
-}
-
-static BOOL OnPushCursor(NSCursorInfo &aInfo)
-{
- if (NSCursorInfo::GetNativeCursorsSupported()) {
- NotifyBrowserOfPushCursor(aInfo);
- return YES;
- }
- return NO;
-}
-
-static BOOL OnPopCursor()
-{
- if (NSCursorInfo::GetNativeCursorsSupported()) {
- NotifyBrowserOfPopCursor();
- return YES;
- }
- return NO;
-}
-
-} // namespace child
-} // namespace mac_plugin_interposing
-
-using namespace mac_plugin_interposing::child;
-
-@interface NSWindow (PluginInterposing)
-- (void)pluginInterpose_orderOut:(id)sender;
-- (void)pluginInterpose_orderFront:(id)sender;
-- (void)pluginInterpose_makeKeyAndOrderFront:(id)sender;
-- (void)pluginInterpose_setWindowNumber:(NSInteger)num;
-@end
-
-@implementation NSWindow (PluginInterposing)
-
-- (void)pluginInterpose_orderOut:(id)sender {
- WindowInfo window_info(self);
- [self pluginInterpose_orderOut:sender];
- OnPluginWindowClosed(window_info);
-}
-
-- (void)pluginInterpose_orderFront:(id)sender {
- mac_plugin_interposing::child::FocusPluginProcess();
- [self pluginInterpose_orderFront:sender];
- OnPluginWindowShown(WindowInfo(self), NO);
-}
-
-- (void)pluginInterpose_makeKeyAndOrderFront:(id)sender {
- mac_plugin_interposing::child::FocusPluginProcess();
- [self pluginInterpose_makeKeyAndOrderFront:sender];
- OnPluginWindowShown(WindowInfo(self), NO);
-}
-
-- (void)pluginInterpose_setWindowNumber:(NSInteger)num {
- if (num > 0)
- mac_plugin_interposing::child::FocusPluginProcess();
- [self pluginInterpose_setWindowNumber:num];
- if (num > 0)
- OnPluginWindowShown(WindowInfo(self), NO);
-}
-
-@end
-
-@interface NSApplication (PluginInterposing)
-- (NSInteger)pluginInterpose_runModalForWindow:(NSWindow*)window;
-@end
-
-@implementation NSApplication (PluginInterposing)
-
-- (NSInteger)pluginInterpose_runModalForWindow:(NSWindow*)window {
- mac_plugin_interposing::child::FocusPluginProcess();
- // This is out-of-order relative to the other calls, but runModalForWindow:
- // won't return until the window closes, and the order only matters for
- // full-screen windows.
- OnPluginWindowShown(WindowInfo(window), YES);
- return [self pluginInterpose_runModalForWindow:window];
-}
-
-@end
-
-// Hook commands to manipulate the current cursor, so that they can be passed
-// from the child process to the parent process. These commands have no
-// effect unless they're performed in the parent process.
-@interface NSCursor (PluginInterposing)
-- (void)pluginInterpose_set;
-- (void)pluginInterpose_push;
-- (void)pluginInterpose_pop;
-+ (NSCursor*)pluginInterpose_currentCursor;
-+ (void)pluginInterpose_hide;
-+ (void)pluginInterpose_unhide;
-+ (void)pluginInterpose_pop;
-@end
-
-// Cache the results of [NSCursor set], [NSCursor push] and [NSCursor pop].
-// The last element is always the current cursor.
-static NSMutableArray* gCursorStack = nil;
-
-static BOOL initCursorStack()
-{
- if (!gCursorStack) {
- gCursorStack = [[NSMutableArray arrayWithCapacity:5] retain];
- }
- return (gCursorStack != NULL);
-}
-
-static NSCursor* currentCursorFromCache()
-{
- if (!initCursorStack())
- return nil;
- return (NSCursor*) [gCursorStack lastObject];
-}
-
-static void setCursorInCache(NSCursor* aCursor)
-{
- if (!initCursorStack() || !aCursor)
- return;
- NSUInteger count = [gCursorStack count];
- if (count) {
- [gCursorStack replaceObjectAtIndex:count - 1 withObject:aCursor];
- } else {
- [gCursorStack addObject:aCursor];
- }
-}
-
-static void pushCursorInCache(NSCursor* aCursor)
-{
- if (!initCursorStack() || !aCursor)
- return;
- [gCursorStack addObject:aCursor];
-}
-
-static void popCursorInCache()
-{
- if (!initCursorStack())
- return;
- // Apple's doc on the +[NSCursor pop] method says: "If the current cursor
- // is the only cursor on the stack, this method does nothing."
- if ([gCursorStack count] > 1) {
- [gCursorStack removeLastObject];
- }
-}
-
-@implementation NSCursor (PluginInterposing)
-
-- (void)pluginInterpose_set
-{
- NSCursorInfo info(self);
- OnSetCursor(info);
- setCursorInCache(self);
- [self pluginInterpose_set];
-}
-
-- (void)pluginInterpose_push
-{
- NSCursorInfo info(self);
- OnPushCursor(info);
- pushCursorInCache(self);
- [self pluginInterpose_push];
-}
-
-- (void)pluginInterpose_pop
-{
- OnPopCursor();
- popCursorInCache();
- [self pluginInterpose_pop];
-}
-
-// The currentCursor method always returns nil when running in a background
-// process. But this may confuse plugins (notably Flash, see bug 621117). So
-// if we get a nil return from the "call to super", we return a cursor that's
-// been cached by previous calls to set or push. According to Apple's docs,
-// currentCursor "only returns the cursor set by your application using
-// NSCursor methods". So we don't need to worry about changes to the cursor
-// made by other methods like SetThemeCursor().
-+ (NSCursor*)pluginInterpose_currentCursor
-{
- NSCursor* retval = [self pluginInterpose_currentCursor];
- if (!retval) {
- retval = currentCursorFromCache();
- }
- return retval;
-}
-
-+ (void)pluginInterpose_hide
-{
- OnHideCursor();
- [self pluginInterpose_hide];
-}
-
-+ (void)pluginInterpose_unhide
-{
- OnUnhideCursor();
- [self pluginInterpose_unhide];
-}
-
-+ (void)pluginInterpose_pop
-{
- OnPopCursor();
- popCursorInCache();
- [self pluginInterpose_pop];
-}
-
-@end
-
-static void ExchangeMethods(Class target_class,
- BOOL class_method,
- SEL original,
- SEL replacement) {
- Method m1;
- Method m2;
- if (class_method) {
- m1 = class_getClassMethod(target_class, original);
- m2 = class_getClassMethod(target_class, replacement);
- } else {
- m1 = class_getInstanceMethod(target_class, original);
- m2 = class_getInstanceMethod(target_class, replacement);
- }
-
- if (m1 == m2)
- return;
-
- if (m1 && m2)
- method_exchangeImplementations(m1, m2);
- else
- NS_NOTREACHED("Cocoa swizzling failed");
-}
-
-namespace mac_plugin_interposing {
-namespace child {
-
-void SetUpCocoaInterposing() {
- Class nswindow_class = [NSWindow class];
- ExchangeMethods(nswindow_class, NO, @selector(orderOut:),
- @selector(pluginInterpose_orderOut:));
- ExchangeMethods(nswindow_class, NO, @selector(orderFront:),
- @selector(pluginInterpose_orderFront:));
- ExchangeMethods(nswindow_class, NO, @selector(makeKeyAndOrderFront:),
- @selector(pluginInterpose_makeKeyAndOrderFront:));
- ExchangeMethods(nswindow_class, NO, @selector(_setWindowNumber:),
- @selector(pluginInterpose_setWindowNumber:));
-
- ExchangeMethods([NSApplication class], NO, @selector(runModalForWindow:),
- @selector(pluginInterpose_runModalForWindow:));
-
- Class nscursor_class = [NSCursor class];
- ExchangeMethods(nscursor_class, NO, @selector(set),
- @selector(pluginInterpose_set));
- ExchangeMethods(nscursor_class, NO, @selector(push),
- @selector(pluginInterpose_push));
- ExchangeMethods(nscursor_class, NO, @selector(pop),
- @selector(pluginInterpose_pop));
- ExchangeMethods(nscursor_class, YES, @selector(currentCursor),
- @selector(pluginInterpose_currentCursor));
- ExchangeMethods(nscursor_class, YES, @selector(hide),
- @selector(pluginInterpose_hide));
- ExchangeMethods(nscursor_class, YES, @selector(unhide),
- @selector(pluginInterpose_unhide));
- ExchangeMethods(nscursor_class, YES, @selector(pop),
- @selector(pluginInterpose_pop));
-}
-
-} // namespace child
-} // namespace mac_plugin_interposing
-
-// Called from plugin_child_interpose.mm, which hooks calls to
-// SetCursor() (the QuickDraw call) from the plugin child process.
-extern "C" NS_VISIBILITY_DEFAULT BOOL
-mac_plugin_interposing_child_OnSetCursor(const Cursor* cursor)
-{
- NSCursorInfo info(cursor);
- return OnSetCursor(info);
-}
-
-// Called from plugin_child_interpose.mm, which hooks calls to
-// SetThemeCursor() (the Appearance Manager call) from the plugin child
-// process.
-extern "C" NS_VISIBILITY_DEFAULT BOOL
-mac_plugin_interposing_child_OnSetThemeCursor(ThemeCursor cursor)
-{
- NSCursorInfo info;
- switch (cursor) {
- case kThemeArrowCursor:
- info.SetType(NSCursorInfo::TypeArrow);
- break;
- case kThemeCopyArrowCursor:
- info.SetType(NSCursorInfo::TypeDragCopy);
- break;
- case kThemeAliasArrowCursor:
- info.SetType(NSCursorInfo::TypeDragLink);
- break;
- case kThemeContextualMenuArrowCursor:
- info.SetType(NSCursorInfo::TypeContextualMenu);
- break;
- case kThemeIBeamCursor:
- info.SetType(NSCursorInfo::TypeIBeam);
- break;
- case kThemeCrossCursor:
- case kThemePlusCursor:
- info.SetType(NSCursorInfo::TypeCrosshair);
- break;
- case kThemeWatchCursor:
- case kThemeSpinningCursor:
- info.SetType(NSCursorInfo::TypeArrow);
- break;
- case kThemeClosedHandCursor:
- info.SetType(NSCursorInfo::TypeClosedHand);
- break;
- case kThemeOpenHandCursor:
- info.SetType(NSCursorInfo::TypeOpenHand);
- break;
- case kThemePointingHandCursor:
- case kThemeCountingUpHandCursor:
- case kThemeCountingDownHandCursor:
- case kThemeCountingUpAndDownHandCursor:
- info.SetType(NSCursorInfo::TypePointingHand);
- break;
- case kThemeResizeLeftCursor:
- info.SetType(NSCursorInfo::TypeResizeLeft);
- break;
- case kThemeResizeRightCursor:
- info.SetType(NSCursorInfo::TypeResizeRight);
- break;
- case kThemeResizeLeftRightCursor:
- info.SetType(NSCursorInfo::TypeResizeLeftRight);
- break;
- case kThemeNotAllowedCursor:
- info.SetType(NSCursorInfo::TypeNotAllowed);
- break;
- case kThemeResizeUpCursor:
- info.SetType(NSCursorInfo::TypeResizeUp);
- break;
- case kThemeResizeDownCursor:
- info.SetType(NSCursorInfo::TypeResizeDown);
- break;
- case kThemeResizeUpDownCursor:
- info.SetType(NSCursorInfo::TypeResizeUpDown);
- break;
- case kThemePoofCursor:
- info.SetType(NSCursorInfo::TypeDisappearingItem);
- break;
- default:
- info.SetType(NSCursorInfo::TypeArrow);
- break;
- }
- return OnSetCursor(info);
-}
-
-extern "C" NS_VISIBILITY_DEFAULT BOOL
-mac_plugin_interposing_child_OnHideCursor()
-{
- return OnHideCursor();
-}
-
-extern "C" NS_VISIBILITY_DEFAULT BOOL
-mac_plugin_interposing_child_OnShowCursor()
-{
- return OnUnhideCursor();
-}