Don't register for Lookup notifications until needed
[WebKit-https.git] / Source / WebKit2 / UIProcess / mac / PageClientImpl.mm
1 /*
2  * Copyright (C) 2010, 2011 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 "PageClientImpl.h"
28
29 #if PLATFORM(MAC)
30
31 #import "AttributedString.h"
32 #import "ColorSpaceData.h"
33 #import "DataReference.h"
34 #import "DictionaryPopupInfo.h"
35 #import "DownloadProxy.h"
36 #import "NativeWebKeyboardEvent.h"
37 #import "NativeWebWheelEvent.h"
38 #import "NavigationState.h"
39 #import "StringUtilities.h"
40 #import "ViewSnapshotStore.h"
41 #import "WKAPICast.h"
42 #import "WKFullScreenWindowController.h"
43 #import "WKStringCF.h"
44 #import "WKViewInternal.h"
45 #import "WKWebViewInternal.h"
46 #import "WebColorPickerMac.h"
47 #import "WebContextMenuProxyMac.h"
48 #import "WebEditCommandProxy.h"
49 #import "WebPopupMenuProxyMac.h"
50 #import "WindowServerConnection.h"
51 #import "_WKDownloadInternal.h"
52 #import "_WKThumbnailView.h"
53 #import <WebCore/AlternativeTextUIController.h>
54 #import <WebCore/BitmapImage.h>
55 #import <WebCore/Cursor.h>
56 #import <WebCore/FloatRect.h>
57 #import <WebCore/GraphicsContext.h>
58 #import <WebCore/Image.h>
59 #import <WebCore/KeyboardEvent.h>
60 #import <WebCore/LookupSPI.h>
61 #import <WebCore/NotImplemented.h>
62 #import <WebCore/SharedBuffer.h>
63 #import <WebCore/TextIndicator.h>
64 #import <WebCore/TextUndoInsertionMarkupMac.h>
65 #import <WebKitSystemInterface.h>
66 #import <wtf/text/CString.h>
67 #import <wtf/text/WTFString.h>
68
69 #if USE(DICTATION_ALTERNATIVES)
70 #import <AppKit/NSTextAlternatives.h>
71 #endif
72
73 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
74 #include <WebCore/WebMediaSessionManagerMac.h>
75 #endif
76
77 @interface NSApplication (WebNSApplicationDetails)
78 - (NSCursor *)_cursorRectCursor;
79 @end
80
81 #if HAVE(OUT_OF_PROCESS_LAYER_HOSTING)
82 @interface NSWindow (WebNSWindowDetails)
83 - (BOOL)_hostsLayersInWindowServer;
84 @end
85 #endif
86
87 SOFT_LINK_CONSTANT_MAY_FAIL(Lookup, LUTermOptionDisableSearchTermIndicator, NSString *)
88
89 using namespace WebCore;
90 using namespace WebKit;
91
92 @interface WKEditCommandObjC : NSObject
93 {
94     RefPtr<WebEditCommandProxy> m_command;
95 }
96 - (id)initWithWebEditCommandProxy:(PassRefPtr<WebEditCommandProxy>)command;
97 - (WebEditCommandProxy*)command;
98 @end
99
100 @interface WKEditorUndoTargetObjC : NSObject
101 - (void)undoEditing:(id)sender;
102 - (void)redoEditing:(id)sender;
103 @end
104
105 @implementation WKEditCommandObjC
106
107 - (id)initWithWebEditCommandProxy:(PassRefPtr<WebEditCommandProxy>)command
108 {
109     self = [super init];
110     if (!self)
111         return nil;
112
113     m_command = command;
114     return self;
115 }
116
117 - (WebEditCommandProxy*)command
118 {
119     return m_command.get();
120 }
121
122 @end
123
124 @implementation WKEditorUndoTargetObjC
125
126 - (void)undoEditing:(id)sender
127 {
128     ASSERT([sender isKindOfClass:[WKEditCommandObjC class]]);
129     [sender command]->unapply();
130 }
131
132 - (void)redoEditing:(id)sender
133 {
134     ASSERT([sender isKindOfClass:[WKEditCommandObjC class]]);
135     [sender command]->reapply();
136 }
137
138 @end
139
140 namespace WebKit {
141
142 PageClientImpl::PageClientImpl(WKView* wkView, WKWebView *webView)
143     : m_wkView(wkView)
144     , m_webView(webView)
145     , m_undoTarget(adoptNS([[WKEditorUndoTargetObjC alloc] init]))
146 #if USE(DICTATION_ALTERNATIVES)
147     , m_alternativeTextUIController(std::make_unique<AlternativeTextUIController>())
148 #endif
149 {
150 #if !WK_API_ENABLED
151     ASSERT_UNUSED(m_webView, !m_webView);
152 #endif
153 }
154
155 PageClientImpl::~PageClientImpl()
156 {
157 }
158
159 std::unique_ptr<DrawingAreaProxy> PageClientImpl::createDrawingAreaProxy()
160 {
161     return [m_wkView _createDrawingAreaProxy];
162 }
163
164 void PageClientImpl::setViewNeedsDisplay(const WebCore::IntRect& rect)
165 {
166     ASSERT_NOT_REACHED();
167 }
168
169 void PageClientImpl::displayView()
170 {
171     ASSERT_NOT_REACHED();
172 }
173
174 bool PageClientImpl::canScrollView()
175 {
176     return false;
177 }
178
179 void PageClientImpl::scrollView(const IntRect& scrollRect, const IntSize& scrollOffset)
180 {
181     ASSERT_NOT_REACHED();
182 }
183
184 void PageClientImpl::requestScroll(const FloatPoint& scrollPosition, bool isProgrammaticScroll)
185 {
186     ASSERT_NOT_REACHED();
187 }
188
189 IntSize PageClientImpl::viewSize()
190 {
191     return IntSize([m_wkView bounds].size);
192 }
193
194 NSView *PageClientImpl::activeView() const
195 {
196 #if WK_API_ENABLED
197     return m_wkView._thumbnailView ? (NSView *)m_wkView._thumbnailView : (NSView *)m_wkView;
198 #else
199     return m_wkView;
200 #endif
201 }
202
203 NSWindow *PageClientImpl::activeWindow() const
204 {
205 #if WK_API_ENABLED
206     if (m_wkView._thumbnailView)
207         return m_wkView._thumbnailView.window;
208 #endif
209     if (m_wkView._targetWindowForMovePreparation)
210         return m_wkView._targetWindowForMovePreparation;
211     return m_wkView.window;
212 }
213
214 bool PageClientImpl::isViewWindowActive()
215 {
216     NSWindow *activeViewWindow = activeWindow();
217     return activeViewWindow.isKeyWindow || [NSApp keyWindow] == activeViewWindow;
218 }
219
220 bool PageClientImpl::isViewFocused()
221 {
222     return [m_wkView _isFocused];
223 }
224
225 void PageClientImpl::makeFirstResponder()
226 {
227      [[m_wkView window] makeFirstResponder:m_wkView];
228 }
229     
230 bool PageClientImpl::isViewVisible()
231 {
232     NSView *activeView = this->activeView();
233     NSWindow *activeViewWindow = activeWindow();
234
235     if (!activeViewWindow)
236         return false;
237
238     if (!activeViewWindow.isVisible)
239         return false;
240
241     if (activeView.isHiddenOrHasHiddenAncestor)
242         return false;
243
244     if ([m_wkView windowOcclusionDetectionEnabled] && (activeViewWindow.occlusionState & NSWindowOcclusionStateVisible) != NSWindowOcclusionStateVisible)
245         return false;
246
247     return true;
248 }
249
250 bool PageClientImpl::isViewVisibleOrOccluded()
251 {
252     return activeWindow().isVisible;
253 }
254
255 bool PageClientImpl::isViewInWindow()
256 {
257     return activeWindow();
258 }
259
260 bool PageClientImpl::isVisuallyIdle()
261 {
262     return WindowServerConnection::singleton().applicationWindowModificationsHaveStopped() || !isViewVisible();
263 }
264
265 LayerHostingMode PageClientImpl::viewLayerHostingMode()
266 {
267 #if HAVE(OUT_OF_PROCESS_LAYER_HOSTING)
268     if ([activeWindow() _hostsLayersInWindowServer])
269         return LayerHostingMode::OutOfProcess;
270 #endif
271     return LayerHostingMode::InProcess;
272 }
273
274 void PageClientImpl::viewWillMoveToAnotherWindow()
275 {
276     clearAllEditCommands();
277 }
278
279 ColorSpaceData PageClientImpl::colorSpace()
280 {
281     return [m_wkView _colorSpace];
282 }
283
284 void PageClientImpl::processDidExit()
285 {
286     [m_wkView _processDidExit];
287 }
288
289 void PageClientImpl::pageClosed()
290 {
291     [m_wkView _pageClosed];
292 #if USE(DICTATION_ALTERNATIVES)
293     m_alternativeTextUIController->clear();
294 #endif
295 }
296
297 void PageClientImpl::didRelaunchProcess()
298 {
299     [m_wkView _didRelaunchProcess];
300 }
301
302 void PageClientImpl::preferencesDidChange()
303 {
304     [m_wkView _preferencesDidChange];
305 }
306
307 void PageClientImpl::toolTipChanged(const String& oldToolTip, const String& newToolTip)
308 {
309     [m_wkView _toolTipChangedFrom:nsStringFromWebCoreString(oldToolTip) to:nsStringFromWebCoreString(newToolTip)];
310 }
311
312 void PageClientImpl::didCommitLoadForMainFrame(const String& mimeType, bool useCustomContentProvider)
313 {
314 }
315
316 void PageClientImpl::didFinishLoadingDataForCustomContentProvider(const String& suggestedFilename, const IPC::DataReference& dataReference)
317 {
318 }
319
320 void PageClientImpl::handleDownloadRequest(DownloadProxy* download)
321 {
322     ASSERT_ARG(download, download);
323 #if WK_API_ENABLED
324     ASSERT([download->wrapper() isKindOfClass:[_WKDownload class]]);
325     [static_cast<_WKDownload *>(download->wrapper()) setOriginatingWebView:m_webView];
326 #endif
327 }
328
329 void PageClientImpl::didChangeContentSize(const WebCore::IntSize& newSize)
330 {
331     [m_wkView _didChangeContentSize:newSize];
332 }
333
334 void PageClientImpl::setCursor(const WebCore::Cursor& cursor)
335 {
336     // FIXME: Would be nice to share this code with WebKit1's WebChromeClient.
337
338     if ([NSApp _cursorRectCursor])
339         return;
340
341     if (!m_wkView)
342         return;
343
344     NSWindow *window = [m_wkView window];
345     if (!window)
346         return;
347
348     if ([window windowNumber] != [NSWindow windowNumberAtPoint:[NSEvent mouseLocation] belowWindowWithWindowNumber:0])
349         return;
350
351     NSCursor *platformCursor = cursor.platformCursor();
352     if ([NSCursor currentCursor] == platformCursor)
353         return;
354
355     [platformCursor set];
356 }
357
358 void PageClientImpl::setCursorHiddenUntilMouseMoves(bool hiddenUntilMouseMoves)
359 {
360     [NSCursor setHiddenUntilMouseMoves:hiddenUntilMouseMoves];
361 }
362
363 void PageClientImpl::didChangeViewportProperties(const WebCore::ViewportAttributes&)
364 {
365 }
366
367 void PageClientImpl::registerEditCommand(PassRefPtr<WebEditCommandProxy> prpCommand, WebPageProxy::UndoOrRedo undoOrRedo)
368 {
369     RefPtr<WebEditCommandProxy> command = prpCommand;
370
371     RetainPtr<WKEditCommandObjC> commandObjC = adoptNS([[WKEditCommandObjC alloc] initWithWebEditCommandProxy:command]);
372     String actionName = WebEditCommandProxy::nameForEditAction(command->editAction());
373
374     NSUndoManager *undoManager = [m_wkView undoManager];
375     [undoManager registerUndoWithTarget:m_undoTarget.get() selector:((undoOrRedo == WebPageProxy::Undo) ? @selector(undoEditing:) : @selector(redoEditing:)) object:commandObjC.get()];
376     if (!actionName.isEmpty())
377         [undoManager setActionName:(NSString *)actionName];
378 }
379
380 #if USE(INSERTION_UNDO_GROUPING)
381 void PageClientImpl::registerInsertionUndoGrouping()
382 {
383     registerInsertionUndoGroupingWithUndoManager([m_wkView undoManager]);
384 }
385 #endif
386
387 void PageClientImpl::clearAllEditCommands()
388 {
389     [[m_wkView undoManager] removeAllActionsWithTarget:m_undoTarget.get()];
390 }
391
392 bool PageClientImpl::canUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo)
393 {
394     return (undoOrRedo == WebPageProxy::Undo) ? [[m_wkView undoManager] canUndo] : [[m_wkView undoManager] canRedo];
395 }
396
397 void PageClientImpl::executeUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo)
398 {
399     return (undoOrRedo == WebPageProxy::Undo) ? [[m_wkView undoManager] undo] : [[m_wkView undoManager] redo];
400 }
401
402 void PageClientImpl::setDragImage(const IntPoint& clientPosition, PassRefPtr<ShareableBitmap> dragImage, bool isLinkDrag)
403 {
404     RetainPtr<CGImageRef> dragCGImage = dragImage->makeCGImage();
405     RetainPtr<NSImage> dragNSImage = adoptNS([[NSImage alloc] initWithCGImage:dragCGImage.get() size:dragImage->size()]);
406     IntSize size([dragNSImage size]);
407     size.scale(1.0 / toImpl([m_wkView pageRef])->deviceScaleFactor());
408     [dragNSImage setSize:size];
409
410 #if WK_API_ENABLED
411     if (m_webView)
412         [m_wkView _dragImageForView:m_webView withImage:dragNSImage.get() at:clientPosition linkDrag:isLinkDrag];
413     else
414 #endif
415         [m_wkView _dragImageForView:m_wkView withImage:dragNSImage.get() at:clientPosition linkDrag:isLinkDrag];
416 }
417
418 void PageClientImpl::setPromisedDataForImage(const String& pasteboardName, PassRefPtr<SharedBuffer> imageBuffer, const String& filename, const String& extension, const String& title, const String& url, const String& visibleUrl, PassRefPtr<SharedBuffer> archiveBuffer)
419 {
420     RefPtr<Image> image = BitmapImage::create();
421     image->setData(imageBuffer.get(), true);
422     [m_wkView _setPromisedDataForImage:image.get() withFileName:filename withExtension:extension withTitle:title withURL:url withVisibleURL:visibleUrl withArchive:archiveBuffer.get() forPasteboard:pasteboardName];
423 }
424
425 #if ENABLE(ATTACHMENT_ELEMENT)
426 void PageClientImpl::setPromisedDataForAttachment(const String& pasteboardName, const String& filename, const String& extension, const String& title, const String& url, const String& visibleUrl)
427 {
428     [m_wkView _setPromisedDataForAttachment:filename withExtension:extension withTitle:title withURL:url withVisibleURL:visibleUrl forPasteboard:pasteboardName];
429 }
430 #endif
431
432 void PageClientImpl::updateSecureInputState()
433 {
434     [m_wkView _updateSecureInputState];
435 }
436
437 void PageClientImpl::resetSecureInputState()
438 {
439     [m_wkView _resetSecureInputState];
440 }
441
442 void PageClientImpl::notifyInputContextAboutDiscardedComposition()
443 {
444     [m_wkView _notifyInputContextAboutDiscardedComposition];
445 }
446
447 #if PLATFORM(MAC) && !USE(ASYNC_NSTEXTINPUTCLIENT)
448 void PageClientImpl::notifyApplicationAboutInputContextChange()
449 {
450     [NSApp updateWindows];
451 }
452 #endif
453
454 FloatRect PageClientImpl::convertToDeviceSpace(const FloatRect& rect)
455 {
456     return [m_wkView _convertToDeviceSpace:rect];
457 }
458
459 FloatRect PageClientImpl::convertToUserSpace(const FloatRect& rect)
460 {
461     return [m_wkView _convertToUserSpace:rect];
462 }
463    
464 IntPoint PageClientImpl::screenToRootView(const IntPoint& point)
465 {
466 #pragma clang diagnostic push
467 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
468     NSPoint windowCoord = [[m_wkView window] convertScreenToBase:point];
469 #pragma clang diagnostic pop
470     return IntPoint([m_wkView convertPoint:windowCoord fromView:nil]);
471 }
472     
473 IntRect PageClientImpl::rootViewToScreen(const IntRect& rect)
474 {
475     NSRect tempRect = rect;
476     tempRect = [m_wkView convertRect:tempRect toView:nil];
477 #pragma clang diagnostic push
478 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
479     tempRect.origin = [[m_wkView window] convertBaseToScreen:tempRect.origin];
480 #pragma clang diagnostic pop
481     return enclosingIntRect(tempRect);
482 }
483
484 void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool eventWasHandled)
485 {
486     [m_wkView _doneWithKeyEvent:event.nativeEvent() eventWasHandled:eventWasHandled];
487 }
488
489 PassRefPtr<WebPopupMenuProxy> PageClientImpl::createPopupMenuProxy(WebPageProxy* page)
490 {
491     return WebPopupMenuProxyMac::create(m_wkView, page);
492 }
493
494 PassRefPtr<WebContextMenuProxy> PageClientImpl::createContextMenuProxy(WebPageProxy* page)
495 {
496     return WebContextMenuProxyMac::create(m_wkView, page);
497 }
498
499 #if ENABLE(INPUT_TYPE_COLOR)
500 PassRefPtr<WebColorPicker> PageClientImpl::createColorPicker(WebPageProxy* page, const WebCore::Color& initialColor,  const WebCore::IntRect& rect)
501 {
502     return WebColorPickerMac::create(page, initialColor, rect, wkView());
503 }
504 #endif
505
506 void PageClientImpl::setTextIndicator(Ref<TextIndicator> textIndicator, WebCore::TextIndicatorLifetime lifetime)
507 {
508     [m_wkView _setTextIndicator:textIndicator.get() withLifetime:lifetime];
509 }
510
511 void PageClientImpl::clearTextIndicator(WebCore::TextIndicatorDismissalAnimation dismissalAnimation)
512 {
513     [m_wkView _clearTextIndicatorWithAnimation:dismissalAnimation];
514 }
515
516 void PageClientImpl::setTextIndicatorAnimationProgress(float progress)
517 {
518     [m_wkView _setTextIndicatorAnimationProgress:progress];
519 }
520
521 void PageClientImpl::accessibilityWebProcessTokenReceived(const IPC::DataReference& data)
522 {
523     NSData* remoteToken = [NSData dataWithBytes:data.data() length:data.size()];
524     [m_wkView _setAccessibilityWebProcessToken:remoteToken];
525 }
526     
527 void PageClientImpl::enterAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext)
528 {
529     ASSERT(!layerTreeContext.isEmpty());
530
531     CALayer *renderLayer = WKMakeRenderLayer(layerTreeContext.contextID);
532     [m_wkView _setAcceleratedCompositingModeRootLayer:renderLayer];
533 }
534
535 void PageClientImpl::exitAcceleratedCompositingMode()
536 {
537     [m_wkView _setAcceleratedCompositingModeRootLayer:nil];
538 }
539
540 void PageClientImpl::updateAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext)
541 {
542     ASSERT(!layerTreeContext.isEmpty());
543
544     CALayer *renderLayer = WKMakeRenderLayer(layerTreeContext.contextID);
545     [m_wkView _setAcceleratedCompositingModeRootLayer:renderLayer];
546 }
547
548 void PageClientImpl::setAcceleratedCompositingRootLayer(CALayer *rootLayer)
549 {
550     [m_wkView _setAcceleratedCompositingModeRootLayer:rootLayer];
551 }
552
553 CALayer *PageClientImpl::acceleratedCompositingRootLayer() const
554 {
555     return m_wkView._acceleratedCompositingModeRootLayer;
556 }
557
558 PassRefPtr<ViewSnapshot> PageClientImpl::takeViewSnapshot()
559 {
560     return [m_wkView _takeViewSnapshot];
561 }
562
563 void PageClientImpl::selectionDidChange()
564 {
565     [m_wkView _selectionChanged];
566 }
567
568 void PageClientImpl::wheelEventWasNotHandledByWebCore(const NativeWebWheelEvent& event)
569 {
570     [m_wkView _wheelEventWasNotHandledByWebCore:event.nativeEvent()];
571 }
572
573 void PageClientImpl::pluginFocusOrWindowFocusChanged(uint64_t pluginComplexTextInputIdentifier, bool pluginHasFocusAndWindowHasFocus)
574 {
575     [m_wkView _pluginFocusOrWindowFocusChanged:pluginHasFocusAndWindowHasFocus pluginComplexTextInputIdentifier:pluginComplexTextInputIdentifier];
576 }
577
578 void PageClientImpl::setPluginComplexTextInputState(uint64_t pluginComplexTextInputIdentifier, PluginComplexTextInputState pluginComplexTextInputState)
579 {
580     [m_wkView _setPluginComplexTextInputState:pluginComplexTextInputState pluginComplexTextInputIdentifier:pluginComplexTextInputIdentifier];
581 }
582
583 void PageClientImpl::didPerformDictionaryLookup(const DictionaryPopupInfo& dictionaryPopupInfo)
584 {
585     if (!getLULookupDefinitionModuleClass())
586         return;
587
588     NSPoint textBaselineOrigin = dictionaryPopupInfo.origin;
589
590     // Convert to screen coordinates.
591     textBaselineOrigin = [m_wkView convertPoint:textBaselineOrigin toView:nil];
592     textBaselineOrigin = [m_wkView.window convertRectToScreen:NSMakeRect(textBaselineOrigin.x, textBaselineOrigin.y, 0, 0)].origin;
593
594     RetainPtr<NSMutableDictionary> mutableOptions = adoptNS([(NSDictionary *)dictionaryPopupInfo.options.get() mutableCopy]);
595
596     [m_wkView _prepareForDictionaryLookup];
597
598     if (canLoadLUTermOptionDisableSearchTermIndicator() && dictionaryPopupInfo.textIndicator.contentImage) {
599         [m_wkView _setTextIndicator:*TextIndicator::create(dictionaryPopupInfo.textIndicator) withLifetime:TextIndicatorLifetime::Permanent];
600         [mutableOptions setObject:@YES forKey:getLUTermOptionDisableSearchTermIndicator()];
601         [getLULookupDefinitionModuleClass() showDefinitionForTerm:dictionaryPopupInfo.attributedString.string.get() atLocation:textBaselineOrigin options:mutableOptions.get()];
602     } else
603         [getLULookupDefinitionModuleClass() showDefinitionForTerm:dictionaryPopupInfo.attributedString.string.get() atLocation:textBaselineOrigin options:mutableOptions.get()];
604 }
605
606 void PageClientImpl::dismissContentRelativeChildWindows(bool withAnimation)
607 {
608     [m_wkView _dismissContentRelativeChildWindowsWithAnimation:withAnimation];
609 }
610
611 void PageClientImpl::showCorrectionPanel(AlternativeTextType type, const FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings)
612 {
613 #if USE(AUTOCORRECTION_PANEL)
614     if (!isViewVisible() || !isViewInWindow())
615         return;
616     m_correctionPanel.show(m_wkView, type, boundingBoxOfReplacedString, replacedString, replacementString, alternativeReplacementStrings);
617 #endif
618 }
619
620 void PageClientImpl::dismissCorrectionPanel(ReasonForDismissingAlternativeText reason)
621 {
622 #if USE(AUTOCORRECTION_PANEL)
623     m_correctionPanel.dismiss(reason);
624 #endif
625 }
626
627 String PageClientImpl::dismissCorrectionPanelSoon(WebCore::ReasonForDismissingAlternativeText reason)
628 {
629 #if USE(AUTOCORRECTION_PANEL)
630     return m_correctionPanel.dismiss(reason);
631 #else
632     return String();
633 #endif
634 }
635
636 void PageClientImpl::recordAutocorrectionResponse(AutocorrectionResponseType responseType, const String& replacedString, const String& replacementString)
637 {
638     NSCorrectionResponse response = responseType == AutocorrectionReverted ? NSCorrectionResponseReverted : NSCorrectionResponseEdited;
639     CorrectionPanel::recordAutocorrectionResponse(m_wkView, response, replacedString, replacementString);
640 }
641
642 void PageClientImpl::recommendedScrollbarStyleDidChange(ScrollbarStyle newStyle)
643 {
644     // Now re-create a tracking area with the appropriate options given the new scrollbar style
645     NSTrackingAreaOptions options = NSTrackingMouseMoved | NSTrackingMouseEnteredAndExited | NSTrackingInVisibleRect | NSTrackingCursorUpdate;
646     if (newStyle == ScrollbarStyle::AlwaysVisible)
647         options |= NSTrackingActiveAlways;
648     else
649         options |= NSTrackingActiveInKeyWindow;
650
651     RetainPtr<NSTrackingArea> trackingArea = adoptNS([[NSTrackingArea alloc] initWithRect:[m_wkView frame] options:options owner:m_wkView userInfo:nil]);
652     [m_wkView _setPrimaryTrackingArea:trackingArea.get()];
653 }
654
655 void PageClientImpl::intrinsicContentSizeDidChange(const IntSize& intrinsicContentSize)
656 {
657     [m_wkView _setIntrinsicContentSize:intrinsicContentSize];
658 }
659
660 bool PageClientImpl::executeSavedCommandBySelector(const String& selectorString)
661 {
662     return [m_wkView _executeSavedCommandBySelector:NSSelectorFromString(selectorString)];
663 }
664
665 #if USE(DICTATION_ALTERNATIVES)
666 uint64_t PageClientImpl::addDictationAlternatives(const RetainPtr<NSTextAlternatives>& alternatives)
667 {
668     return m_alternativeTextUIController->addAlternatives(alternatives);
669 }
670
671 void PageClientImpl::removeDictationAlternatives(uint64_t dictationContext)
672 {
673     m_alternativeTextUIController->removeAlternatives(dictationContext);
674 }
675
676 void PageClientImpl::showDictationAlternativeUI(const WebCore::FloatRect& boundingBoxOfDictatedText, uint64_t dictationContext)
677 {
678     if (!isViewVisible() || !isViewInWindow())
679         return;
680     m_alternativeTextUIController->showAlternatives(m_wkView, boundingBoxOfDictatedText, dictationContext, ^(NSString* acceptedAlternative){
681         [m_wkView handleAcceptedAlternativeText:acceptedAlternative];
682     });
683 }
684
685 Vector<String> PageClientImpl::dictationAlternatives(uint64_t dictationContext)
686 {
687     return m_alternativeTextUIController->alternativesForContext(dictationContext);
688 }
689 #endif
690
691 #if ENABLE(FULLSCREEN_API)
692
693 WebFullScreenManagerProxyClient& PageClientImpl::fullScreenManagerProxyClient()
694 {
695     return *this;
696 }
697
698 // WebFullScreenManagerProxyClient
699
700 void PageClientImpl::closeFullScreenManager()
701 {
702     [m_wkView _closeFullScreenWindowController];
703 }
704
705 bool PageClientImpl::isFullScreen()
706 {
707     if (!m_wkView._hasFullScreenWindowController)
708         return false;
709
710     return m_wkView._fullScreenWindowController.isFullScreen;
711 }
712
713 void PageClientImpl::enterFullScreen()
714 {
715     [m_wkView._fullScreenWindowController enterFullScreen:nil];
716 }
717
718 void PageClientImpl::exitFullScreen()
719 {
720     [m_wkView._fullScreenWindowController exitFullScreen];
721 }
722
723 void PageClientImpl::beganEnterFullScreen(const IntRect& initialFrame, const IntRect& finalFrame)
724 {
725     [m_wkView._fullScreenWindowController beganEnterFullScreenWithInitialFrame:initialFrame finalFrame:finalFrame];
726 }
727
728 void PageClientImpl::beganExitFullScreen(const IntRect& initialFrame, const IntRect& finalFrame)
729 {
730     [m_wkView._fullScreenWindowController beganExitFullScreenWithInitialFrame:initialFrame finalFrame:finalFrame];
731 }
732
733 #endif // ENABLE(FULLSCREEN_API)
734
735 void PageClientImpl::navigationGestureDidBegin()
736 {
737     dismissContentRelativeChildWindows();
738
739 #if WK_API_ENABLED
740     if (m_webView)
741         NavigationState::fromWebPage(*m_webView->_page).navigationGestureDidBegin();
742 #endif
743 }
744
745 void PageClientImpl::navigationGestureWillEnd(bool willNavigate, WebBackForwardListItem& item)
746 {
747 #if WK_API_ENABLED
748     if (m_webView)
749         NavigationState::fromWebPage(*m_webView->_page).navigationGestureWillEnd(willNavigate, item);
750 #else
751     UNUSED_PARAM(willNavigate);
752     UNUSED_PARAM(item);
753 #endif
754 }
755
756 void PageClientImpl::navigationGestureDidEnd(bool willNavigate, WebBackForwardListItem& item)
757 {
758 #if WK_API_ENABLED
759     if (m_webView)
760         NavigationState::fromWebPage(*m_webView->_page).navigationGestureDidEnd(willNavigate, item);
761 #else
762     UNUSED_PARAM(willNavigate);
763     UNUSED_PARAM(item);
764 #endif
765 }
766
767 void PageClientImpl::willRecordNavigationSnapshot(WebBackForwardListItem& item)
768 {
769 #if WK_API_ENABLED
770     if (m_webView)
771         NavigationState::fromWebPage(*m_webView->_page).willRecordNavigationSnapshot(item);
772 #else
773     UNUSED_PARAM(item);
774 #endif
775 }
776
777 void PageClientImpl::didFirstVisuallyNonEmptyLayoutForMainFrame()
778 {
779     [m_wkView _didFirstVisuallyNonEmptyLayoutForMainFrame];
780 }
781
782 void PageClientImpl::didFinishLoadForMainFrame()
783 {
784     [m_wkView _didFinishLoadForMainFrame];
785 }
786
787 void PageClientImpl::didSameDocumentNavigationForMainFrame(SameDocumentNavigationType type)
788 {
789     [m_wkView _didSameDocumentNavigationForMainFrame:type];
790 }
791
792 void PageClientImpl::removeNavigationGestureSnapshot()
793 {
794     [m_wkView _removeNavigationGestureSnapshot];
795 }
796
797 void PageClientImpl::didChangeBackgroundColor()
798 {
799     notImplemented();
800 }
801
802 CGRect PageClientImpl::boundsOfLayerInLayerBackedWindowCoordinates(CALayer *layer) const
803 {
804     CALayer *windowContentLayer = static_cast<NSView *>(m_wkView.window.contentView).layer;
805     ASSERT(windowContentLayer);
806
807     return [windowContentLayer convertRect:layer.bounds fromLayer:layer];
808 }
809
810 void PageClientImpl::didPerformActionMenuHitTest(const WebHitTestResult::Data& result, bool forImmediateAction, bool contentPreventsDefault, API::Object* userData)
811 {
812 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
813     [m_wkView _didPerformActionMenuHitTest:result forImmediateAction:forImmediateAction contentPreventsDefault:contentPreventsDefault userData:userData];
814 #endif
815 }
816
817 void PageClientImpl::showPlatformContextMenu(NSMenu *menu, IntPoint location)
818 {
819     [menu popUpMenuPositioningItem:nil atLocation:location inView:m_wkView];
820 }
821
822 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
823 WebCore::WebMediaSessionManager& PageClientImpl::mediaSessionManager()
824 {
825     return WebMediaSessionManagerMac::singleton();
826 }
827 #endif
828
829 } // namespace WebKit
830
831 #endif // PLATFORM(MAC)