6482298f37b1396173de83b0ec2c955c142c8521
[WebKit-https.git] / Source / WebKit / UIProcess / API / gtk / PageClientImpl.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  * Portions Copyright (c) 2010 Motorola Mobility, Inc.  All rights reserved.
4  * Copyright (C) 2011 Igalia S.L.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
19  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
25  * THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include "config.h"
29 #include "PageClientImpl.h"
30
31 #include "DrawingAreaProxyCoordinatedGraphics.h"
32 #include "NativeWebKeyboardEvent.h"
33 #include "NativeWebMouseEvent.h"
34 #include "NativeWebWheelEvent.h"
35 #include "ViewSnapshotStore.h"
36 #include "WebColorPickerGtk.h"
37 #include "WebContextMenuProxyGtk.h"
38 #include "WebEventFactory.h"
39 #include "WebKitColorChooser.h"
40 #include "WebKitPopupMenu.h"
41 #include "WebKitWebViewBasePrivate.h"
42 #include "WebKitWebViewPrivate.h"
43 #include "WebPageProxy.h"
44 #include "WebProcessPool.h"
45 #include <WebCore/CairoUtilities.h>
46 #include <WebCore/Cursor.h>
47 #include <WebCore/DOMPasteAccess.h>
48 #include <WebCore/EventNames.h>
49 #include <WebCore/GtkUtilities.h>
50 #include <WebCore/NotImplemented.h>
51 #include <WebCore/RefPtrCairo.h>
52 #include <wtf/Compiler.h>
53 #include <wtf/text/CString.h>
54 #include <wtf/text/WTFString.h>
55
56 namespace WebKit {
57 using namespace WebCore;
58
59 PageClientImpl::PageClientImpl(GtkWidget* viewWidget)
60     : m_viewWidget(viewWidget)
61 {
62 }
63
64 // PageClient's pure virtual functions
65 std::unique_ptr<DrawingAreaProxy> PageClientImpl::createDrawingAreaProxy(WebProcessProxy& process)
66 {
67     return std::make_unique<DrawingAreaProxyCoordinatedGraphics>(*webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(m_viewWidget)), process);
68 }
69
70 void PageClientImpl::setViewNeedsDisplay(const WebCore::Region& region)
71 {
72     WebPageProxy* pageProxy = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
73     ASSERT(pageProxy);
74
75     // During the gesture, the page may be displayed with an offset.
76     // To avoid visual glitches, redraw the whole page.
77     if (pageProxy->isShowingNavigationGestureSnapshot()) {
78         gtk_widget_queue_draw(m_viewWidget);
79         return;
80     }
81
82     gtk_widget_queue_draw_region(m_viewWidget, toCairoRegion(region).get());
83 }
84
85 void PageClientImpl::requestScroll(const WebCore::FloatPoint&, const WebCore::IntPoint&)
86 {
87     notImplemented();
88 }
89
90 WebCore::FloatPoint PageClientImpl::viewScrollPosition()
91 {
92     return { };
93 }
94
95 WebCore::IntSize PageClientImpl::viewSize()
96 {
97     auto* drawingArea = static_cast<DrawingAreaProxyCoordinatedGraphics*>(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(m_viewWidget))->drawingArea());
98     return drawingArea ? drawingArea->size() : IntSize();
99 }
100
101 bool PageClientImpl::isViewWindowActive()
102 {
103     return webkitWebViewBaseIsInWindowActive(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
104 }
105
106 bool PageClientImpl::isViewFocused()
107 {
108     return webkitWebViewBaseIsFocused(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
109 }
110
111 bool PageClientImpl::isViewVisible()
112 {
113     return webkitWebViewBaseIsVisible(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
114 }
115
116 bool PageClientImpl::isViewInWindow()
117 {
118     return webkitWebViewBaseIsInWindow(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
119 }
120
121 void PageClientImpl::PageClientImpl::processWillSwap()
122 {
123     webkitWebViewBaseWillSwapWebProcess(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
124 }
125
126 void PageClientImpl::PageClientImpl::processDidExit()
127 {
128     webkitWebViewBaseDidExitWebProcess(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
129 }
130
131 void PageClientImpl::didRelaunchProcess()
132 {
133     webkitWebViewBaseDidRelaunchWebProcess(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
134 }
135
136 void PageClientImpl::toolTipChanged(const String&, const String& newToolTip)
137 {
138     webkitWebViewBaseSetTooltipText(WEBKIT_WEB_VIEW_BASE(m_viewWidget), newToolTip.utf8().data());
139 }
140
141 void PageClientImpl::setCursor(const WebCore::Cursor& cursor)
142 {
143     if (!gtk_widget_get_realized(m_viewWidget))
144         return;
145
146     // [GTK] Widget::setCursor() gets called frequently
147     // http://bugs.webkit.org/show_bug.cgi?id=16388
148     // Setting the cursor may be an expensive operation in some backends,
149     // so don't re-set the cursor if it's already set to the target value.
150     GdkWindow* window = gtk_widget_get_window(m_viewWidget);
151     GdkCursor* currentCursor = gdk_window_get_cursor(window);
152     GdkCursor* newCursor = cursor.platformCursor().get();
153     if (currentCursor != newCursor)
154         gdk_window_set_cursor(window, newCursor);
155 }
156
157 void PageClientImpl::setCursorHiddenUntilMouseMoves(bool /* hiddenUntilMouseMoves */)
158 {
159     notImplemented();
160 }
161
162 void PageClientImpl::didChangeViewportProperties(const WebCore::ViewportAttributes&)
163 {
164     notImplemented();
165 }
166
167 void PageClientImpl::registerEditCommand(Ref<WebEditCommandProxy>&& command, UndoOrRedo undoOrRedo)
168 {
169     m_undoController.registerEditCommand(WTFMove(command), undoOrRedo);
170 }
171
172 void PageClientImpl::clearAllEditCommands()
173 {
174     m_undoController.clearAllEditCommands();
175 }
176
177 bool PageClientImpl::canUndoRedo(UndoOrRedo undoOrRedo)
178 {
179     return m_undoController.canUndoRedo(undoOrRedo);
180 }
181
182 void PageClientImpl::executeUndoRedo(UndoOrRedo undoOrRedo)
183 {
184     m_undoController.executeUndoRedo(undoOrRedo);
185 }
186
187 FloatRect PageClientImpl::convertToDeviceSpace(const FloatRect& viewRect)
188 {
189     notImplemented();
190     return viewRect;
191 }
192
193 FloatRect PageClientImpl::convertToUserSpace(const FloatRect& viewRect)
194 {
195     notImplemented();
196     return viewRect;
197 }
198
199 IntPoint PageClientImpl::screenToRootView(const IntPoint& point)
200 {
201     IntPoint widgetPositionOnScreen = convertWidgetPointToScreenPoint(m_viewWidget, IntPoint());
202     IntPoint result(point);
203     result.move(-widgetPositionOnScreen.x(), -widgetPositionOnScreen.y());
204     return result;
205 }
206
207 IntRect PageClientImpl::rootViewToScreen(const IntRect& rect)
208 {
209     return IntRect(convertWidgetPointToScreenPoint(m_viewWidget, rect.location()), rect.size());
210 }
211
212 WebCore::IntPoint PageClientImpl::accessibilityScreenToRootView(const WebCore::IntPoint& point)
213 {
214     return screenToRootView(point);
215 }
216
217 WebCore::IntRect PageClientImpl::rootViewToAccessibilityScreen(const WebCore::IntRect& rect)    
218 {
219     return rootViewToScreen(rect);
220 }
221
222 void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool wasEventHandled)
223 {
224     if (wasEventHandled)
225         return;
226     if (event.isFakeEventForComposition())
227         return;
228
229     WebKitWebViewBase* webkitWebViewBase = WEBKIT_WEB_VIEW_BASE(m_viewWidget);
230     webkitWebViewBaseForwardNextKeyEvent(webkitWebViewBase);
231     gtk_main_do_event(event.nativeEvent());
232 }
233
234 RefPtr<WebPopupMenuProxy> PageClientImpl::createPopupMenuProxy(WebPageProxy& page)
235 {
236     if (WEBKIT_IS_WEB_VIEW(m_viewWidget))
237         return WebKitPopupMenu::create(m_viewWidget, page);
238     return WebPopupMenuProxyGtk::create(m_viewWidget, page);
239 }
240
241 Ref<WebContextMenuProxy> PageClientImpl::createContextMenuProxy(WebPageProxy& page, ContextMenuContextData&& context, const UserData& userData)
242 {
243     return WebContextMenuProxyGtk::create(m_viewWidget, page, WTFMove(context), userData);
244 }
245
246 RefPtr<WebColorPicker> PageClientImpl::createColorPicker(WebPageProxy* page, const WebCore::Color& color, const WebCore::IntRect& rect, Vector<WebCore::Color>&&)
247 {
248     if (WEBKIT_IS_WEB_VIEW(m_viewWidget))
249         return WebKitColorChooser::create(*page, color, rect);
250     return WebColorPickerGtk::create(*page, color, rect);
251 }
252
253 void PageClientImpl::enterAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext)
254 {
255     webkitWebViewBaseEnterAcceleratedCompositingMode(WEBKIT_WEB_VIEW_BASE(m_viewWidget), layerTreeContext);
256 }
257
258 void PageClientImpl::exitAcceleratedCompositingMode()
259 {
260     webkitWebViewBaseExitAcceleratedCompositingMode(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
261 }
262
263 void PageClientImpl::updateAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext)
264 {
265     webkitWebViewBaseUpdateAcceleratedCompositingMode(WEBKIT_WEB_VIEW_BASE(m_viewWidget), layerTreeContext);
266 }
267
268 void PageClientImpl::pageClosed()
269 {
270     webkitWebViewBasePageClosed(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
271 }
272
273 void PageClientImpl::preferencesDidChange()
274 {
275     notImplemented();
276 }
277
278 void PageClientImpl::selectionDidChange()
279 {
280     webkitWebViewBaseUpdateTextInputState(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
281     if (WEBKIT_IS_WEB_VIEW(m_viewWidget))
282         webkitWebViewSelectionDidChange(WEBKIT_WEB_VIEW(m_viewWidget));
283 }
284
285 RefPtr<ViewSnapshot> PageClientImpl::takeViewSnapshot()
286 {
287     return webkitWebViewBaseTakeViewSnapshot(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
288 }
289
290 void PageClientImpl::didChangeContentSize(const IntSize& size)
291 {
292     webkitWebViewBaseSetContentsSize(WEBKIT_WEB_VIEW_BASE(m_viewWidget), size);
293 }
294
295 #if ENABLE(DRAG_SUPPORT)
296 void PageClientImpl::startDrag(Ref<SelectionData>&& selection, DragOperation dragOperation, RefPtr<ShareableBitmap>&& dragImage)
297 {
298     WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(m_viewWidget);
299     webkitWebViewBaseDragAndDropHandler(webView).startDrag(WTFMove(selection), dragOperation, WTFMove(dragImage));
300
301     // A drag starting should prevent a double-click from happening. This might
302     // happen if a drag is followed very quickly by another click (like in the WTR).
303     webkitWebViewBaseResetClickCounter(webView);
304 }
305 #endif
306
307 void PageClientImpl::handleDownloadRequest(DownloadProxy& download)
308 {
309     if (WEBKIT_IS_WEB_VIEW(m_viewWidget))
310         webkitWebViewHandleDownloadRequest(WEBKIT_WEB_VIEW(m_viewWidget), &download);
311 }
312
313 void PageClientImpl::didCommitLoadForMainFrame(const String& /* mimeType */, bool /* useCustomContentProvider */ )
314 {
315     webkitWebViewBaseResetClickCounter(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
316 }
317
318 #if ENABLE(FULLSCREEN_API)
319 WebFullScreenManagerProxyClient& PageClientImpl::fullScreenManagerProxyClient()
320 {
321     return *this;
322 }
323
324 void PageClientImpl::closeFullScreenManager()
325 {
326     notImplemented();
327 }
328
329 bool PageClientImpl::isFullScreen()
330 {
331     return webkitWebViewBaseIsFullScreen(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
332 }
333
334 void PageClientImpl::enterFullScreen()
335 {
336     if (!m_viewWidget)
337         return;
338
339     if (isFullScreen())
340         return;
341
342     if (WEBKIT_IS_WEB_VIEW(m_viewWidget))
343         webkitWebViewEnterFullScreen(WEBKIT_WEB_VIEW(m_viewWidget));
344     else
345         webkitWebViewBaseEnterFullScreen(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
346 }
347
348 void PageClientImpl::exitFullScreen()
349 {
350     if (!m_viewWidget)
351         return;
352
353     if (!isFullScreen())
354         return;
355
356     if (WEBKIT_IS_WEB_VIEW(m_viewWidget))
357         webkitWebViewExitFullScreen(WEBKIT_WEB_VIEW(m_viewWidget));
358     else
359         webkitWebViewBaseExitFullScreen(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
360 }
361
362 void PageClientImpl::beganEnterFullScreen(const IntRect& /* initialFrame */, const IntRect& /* finalFrame */)
363 {
364     notImplemented();
365 }
366
367 void PageClientImpl::beganExitFullScreen(const IntRect& /* initialFrame */, const IntRect& /* finalFrame */)
368 {
369     notImplemented();
370 }
371
372 #endif // ENABLE(FULLSCREEN_API)
373
374 #if ENABLE(TOUCH_EVENTS)
375 void PageClientImpl::doneWithTouchEvent(const NativeWebTouchEvent& event, bool wasEventHandled)
376 {
377     const GdkEvent* touchEvent = event.nativeEvent();
378
379 #if HAVE(GTK_GESTURES)
380     GestureController& gestureController = webkitWebViewBaseGestureController(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
381     if (wasEventHandled) {
382         gestureController.reset();
383         return;
384     }
385     wasEventHandled = gestureController.handleEvent(const_cast<GdkEvent*>(event.nativeEvent()));
386 #endif
387
388     if (wasEventHandled)
389         return;
390
391     // Emulate pointer events if unhandled.
392     if (!touchEvent->touch.emulating_pointer)
393         return;
394
395     GUniquePtr<GdkEvent> pointerEvent;
396
397     if (touchEvent->type == GDK_TOUCH_UPDATE) {
398         pointerEvent.reset(gdk_event_new(GDK_MOTION_NOTIFY));
399         pointerEvent->motion.time = touchEvent->touch.time;
400         pointerEvent->motion.x = touchEvent->touch.x;
401         pointerEvent->motion.y = touchEvent->touch.y;
402         pointerEvent->motion.x_root = touchEvent->touch.x_root;
403         pointerEvent->motion.y_root = touchEvent->touch.y_root;
404         pointerEvent->motion.state = touchEvent->touch.state | GDK_BUTTON1_MASK;
405     } else {
406         switch (touchEvent->type) {
407         case GDK_TOUCH_CANCEL:
408             FALLTHROUGH;
409         case GDK_TOUCH_END:
410             pointerEvent.reset(gdk_event_new(GDK_BUTTON_RELEASE));
411             pointerEvent->button.state = touchEvent->touch.state | GDK_BUTTON1_MASK;
412             break;
413         case GDK_TOUCH_BEGIN:
414             pointerEvent.reset(gdk_event_new(GDK_BUTTON_PRESS));
415             break;
416         default:
417             ASSERT_NOT_REACHED();
418         }
419
420         pointerEvent->button.button = 1;
421         pointerEvent->button.time = touchEvent->touch.time;
422         pointerEvent->button.x = touchEvent->touch.x;
423         pointerEvent->button.y = touchEvent->touch.y;
424         pointerEvent->button.x_root = touchEvent->touch.x_root;
425         pointerEvent->button.y_root = touchEvent->touch.y_root;
426     }
427
428     gdk_event_set_device(pointerEvent.get(), gdk_event_get_device(touchEvent));
429     gdk_event_set_source_device(pointerEvent.get(), gdk_event_get_source_device(touchEvent));
430     pointerEvent->any.window = GDK_WINDOW(g_object_ref(touchEvent->any.window));
431     pointerEvent->any.send_event = TRUE;
432
433     gtk_widget_event(m_viewWidget, pointerEvent.get());
434 }
435 #endif // ENABLE(TOUCH_EVENTS)
436
437 void PageClientImpl::wheelEventWasNotHandledByWebCore(const NativeWebWheelEvent& event)
438 {
439     ViewGestureController* controller = webkitWebViewBaseViewGestureController(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
440     if (controller && controller->isSwipeGestureEnabled()) {
441         controller->wheelEventWasNotHandledByWebCore(&event.nativeEvent()->scroll);
442         return;
443     }
444
445     webkitWebViewBaseForwardNextWheelEvent(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
446     gtk_main_do_event(event.nativeEvent());
447 }
448
449 void PageClientImpl::didFinishLoadingDataForCustomContentProvider(const String&, const IPC::DataReference&)
450 {
451 }
452
453 void PageClientImpl::navigationGestureDidBegin()
454 {
455 }
456
457 void PageClientImpl::navigationGestureWillEnd(bool, WebBackForwardListItem&)
458 {
459 }
460
461 void PageClientImpl::navigationGestureDidEnd(bool, WebBackForwardListItem&)
462 {
463 }
464
465 void PageClientImpl::navigationGestureDidEnd()
466 {
467 }
468
469 void PageClientImpl::willRecordNavigationSnapshot(WebBackForwardListItem&)
470 {
471 }
472
473 void PageClientImpl::didRemoveNavigationGestureSnapshot()
474 {
475     gtk_widget_queue_draw(m_viewWidget);
476 }
477
478 void PageClientImpl::didStartProvisionalLoadForMainFrame()
479 {
480     if (WEBKIT_IS_WEB_VIEW(m_viewWidget))
481         webkitWebViewWillStartLoad(WEBKIT_WEB_VIEW(m_viewWidget));
482
483     webkitWebViewBaseDidStartProvisionalLoadForMainFrame(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
484 }
485
486 void PageClientImpl::didFirstVisuallyNonEmptyLayoutForMainFrame()
487 {
488     webkitWebViewBaseDidFirstVisuallyNonEmptyLayoutForMainFrame(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
489 }
490
491 void PageClientImpl::didFinishLoadForMainFrame()
492 {
493     webkitWebViewBaseDidFinishLoadForMainFrame(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
494 }
495
496 void PageClientImpl::didFailLoadForMainFrame()
497 {
498     webkitWebViewBaseDidFailLoadForMainFrame(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
499 }
500
501 void PageClientImpl::didSameDocumentNavigationForMainFrame(SameDocumentNavigationType type)
502 {
503     webkitWebViewBaseDidSameDocumentNavigationForMainFrame(WEBKIT_WEB_VIEW_BASE(m_viewWidget), type);
504 }
505
506 void PageClientImpl::didRestoreScrollPosition()
507 {
508     webkitWebViewBaseDidRestoreScrollPosition(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
509 }
510
511 void PageClientImpl::didChangeBackgroundColor()
512 {
513 }
514
515 void PageClientImpl::refView()
516 {
517     g_object_ref(m_viewWidget);
518 }
519
520 void PageClientImpl::derefView()
521 {
522     g_object_unref(m_viewWidget);
523 }
524
525 #if ENABLE(VIDEO) && USE(GSTREAMER)
526 bool PageClientImpl::decidePolicyForInstallMissingMediaPluginsPermissionRequest(InstallMissingMediaPluginsPermissionRequest& request)
527 {
528     if (!WEBKIT_IS_WEB_VIEW(m_viewWidget))
529         return false;
530
531     webkitWebViewRequestInstallMissingMediaPlugins(WEBKIT_WEB_VIEW(m_viewWidget), request);
532     return true;
533 }
534 #endif
535
536 void PageClientImpl::requestDOMPasteAccess(const IntRect&, const String&, CompletionHandler<void(WebCore::DOMPasteAccessResponse)>&& completionHandler)
537 {
538     completionHandler(WebCore::DOMPasteAccessResponse::DeniedForGesture);
539 }
540
541 UserInterfaceLayoutDirection PageClientImpl::userInterfaceLayoutDirection()
542 {
543     GtkTextDirection direction = gtk_widget_get_direction(m_viewWidget);
544     if (direction == GTK_TEXT_DIR_RTL)
545         return UserInterfaceLayoutDirection::RTL;
546
547     return UserInterfaceLayoutDirection::LTR;
548 }
549
550 bool PageClientImpl::effectiveAppearanceIsDark() const
551 {
552     auto* settings = gtk_widget_get_settings(m_viewWidget);
553     gboolean preferDarkTheme;
554     g_object_get(settings, "gtk-application-prefer-dark-theme", &preferDarkTheme, nullptr);
555     if (preferDarkTheme)
556         return true;
557
558     GUniqueOutPtr<char> themeName;
559     g_object_get(settings, "gtk-theme-name", &themeName.outPtr(), nullptr);
560     if (g_str_has_suffix(themeName.get(), "-dark"))
561         return true;
562
563     if (auto* themeNameEnv = g_getenv("GTK_THEME"))
564         return g_str_has_suffix(themeNameEnv, ":dark");
565
566     return false;
567 }
568
569 #if USE(WPE_RENDERER)
570 IPC::Attachment PageClientImpl::hostFileDescriptor()
571 {
572     return webkitWebViewBaseRenderHostFileDescriptor(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
573 }
574 #endif
575
576 } // namespace WebKit