| /* |
| * Copyright (C) 2005-2017 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. 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. |
| * 3. Neither the name of Apple Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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. |
| */ |
| |
| #if ENABLE(NETSCAPE_PLUGIN_API) |
| |
| #import "WebBaseNetscapePluginView.h" |
| |
| #import "WebFrameInternal.h" |
| #import "WebKitLogging.h" |
| #import "WebKitNSStringExtras.h" |
| #import "WebNSURLExtras.h" |
| #import "WebNSURLRequestExtras.h" |
| #import "WebView.h" |
| #import "WebViewInternal.h" |
| #import <JavaScriptCore/InitializeThreading.h> |
| #import <WebCore/AuthenticationMac.h> |
| #import <WebCore/BitmapImage.h> |
| #import <WebCore/Credential.h> |
| #import <WebCore/CredentialStorage.h> |
| #import <WebCore/Document.h> |
| #import <WebCore/Element.h> |
| #import <WebCore/Frame.h> |
| #import <WebCore/FrameLoader.h> |
| #import <WebCore/HTMLPlugInElement.h> |
| #import <WebCore/Page.h> |
| #import <WebCore/ProtectionSpace.h> |
| #import <WebCore/RenderEmbeddedObject.h> |
| #import <WebCore/RenderView.h> |
| #import <WebCore/SecurityOrigin.h> |
| #import <WebKitLegacy/DOMPrivate.h> |
| #import <pal/spi/cg/CoreGraphicsSPI.h> |
| #import <wtf/Assertions.h> |
| #import <wtf/MainThread.h> |
| #import <wtf/RunLoop.h> |
| #import <wtf/text/CString.h> |
| |
| #define LoginWindowDidSwitchFromUserNotification @"WebLoginWindowDidSwitchFromUserNotification" |
| #define LoginWindowDidSwitchToUserNotification @"WebLoginWindowDidSwitchToUserNotification" |
| |
| using namespace WebCore; |
| |
| @implementation WebBaseNetscapePluginView |
| |
| + (void)initialize |
| { |
| JSC::initializeThreading(); |
| WTF::initializeMainThreadToProcessMainThread(); |
| RunLoop::initializeMainRunLoop(); |
| WebKit::sendUserChangeNotifications(); |
| } |
| |
| - (id)initWithFrame:(NSRect)frame |
| pluginPackage:(WebNetscapePluginPackage *)pluginPackage |
| URL:(NSURL *)URL |
| baseURL:(NSURL *)baseURL |
| MIMEType:(NSString *)MIME |
| attributeKeys:(NSArray *)keys |
| attributeValues:(NSArray *)values |
| loadManually:(BOOL)loadManually |
| element:(RefPtr<WebCore::HTMLPlugInElement>&&)element |
| { |
| self = [super initWithFrame:frame]; |
| if (!self) |
| return nil; |
| |
| _pluginPackage = pluginPackage; |
| _element = WTFMove(element); |
| _sourceURL = adoptNS([URL copy]); |
| _baseURL = adoptNS([baseURL copy]); |
| _MIMEType = adoptNS([MIME copy]); |
| |
| // Enable "kiosk mode" when instantiating the QT plug-in inside of Dashboard. See <rdar://problem/6878105> |
| if ([[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.dashboard.client"] && |
| [_pluginPackage.get() bundleIdentifier] == "com.apple.QuickTime Plugin.plugin") { |
| RetainPtr<NSMutableArray> mutableKeys = adoptNS([keys mutableCopy]); |
| RetainPtr<NSMutableArray> mutableValues = adoptNS([values mutableCopy]); |
| |
| [mutableKeys.get() addObject:@"kioskmode"]; |
| [mutableValues.get() addObject:@"true"]; |
| [self setAttributeKeys:mutableKeys.get() andValues:mutableValues.get()]; |
| } else |
| [self setAttributeKeys:keys andValues:values]; |
| |
| if (loadManually) |
| _mode = NP_FULL; |
| else |
| _mode = NP_EMBED; |
| |
| _loadManually = loadManually; |
| return self; |
| } |
| |
| - (void)dealloc |
| { |
| ASSERT(!_isStarted); |
| |
| [super dealloc]; |
| } |
| |
| - (WebNetscapePluginPackage *)pluginPackage |
| { |
| return _pluginPackage.get(); |
| } |
| |
| - (BOOL)isFlipped |
| { |
| return YES; |
| } |
| |
| - (NSURL *)URLWithCString:(const char *)cString |
| { |
| if (!cString) |
| return nil; |
| |
| NSString *string = [NSString stringWithCString:cString encoding:NSISOLatin1StringEncoding]; |
| string = [string stringByReplacingOccurrencesOfString:@"\r" withString:@""]; |
| string = [string stringByReplacingOccurrencesOfString:@"\n" withString:@""]; |
| return [NSURL _web_URLWithDataAsString:string relativeToURL:_baseURL.get()]; |
| } |
| |
| - (NSMutableURLRequest *)requestWithURLCString:(const char *)URLCString |
| { |
| NSURL *URL = [self URLWithCString:URLCString]; |
| if (!URL) |
| return nil; |
| |
| NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL]; |
| Frame* frame = core([self webFrame]); |
| if (!frame) |
| return nil; |
| [request _web_setHTTPReferrer:frame->loader().outgoingReferrer()]; |
| return request; |
| } |
| |
| // Methods that subclasses must override |
| - (void)setAttributeKeys:(NSArray *)keys andValues:(NSArray *)values |
| { |
| // This needs to be overridden by subclasses. |
| } |
| |
| - (void)handleMouseMoved:(NSEvent *)event |
| { |
| // This needs to be overriden by subclasses. |
| } |
| |
| - (void)handleMouseEntered:(NSEvent *)event |
| { |
| // This needs to be overridden by subclasses. |
| } |
| |
| - (void)handleMouseExited:(NSEvent *)event |
| { |
| // This needs to be overridden by subclasses. |
| } |
| |
| - (void)focusChanged |
| { |
| // This needs to be overridden by subclasses. |
| } |
| |
| - (void)windowFocusChanged:(BOOL)hasFocus |
| { |
| // This needs to be overridden by subclasses. |
| } |
| |
| - (BOOL)createPlugin |
| { |
| // This needs to be overridden by subclasses. |
| return NO; |
| } |
| |
| - (void)loadStream |
| { |
| // This needs to be overridden by subclasses. |
| } |
| |
| - (BOOL)shouldStop |
| { |
| // This needs to be overridden by subclasses. |
| return YES; |
| } |
| |
| - (void)destroyPlugin |
| { |
| // This needs to be overridden by subclasses. |
| } |
| |
| - (void)updateAndSetWindow |
| { |
| // This needs to be overridden by subclasses. |
| } |
| |
| - (void)sendModifierEventWithKeyCode:(int)keyCode character:(char)character |
| { |
| // This needs to be overridden by subclasses. |
| } |
| |
| - (void)privateBrowsingModeDidChange |
| { |
| } |
| |
| - (void)removeTrackingRect |
| { |
| if (_trackingTag) { |
| [self removeTrackingRect:_trackingTag]; |
| _trackingTag = 0; |
| |
| // Do the following after setting trackingTag to 0 so we don't re-enter. |
| |
| // Balance the retain in resetTrackingRect. Use autorelease in case we hold |
| // the last reference to the window during tear-down, to avoid crashing AppKit. |
| [[self window] autorelease]; |
| } |
| } |
| |
| - (void)resetTrackingRect |
| { |
| [self removeTrackingRect]; |
| if (_isStarted) { |
| // Retain the window so that removeTrackingRect can work after the window is closed. |
| [[self window] retain]; |
| _trackingTag = [self addTrackingRect:[self bounds] owner:self userData:nil assumeInside:NO]; |
| } |
| } |
| |
| - (void)stopTimers |
| { |
| _shouldFireTimers = NO; |
| } |
| |
| - (void)startTimers |
| { |
| _shouldFireTimers = YES; |
| } |
| |
| - (void)restartTimers |
| { |
| [self stopTimers]; |
| |
| if (!_isStarted || [[self window] isMiniaturized]) |
| return; |
| |
| [self startTimers]; |
| } |
| |
| - (NSRect)_windowClipRect |
| { |
| auto* renderer = _element->renderer(); |
| if (!is<RenderEmbeddedObject>(renderer)) |
| return NSZeroRect; |
| return downcast<RenderEmbeddedObject>(*renderer).windowClipRect(); |
| } |
| |
| - (NSRect)visibleRect |
| { |
| // WebCore may impose an additional clip (via CSS overflow or clip properties). Fetch |
| // that clip now. |
| return NSIntersectionRect([self convertRect:[self _windowClipRect] fromView:nil], [super visibleRect]); |
| } |
| |
| - (BOOL)acceptsFirstResponder |
| { |
| return YES; |
| } |
| |
| - (void)sendActivateEvent:(BOOL)activate |
| { |
| if (!_isStarted) |
| return; |
| |
| [self windowFocusChanged:activate]; |
| } |
| |
| - (void)setHasFocus:(BOOL)flag |
| { |
| if (!_isStarted) |
| return; |
| |
| if (_hasFocus == flag) |
| return; |
| |
| _hasFocus = flag; |
| |
| [self focusChanged]; |
| } |
| |
| - (void)addWindowObservers |
| { |
| ASSERT([self window]); |
| |
| NSWindow *theWindow = [self window]; |
| |
| NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; |
| [notificationCenter addObserver:self selector:@selector(windowWillClose:) |
| name:NSWindowWillCloseNotification object:theWindow]; |
| [notificationCenter addObserver:self selector:@selector(windowBecameKey:) |
| name:NSWindowDidBecomeKeyNotification object:theWindow]; |
| [notificationCenter addObserver:self selector:@selector(windowResignedKey:) |
| name:NSWindowDidResignKeyNotification object:theWindow]; |
| [notificationCenter addObserver:self selector:@selector(windowDidMiniaturize:) |
| name:NSWindowDidMiniaturizeNotification object:theWindow]; |
| [notificationCenter addObserver:self selector:@selector(windowDidDeminiaturize:) |
| name:NSWindowDidDeminiaturizeNotification object:theWindow]; |
| |
| [notificationCenter addObserver:self selector:@selector(loginWindowDidSwitchFromUser:) |
| name:LoginWindowDidSwitchFromUserNotification object:nil]; |
| [notificationCenter addObserver:self selector:@selector(loginWindowDidSwitchToUser:) |
| name:LoginWindowDidSwitchToUserNotification object:nil]; |
| } |
| |
| - (void)removeWindowObservers |
| { |
| NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; |
| [notificationCenter removeObserver:self name:NSWindowWillCloseNotification object:nil]; |
| [notificationCenter removeObserver:self name:NSWindowDidBecomeKeyNotification object:nil]; |
| [notificationCenter removeObserver:self name:NSWindowDidResignKeyNotification object:nil]; |
| [notificationCenter removeObserver:self name:NSWindowDidMiniaturizeNotification object:nil]; |
| [notificationCenter removeObserver:self name:NSWindowDidDeminiaturizeNotification object:nil]; |
| [notificationCenter removeObserver:self name:LoginWindowDidSwitchFromUserNotification object:nil]; |
| [notificationCenter removeObserver:self name:LoginWindowDidSwitchToUserNotification object:nil]; |
| } |
| |
| - (void)start |
| { |
| ASSERT([self currentWindow]); |
| |
| if (_isStarted) |
| return; |
| |
| if (_triedAndFailedToCreatePlugin) |
| return; |
| |
| ASSERT([self webView]); |
| |
| if (![[[self webView] preferences] arePlugInsEnabled]) |
| return; |
| |
| Frame* frame = core([self webFrame]); |
| if (!frame) |
| return; |
| Page* page = frame->page(); |
| if (!page) |
| return; |
| |
| bool wasDeferring = page->defersLoading(); |
| if (!wasDeferring) |
| page->setDefersLoading(true); |
| |
| BOOL result = [self createPlugin]; |
| |
| if (!wasDeferring) |
| page->setDefersLoading(false); |
| |
| if (!result) { |
| _triedAndFailedToCreatePlugin = YES; |
| return; |
| } |
| |
| _isStarted = YES; |
| |
| [[self webView] addPluginInstanceView:self]; |
| |
| if ([self currentWindow]) |
| [self updateAndSetWindow]; |
| |
| if ([self window]) { |
| [self addWindowObservers]; |
| if ([[self window] isKeyWindow]) { |
| [self sendActivateEvent:YES]; |
| } |
| [self restartTimers]; |
| } |
| |
| [self resetTrackingRect]; |
| |
| [self loadStream]; |
| } |
| |
| - (void)stop |
| { |
| if (![self shouldStop]) |
| return; |
| |
| [self removeTrackingRect]; |
| |
| if (!_isStarted) |
| return; |
| |
| _isStarted = NO; |
| |
| [[self webView] removePluginInstanceView:self]; |
| |
| // Stop the timers |
| [self stopTimers]; |
| |
| // Stop notifications and callbacks. |
| [self removeWindowObservers]; |
| |
| [self destroyPlugin]; |
| } |
| |
| - (BOOL)shouldClipOutPlugin |
| { |
| NSWindow *window = [self window]; |
| return !window || [window isMiniaturized] || [NSApp isHidden] || ![self isDescendantOf:[[self window] contentView]] || [self isHiddenOrHasHiddenAncestor]; |
| } |
| |
| - (BOOL)supportsSnapshotting |
| { |
| return [_pluginPackage.get() supportsSnapshotting]; |
| } |
| |
| - (void)cacheSnapshot |
| { |
| NSSize boundsSize = [self bounds].size; |
| if (!boundsSize.height || !boundsSize.width) |
| return; |
| |
| NSImage *snapshot = [[NSImage alloc] initWithSize:boundsSize]; |
| |
| _snapshotting = YES; |
| [snapshot lockFocus]; |
| [self drawRect:[self bounds]]; |
| [snapshot unlockFocus]; |
| _snapshotting = NO; |
| |
| _cachedSnapshot = adoptNS(snapshot); |
| } |
| |
| - (void)clearCachedSnapshot |
| { |
| _cachedSnapshot.clear(); |
| } |
| |
| - (void)viewWillMoveToWindow:(NSWindow *)newWindow |
| { |
| // We must remove the tracking rect before we move to the new window. |
| // Once we move to the new window, it will be too late. |
| [self removeTrackingRect]; |
| [self removeWindowObservers]; |
| |
| // Workaround for: <rdar://problem/3822871> resignFirstResponder is not sent to first responder view when it is removed from the window |
| [self setHasFocus:NO]; |
| |
| if (!newWindow) { |
| if ([[self webView] hostWindow]) { |
| // View will be moved out of the actual window but it still has a host window. |
| [self stopTimers]; |
| } else { |
| // View will have no associated windows. |
| [self stop]; |
| |
| // Stop observing WebPreferencesChangedInternalNotification -- we only need to observe this when installed in the view hierarchy. |
| // When not in the view hierarchy, -viewWillMoveToWindow: and -viewDidMoveToWindow will start/stop the plugin as needed. |
| [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedInternalNotification object:nil]; |
| } |
| } |
| } |
| |
| - (void)viewWillMoveToSuperview:(NSView *)newSuperview |
| { |
| if (!newSuperview) { |
| // Stop the plug-in when it is removed from its superview. It is not sufficient to do this in -viewWillMoveToWindow:nil, because |
| // the WebView might still has a hostWindow at that point, which prevents the plug-in from being destroyed. |
| // There is no need to start the plug-in when moving into a superview. -viewDidMoveToWindow takes care of that. |
| [self stop]; |
| |
| // Stop observing WebPreferencesChangedInternalNotification -- we only need to observe this when installed in the view hierarchy. |
| // When not in the view hierarchy, -viewWillMoveToWindow: and -viewDidMoveToWindow will start/stop the plugin as needed. |
| [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedInternalNotification object:nil]; |
| } |
| } |
| |
| - (void)viewDidMoveToWindow |
| { |
| [self resetTrackingRect]; |
| |
| if ([self window]) { |
| // While in the view hierarchy, observe WebPreferencesChangedInternalNotification so that we can start/stop depending |
| // on whether plugins are enabled. |
| [[NSNotificationCenter defaultCenter] addObserver:self |
| selector:@selector(preferencesHaveChanged:) |
| name:WebPreferencesChangedInternalNotification |
| object:nil]; |
| |
| _isPrivateBrowsingEnabled = [[[self webView] preferences] privateBrowsingEnabled]; |
| |
| // View moved to an actual window. Start it if not already started. |
| [self start]; |
| |
| // Starting the plug-in can result in it removing itself from the window so we need to ensure that we're still in |
| // place before doing anything that requires a window. |
| if ([self window]) { |
| [self restartTimers]; |
| [self addWindowObservers]; |
| } |
| } else if ([[self webView] hostWindow]) { |
| // View moved out of an actual window, but still has a host window. |
| // Call setWindow to explicitly "clip out" the plug-in from sight. |
| // FIXME: It would be nice to do this where we call stopNullEvents in viewWillMoveToWindow. |
| [self updateAndSetWindow]; |
| } |
| } |
| |
| - (void)viewWillMoveToHostWindow:(NSWindow *)hostWindow |
| { |
| if (!hostWindow && ![self window]) { |
| // View will have no associated windows. |
| [self stop]; |
| |
| // Remove WebPreferencesChangedInternalNotification observer -- we will observe once again when we move back into the window |
| [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedInternalNotification object:nil]; |
| } |
| } |
| |
| - (void)viewDidMoveToHostWindow |
| { |
| if ([[self webView] hostWindow]) { |
| // View now has an associated window. Start it if not already started. |
| [self start]; |
| } |
| } |
| |
| // MARK: NOTIFICATIONS |
| |
| - (void)windowWillClose:(NSNotification *)notification |
| { |
| [self stop]; |
| } |
| |
| - (void)windowBecameKey:(NSNotification *)notification |
| { |
| [self sendActivateEvent:YES]; |
| [self invalidatePluginContentRect:[self bounds]]; |
| [self restartTimers]; |
| } |
| |
| - (void)windowResignedKey:(NSNotification *)notification |
| { |
| [self sendActivateEvent:NO]; |
| [self invalidatePluginContentRect:[self bounds]]; |
| [self restartTimers]; |
| } |
| |
| - (void)windowDidMiniaturize:(NSNotification *)notification |
| { |
| [self stopTimers]; |
| } |
| |
| - (void)windowDidDeminiaturize:(NSNotification *)notification |
| { |
| [self restartTimers]; |
| } |
| |
| - (void)loginWindowDidSwitchFromUser:(NSNotification *)notification |
| { |
| [self stopTimers]; |
| } |
| |
| -(void)loginWindowDidSwitchToUser:(NSNotification *)notification |
| { |
| [self restartTimers]; |
| } |
| |
| - (void)preferencesHaveChanged:(NSNotification *)notification |
| { |
| WebPreferences *preferences = [[self webView] preferences]; |
| |
| if ([notification object] != preferences) |
| return; |
| |
| BOOL arePlugInsEnabled = [preferences arePlugInsEnabled]; |
| if (_isStarted != arePlugInsEnabled) { |
| if (arePlugInsEnabled) { |
| if ([self currentWindow]) { |
| [self start]; |
| } |
| } else { |
| [self stop]; |
| [self invalidatePluginContentRect:[self bounds]]; |
| } |
| } |
| |
| BOOL isPrivateBrowsingEnabled = [preferences privateBrowsingEnabled]; |
| if (isPrivateBrowsingEnabled != _isPrivateBrowsingEnabled) { |
| _isPrivateBrowsingEnabled = isPrivateBrowsingEnabled; |
| [self privateBrowsingModeDidChange]; |
| } |
| } |
| |
| - (void)renewGState |
| { |
| [super renewGState]; |
| |
| // -renewGState is called whenever the view's geometry changes. It's a little hacky to override this method, but |
| // much safer than walking up the view hierarchy and observing frame/bounds changed notifications, since you don't |
| // have to track subsequent changes to the view hierarchy and add/remove notification observers. |
| // NSOpenGLView uses the exact same technique to reshape its OpenGL surface. |
| |
| // All of the work this method does may safely be skipped if the view is not in a window. When the view |
| // is moved back into a window, everything should be set up correctly. |
| if (![self window]) |
| return; |
| |
| [self updateAndSetWindow]; |
| |
| [self resetTrackingRect]; |
| |
| // Check to see if the plugin view is completely obscured (scrolled out of view, for example). |
| // For performance reasons, we send null events at a lower rate to plugins which are obscured. |
| BOOL oldIsObscured = _isCompletelyObscured; |
| _isCompletelyObscured = NSIsEmptyRect([self visibleRect]); |
| if (_isCompletelyObscured != oldIsObscured) |
| [self restartTimers]; |
| } |
| |
| - (BOOL)becomeFirstResponder |
| { |
| [self setHasFocus:YES]; |
| return YES; |
| } |
| |
| - (BOOL)resignFirstResponder |
| { |
| [self setHasFocus:NO]; |
| return YES; |
| } |
| |
| - (WebDataSource *)dataSource |
| { |
| return [[self webFrame] _dataSource]; |
| } |
| |
| - (WebFrame *)webFrame |
| { |
| return kit(_element->document().frame()); |
| } |
| |
| - (WebView *)webView |
| { |
| return [[self webFrame] webView]; |
| } |
| |
| - (NSWindow *)currentWindow |
| { |
| return [self window] ? [self window] : [[self webView] hostWindow]; |
| } |
| |
| - (WebCore::HTMLPlugInElement*)element |
| { |
| return _element.get(); |
| } |
| |
| - (void)cut:(id)sender |
| { |
| [self sendModifierEventWithKeyCode:7 character:'x']; |
| } |
| |
| - (void)copy:(id)sender |
| { |
| [self sendModifierEventWithKeyCode:8 character:'c']; |
| } |
| |
| - (void)paste:(id)sender |
| { |
| [self sendModifierEventWithKeyCode:9 character:'v']; |
| } |
| |
| - (void)selectAll:(id)sender |
| { |
| [self sendModifierEventWithKeyCode:0 character:'a']; |
| } |
| |
| // AppKit doesn't call mouseDown or mouseUp on right-click. Simulate control-click |
| // mouseDown and mouseUp so plug-ins get the right-click event as they do in Carbon (3125743). |
| - (void)rightMouseDown:(NSEvent *)theEvent |
| { |
| [self mouseDown:theEvent]; |
| } |
| |
| - (void)rightMouseUp:(NSEvent *)theEvent |
| { |
| [self mouseUp:theEvent]; |
| } |
| |
| |
| - (BOOL)convertFromX:(double)sourceX andY:(double)sourceY space:(NPCoordinateSpace)sourceSpace |
| toX:(double *)destX andY:(double *)destY space:(NPCoordinateSpace)destSpace |
| { |
| // Nothing to do |
| if (sourceSpace == destSpace) { |
| if (destX) |
| *destX = sourceX; |
| if (destY) |
| *destY = sourceY; |
| return YES; |
| } |
| |
| NSPoint sourcePoint = NSMakePoint(sourceX, sourceY); |
| |
| NSPoint sourcePointInScreenSpace; |
| |
| // First convert to screen space |
| switch (sourceSpace) { |
| case NPCoordinateSpacePlugin: |
| sourcePointInScreenSpace = [self convertPoint:sourcePoint toView:nil]; |
| #pragma clang diagnostic push |
| #pragma clang diagnostic ignored "-Wdeprecated-declarations" |
| sourcePointInScreenSpace = [[self currentWindow] convertBaseToScreen:sourcePointInScreenSpace]; |
| #pragma clang diagnostic pop |
| break; |
| |
| case NPCoordinateSpaceWindow: |
| #pragma clang diagnostic push |
| #pragma clang diagnostic ignored "-Wdeprecated-declarations" |
| sourcePointInScreenSpace = [[self currentWindow] convertBaseToScreen:sourcePoint]; |
| #pragma clang diagnostic pop |
| break; |
| |
| case NPCoordinateSpaceFlippedWindow: |
| sourcePoint.y = [[self currentWindow] frame].size.height - sourcePoint.y; |
| #pragma clang diagnostic push |
| #pragma clang diagnostic ignored "-Wdeprecated-declarations" |
| sourcePointInScreenSpace = [[self currentWindow] convertBaseToScreen:sourcePoint]; |
| #pragma clang diagnostic pop |
| break; |
| |
| case NPCoordinateSpaceScreen: |
| sourcePointInScreenSpace = sourcePoint; |
| break; |
| |
| case NPCoordinateSpaceFlippedScreen: |
| sourcePoint.y = [(NSScreen *)[[NSScreen screens] objectAtIndex:0] frame].size.height - sourcePoint.y; |
| sourcePointInScreenSpace = sourcePoint; |
| break; |
| default: |
| return FALSE; |
| } |
| |
| NSPoint destPoint; |
| |
| // Then convert back to the destination space |
| switch (destSpace) { |
| case NPCoordinateSpacePlugin: |
| #pragma clang diagnostic push |
| #pragma clang diagnostic ignored "-Wdeprecated-declarations" |
| destPoint = [[self currentWindow] convertScreenToBase:sourcePointInScreenSpace]; |
| #pragma clang diagnostic pop |
| destPoint = [self convertPoint:destPoint fromView:nil]; |
| break; |
| |
| case NPCoordinateSpaceWindow: |
| #pragma clang diagnostic push |
| #pragma clang diagnostic ignored "-Wdeprecated-declarations" |
| destPoint = [[self currentWindow] convertScreenToBase:sourcePointInScreenSpace]; |
| #pragma clang diagnostic pop |
| break; |
| |
| case NPCoordinateSpaceFlippedWindow: |
| #pragma clang diagnostic push |
| #pragma clang diagnostic ignored "-Wdeprecated-declarations" |
| destPoint = [[self currentWindow] convertScreenToBase:sourcePointInScreenSpace]; |
| #pragma clang diagnostic pop |
| destPoint.y = [[self currentWindow] frame].size.height - destPoint.y; |
| break; |
| |
| case NPCoordinateSpaceScreen: |
| destPoint = sourcePointInScreenSpace; |
| break; |
| |
| case NPCoordinateSpaceFlippedScreen: |
| destPoint = sourcePointInScreenSpace; |
| destPoint.y = [(NSScreen *)[[NSScreen screens] objectAtIndex:0] frame].size.height - destPoint.y; |
| break; |
| |
| default: |
| return FALSE; |
| } |
| |
| if (destX) |
| *destX = destPoint.x; |
| if (destY) |
| *destY = destPoint.y; |
| |
| return TRUE; |
| } |
| |
| |
| - (void)invalidatePluginContentRect:(NSRect)rect |
| { |
| auto* renderer = _element->renderer(); |
| if (!is<RenderEmbeddedObject>(renderer)) |
| return; |
| auto& object = downcast<RenderEmbeddedObject>(*renderer); |
| IntRect contentRect(rect); |
| contentRect.move(object.borderLeft() + object.paddingLeft(), object.borderTop() + object.paddingTop()); |
| object.repaintRectangle(contentRect); |
| } |
| |
| - (NSRect)actualVisibleRectInWindow |
| { |
| auto* renderer = _element->renderer(); |
| if (!is<RenderEmbeddedObject>(renderer)) |
| return NSZeroRect; |
| auto& object = downcast<RenderEmbeddedObject>(*renderer); |
| auto widgetRect = object.view().frameView().contentsToWindow(object.pixelSnappedAbsoluteClippedOverflowRect()); |
| return intersection(object.windowClipRect(), widgetRect); |
| } |
| |
| - (CALayer *)pluginLayer |
| { |
| // This needs to be overridden by subclasses. |
| return nil; |
| } |
| |
| - (BOOL)getFormValue:(NSString **)value |
| { |
| // This needs to be overridden by subclasses. |
| return false; |
| } |
| |
| @end |
| |
| namespace WebKit { |
| |
| bool getAuthenticationInfo(const char* protocolStr, const char* hostStr, int32_t port, const char* schemeStr, const char* realmStr, CString& username, CString& password) |
| { |
| if (!equalLettersIgnoringASCIICase(protocolStr, "http") && !equalLettersIgnoringASCIICase(protocolStr, "https")) |
| return false; |
| |
| NSString *host = [NSString stringWithUTF8String:hostStr]; |
| if (!hostStr) |
| return false; |
| |
| NSString *protocol = [NSString stringWithUTF8String:protocolStr]; |
| if (!protocol) |
| return false; |
| |
| NSString *realm = [NSString stringWithUTF8String:realmStr]; |
| if (!realm) |
| return NPERR_GENERIC_ERROR; |
| |
| NSString *authenticationMethod = NSURLAuthenticationMethodDefault; |
| if (equalLettersIgnoringASCIICase(protocolStr, "http")) { |
| if (equalLettersIgnoringASCIICase(schemeStr, "basic")) |
| authenticationMethod = NSURLAuthenticationMethodHTTPBasic; |
| else if (equalLettersIgnoringASCIICase(schemeStr, "digest")) |
| authenticationMethod = NSURLAuthenticationMethodHTTPDigest; |
| } |
| |
| RetainPtr<NSURLProtectionSpace> protectionSpace = adoptNS([[NSURLProtectionSpace alloc] initWithHost:host port:port protocol:protocol realm:realm authenticationMethod:authenticationMethod]); |
| |
| NSURLCredential *credential = CredentialStorage::defaultCredentialStorage().get(emptyString(), ProtectionSpace(protectionSpace.get())).nsCredential(); |
| if (!credential) |
| credential = [[NSURLCredentialStorage sharedCredentialStorage] defaultCredentialForProtectionSpace:protectionSpace.get()]; |
| if (!credential) |
| return false; |
| |
| if (![credential hasPassword]) |
| return false; |
| |
| username = [[credential user] UTF8String]; |
| password = [[credential password] UTF8String]; |
| |
| return true; |
| } |
| |
| void sendUserChangeNotifications() |
| { |
| auto consoleConnectionChangeNotifyProc = [](CGSNotificationType type, CGSNotificationData, CGSByteCount, CGSNotificationArg) { |
| NSString *notificationName = nil; |
| if (type == kCGSessionConsoleConnect) |
| notificationName = LoginWindowDidSwitchToUserNotification; |
| else if (type == kCGSessionConsoleDisconnect) |
| notificationName = LoginWindowDidSwitchFromUserNotification; |
| else |
| ASSERT_NOT_REACHED(); |
| [[NSNotificationCenter defaultCenter] postNotificationName:notificationName object:nil]; |
| }; |
| |
| CGSRegisterNotifyProc(consoleConnectionChangeNotifyProc, kCGSessionConsoleConnect, nullptr); |
| CGSRegisterNotifyProc(consoleConnectionChangeNotifyProc, kCGSessionConsoleDisconnect, nullptr); |
| } |
| |
| } // namespace WebKit |
| |
| #endif // ENABLE(NETSCAPE_PLUGIN_API) |
| |