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 "WebView.h"
30
31 #include "ChunkedUpdateDrawingAreaProxy.h"
32 #include "NativeWebKeyboardEvent.h"
33 #include "NativeWebMouseEvent.h"
34 #include "NotImplemented.h"
35 #include "WebContext.h"
36 #include "WebContextMenuProxy.h"
37 #include "WebEventFactory.h"
38 #include "WebViewWidget.h"
39 #include "WebPageProxy.h"
40 #include <wtf/text/WTFString.h>
41
42 typedef HashMap<int, const char*> IntConstCharHashMap;
43
44 using namespace WebCore;
45
46 namespace WebKit {
47
handleFocusInEvent(GtkWidget * widget)48 void WebView::handleFocusInEvent(GtkWidget* widget)
49 {
50 if (!(m_isPageActive)) {
51 m_isPageActive = true;
52 m_page->viewStateDidChange(WebPageProxy::ViewWindowIsActive);
53 }
54
55 m_page->viewStateDidChange(WebPageProxy::ViewIsFocused);
56 }
57
handleFocusOutEvent(GtkWidget * widget)58 void WebView::handleFocusOutEvent(GtkWidget* widget)
59 {
60 m_isPageActive = false;
61 m_page->viewStateDidChange(WebPageProxy::ViewWindowIsActive);
62 }
63
64
backspaceCallback(GtkWidget * widget,WebView * client)65 static void backspaceCallback(GtkWidget* widget, WebView* client)
66 {
67 g_signal_stop_emission_by_name(widget, "backspace");
68 client->addPendingEditorCommand("DeleteBackward");
69 }
70
selectAllCallback(GtkWidget * widget,gboolean select,WebView * client)71 static void selectAllCallback(GtkWidget* widget, gboolean select, WebView* client)
72 {
73 g_signal_stop_emission_by_name(widget, "select-all");
74 client->addPendingEditorCommand(select ? "SelectAll" : "Unselect");
75 }
76
cutClipboardCallback(GtkWidget * widget,WebView * client)77 static void cutClipboardCallback(GtkWidget* widget, WebView* client)
78 {
79 g_signal_stop_emission_by_name(widget, "cut-clipboard");
80 client->addPendingEditorCommand("Cut");
81 }
82
copyClipboardCallback(GtkWidget * widget,WebView * client)83 static void copyClipboardCallback(GtkWidget* widget, WebView* client)
84 {
85 g_signal_stop_emission_by_name(widget, "copy-clipboard");
86 client->addPendingEditorCommand("Copy");
87 }
88
pasteClipboardCallback(GtkWidget * widget,WebView * client)89 static void pasteClipboardCallback(GtkWidget* widget, WebView* client)
90 {
91 g_signal_stop_emission_by_name(widget, "paste-clipboard");
92 client->addPendingEditorCommand("Paste");
93 }
94
toggleOverwriteCallback(GtkWidget * widget,EditorClient *)95 static void toggleOverwriteCallback(GtkWidget* widget, EditorClient*)
96 {
97 // We don't support toggling the overwrite mode, but the default callback expects
98 // the GtkTextView to have a layout, so we handle this signal just to stop it.
99 g_signal_stop_emission_by_name(widget, "toggle-overwrite");
100 }
101
102 // GTK+ will still send these signals to the web view. So we can safely stop signal
103 // emission without breaking accessibility.
popupMenuCallback(GtkWidget * widget,EditorClient *)104 static void popupMenuCallback(GtkWidget* widget, EditorClient*)
105 {
106 g_signal_stop_emission_by_name(widget, "popup-menu");
107 }
108
showHelpCallback(GtkWidget * widget,EditorClient *)109 static void showHelpCallback(GtkWidget* widget, EditorClient*)
110 {
111 g_signal_stop_emission_by_name(widget, "show-help");
112 }
113
114 static const char* const gtkDeleteCommands[][2] = {
115 { "DeleteBackward", "DeleteForward" }, // Characters
116 { "DeleteWordBackward", "DeleteWordForward" }, // Word ends
117 { "DeleteWordBackward", "DeleteWordForward" }, // Words
118 { "DeleteToBeginningOfLine", "DeleteToEndOfLine" }, // Lines
119 { "DeleteToBeginningOfLine", "DeleteToEndOfLine" }, // Line ends
120 { "DeleteToBeginningOfParagraph", "DeleteToEndOfParagraph" }, // Paragraph ends
121 { "DeleteToBeginningOfParagraph", "DeleteToEndOfParagraph" }, // Paragraphs
122 { 0, 0 } // Whitespace (M-\ in Emacs)
123 };
124
deleteFromCursorCallback(GtkWidget * widget,GtkDeleteType deleteType,gint count,WebView * client)125 static void deleteFromCursorCallback(GtkWidget* widget, GtkDeleteType deleteType, gint count, WebView* client)
126 {
127 g_signal_stop_emission_by_name(widget, "delete-from-cursor");
128 int direction = count > 0 ? 1 : 0;
129
130 // Ensuring that deleteType <= G_N_ELEMENTS here results in a compiler warning
131 // that the condition is always true.
132
133 if (deleteType == GTK_DELETE_WORDS) {
134 if (!direction) {
135 client->addPendingEditorCommand("MoveWordForward");
136 client->addPendingEditorCommand("MoveWordBackward");
137 } else {
138 client->addPendingEditorCommand("MoveWordBackward");
139 client->addPendingEditorCommand("MoveWordForward");
140 }
141 } else if (deleteType == GTK_DELETE_DISPLAY_LINES) {
142 if (!direction)
143 client->addPendingEditorCommand("MoveToBeginningOfLine");
144 else
145 client->addPendingEditorCommand("MoveToEndOfLine");
146 } else if (deleteType == GTK_DELETE_PARAGRAPHS) {
147 if (!direction)
148 client->addPendingEditorCommand("MoveToBeginningOfParagraph");
149 else
150 client->addPendingEditorCommand("MoveToEndOfParagraph");
151 }
152
153 const char* rawCommand = gtkDeleteCommands[deleteType][direction];
154 if (!rawCommand)
155 return;
156
157 for (int i = 0; i < abs(count); i++)
158 client->addPendingEditorCommand(rawCommand);
159 }
160
161 static const char* const gtkMoveCommands[][4] = {
162 { "MoveBackward", "MoveForward",
163 "MoveBackwardAndModifySelection", "MoveForwardAndModifySelection" }, // Forward/backward grapheme
164 { "MoveLeft", "MoveRight",
165 "MoveBackwardAndModifySelection", "MoveForwardAndModifySelection" }, // Left/right grapheme
166 { "MoveWordBackward", "MoveWordForward",
167 "MoveWordBackwardAndModifySelection", "MoveWordForwardAndModifySelection" }, // Forward/backward word
168 { "MoveUp", "MoveDown",
169 "MoveUpAndModifySelection", "MoveDownAndModifySelection" }, // Up/down line
170 { "MoveToBeginningOfLine", "MoveToEndOfLine",
171 "MoveToBeginningOfLineAndModifySelection", "MoveToEndOfLineAndModifySelection" }, // Up/down line ends
172 { "MoveParagraphForward", "MoveParagraphBackward",
173 "MoveParagraphForwardAndModifySelection", "MoveParagraphBackwardAndModifySelection" }, // Up/down paragraphs
174 { "MoveToBeginningOfParagraph", "MoveToEndOfParagraph",
175 "MoveToBeginningOfParagraphAndModifySelection", "MoveToEndOfParagraphAndModifySelection" }, // Up/down paragraph ends.
176 { "MovePageUp", "MovePageDown",
177 "MovePageUpAndModifySelection", "MovePageDownAndModifySelection" }, // Up/down page
178 { "MoveToBeginningOfDocument", "MoveToEndOfDocument",
179 "MoveToBeginningOfDocumentAndModifySelection", "MoveToEndOfDocumentAndModifySelection" }, // Begin/end of buffer
180 { 0, 0,
181 0, 0 } // Horizontal page movement
182 };
183
moveCursorCallback(GtkWidget * widget,GtkMovementStep step,gint count,gboolean extendSelection,WebView * client)184 static void moveCursorCallback(GtkWidget* widget, GtkMovementStep step, gint count, gboolean extendSelection, WebView* client)
185 {
186 g_signal_stop_emission_by_name(widget, "move-cursor");
187 int direction = count > 0 ? 1 : 0;
188 if (extendSelection)
189 direction += 2;
190
191 if (static_cast<unsigned>(step) >= G_N_ELEMENTS(gtkMoveCommands))
192 return;
193
194 const char* rawCommand = gtkMoveCommands[step][direction];
195 if (!rawCommand)
196 return;
197
198 for (int i = 0; i < abs(count); i++)
199 client->addPendingEditorCommand(rawCommand);
200 }
201
202 static const unsigned CtrlKey = 1 << 0;
203 static const unsigned AltKey = 1 << 1;
204 static const unsigned ShiftKey = 1 << 2;
205
206 struct KeyDownEntry {
207 unsigned virtualKey;
208 unsigned modifiers;
209 const char* name;
210 };
211
212 struct KeyPressEntry {
213 unsigned charCode;
214 unsigned modifiers;
215 const char* name;
216 };
217
218 static const KeyDownEntry keyDownEntries[] = {
219 { 'B', CtrlKey, "ToggleBold" },
220 { 'I', CtrlKey, "ToggleItalic" },
221 { VK_ESCAPE, 0, "Cancel" },
222 { VK_OEM_PERIOD, CtrlKey, "Cancel" },
223 { VK_TAB, 0, "InsertTab" },
224 { VK_TAB, ShiftKey, "InsertBacktab" },
225 { VK_RETURN, 0, "InsertNewline" },
226 { VK_RETURN, CtrlKey, "InsertNewline" },
227 { VK_RETURN, AltKey, "InsertNewline" },
228 { VK_RETURN, AltKey | ShiftKey, "InsertNewline" },
229 };
230
231 static const KeyPressEntry keyPressEntries[] = {
232 { '\t', 0, "InsertTab" },
233 { '\t', ShiftKey, "InsertBacktab" },
234 { '\r', 0, "InsertNewline" },
235 { '\r', CtrlKey, "InsertNewline" },
236 { '\r', AltKey, "InsertNewline" },
237 { '\r', AltKey | ShiftKey, "InsertNewline" },
238 };
239
WebView(WebContext * context,WebPageGroup * pageGroup)240 WebView::WebView(WebContext* context, WebPageGroup* pageGroup)
241 : m_isPageActive(true)
242 , m_nativeWidget(gtk_text_view_new())
243 {
244 m_page = context->createWebPage(this, pageGroup);
245
246 m_viewWidget = static_cast<GtkWidget*>(g_object_new(WEB_VIEW_TYPE_WIDGET, NULL));
247 ASSERT(m_viewWidget);
248
249 m_page->initializeWebPage();
250
251 WebViewWidget* webViewWidget = WEB_VIEW_WIDGET(m_viewWidget);
252 webViewWidgetSetWebViewInstance(webViewWidget, this);
253
254 g_signal_connect(m_nativeWidget.get(), "backspace", G_CALLBACK(backspaceCallback), this);
255 g_signal_connect(m_nativeWidget.get(), "cut-clipboard", G_CALLBACK(cutClipboardCallback), this);
256 g_signal_connect(m_nativeWidget.get(), "copy-clipboard", G_CALLBACK(copyClipboardCallback), this);
257 g_signal_connect(m_nativeWidget.get(), "paste-clipboard", G_CALLBACK(pasteClipboardCallback), this);
258 g_signal_connect(m_nativeWidget.get(), "select-all", G_CALLBACK(selectAllCallback), this);
259 g_signal_connect(m_nativeWidget.get(), "move-cursor", G_CALLBACK(moveCursorCallback), this);
260 g_signal_connect(m_nativeWidget.get(), "delete-from-cursor", G_CALLBACK(deleteFromCursorCallback), this);
261 g_signal_connect(m_nativeWidget.get(), "toggle-overwrite", G_CALLBACK(toggleOverwriteCallback), this);
262 g_signal_connect(m_nativeWidget.get(), "popup-menu", G_CALLBACK(popupMenuCallback), this);
263 g_signal_connect(m_nativeWidget.get(), "show-help", G_CALLBACK(showHelpCallback), this);
264 }
265
~WebView()266 WebView::~WebView()
267 {
268 }
269
getWebViewWindow()270 GdkWindow* WebView::getWebViewWindow()
271 {
272 return gtk_widget_get_window(m_viewWidget);
273 }
274
paint(GtkWidget * widget,GdkRectangle rect,cairo_t * cr)275 void WebView::paint(GtkWidget* widget, GdkRectangle rect, cairo_t* cr)
276 {
277 m_page->drawingArea()->paint(IntRect(rect), cr);
278 }
279
setSize(GtkWidget *,IntSize windowSize)280 void WebView::setSize(GtkWidget*, IntSize windowSize)
281 {
282 m_page->drawingArea()->setSize(windowSize, IntSize());
283 }
284
handleKeyboardEvent(GdkEventKey * event)285 void WebView::handleKeyboardEvent(GdkEventKey* event)
286 {
287 m_page->handleKeyboardEvent(NativeWebKeyboardEvent(reinterpret_cast<GdkEvent*>(event)));
288 }
289
handleMouseEvent(GdkEvent * event,int currentClickCount)290 void WebView::handleMouseEvent(GdkEvent* event, int currentClickCount)
291 {
292 m_page->handleMouseEvent(NativeWebMouseEvent(event, currentClickCount));
293 }
294
handleWheelEvent(GdkEventScroll * event)295 void WebView::handleWheelEvent(GdkEventScroll* event)
296 {
297 m_page->handleWheelEvent(WebEventFactory::createWebWheelEvent(event));
298 }
299
getEditorCommandsForKeyEvent(const NativeWebKeyboardEvent & event,Vector<WTF::String> & commandList)300 void WebView::getEditorCommandsForKeyEvent(const NativeWebKeyboardEvent& event, Vector<WTF::String>& commandList)
301 {
302 m_pendingEditorCommands.clear();
303
304 #ifdef GTK_API_VERSION_2
305 gtk_bindings_activate_event(GTK_OBJECT(m_nativeWidget.get()), const_cast<GdkEventKey*>(&event.nativeEvent()->key));
306 #else
307 gtk_bindings_activate_event(G_OBJECT(m_nativeWidget.get()), const_cast<GdkEventKey*>(&event.nativeEvent()->key));
308 #endif
309
310 if (m_pendingEditorCommands.isEmpty()) {
311 commandList.append(m_pendingEditorCommands);
312 return;
313 }
314
315 DEFINE_STATIC_LOCAL(IntConstCharHashMap, keyDownCommandsMap, ());
316 DEFINE_STATIC_LOCAL(IntConstCharHashMap, keyPressCommandsMap, ());
317
318 if (keyDownCommandsMap.isEmpty()) {
319 for (unsigned i = 0; i < G_N_ELEMENTS(keyDownEntries); i++)
320 keyDownCommandsMap.set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name);
321
322 for (unsigned i = 0; i < G_N_ELEMENTS(keyPressEntries); i++)
323 keyPressCommandsMap.set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name);
324 }
325
326 unsigned modifiers = 0;
327 if (event.shiftKey())
328 modifiers |= ShiftKey;
329 if (event.altKey())
330 modifiers |= AltKey;
331 if (event.controlKey())
332 modifiers |= CtrlKey;
333
334 // For keypress events, we want charCode(), but keyCode() does that.
335 int mapKey = modifiers << 16 | event.nativeVirtualKeyCode();
336 if (mapKey) {
337 HashMap<int, const char*>* commandMap = event.type() == WebEvent::KeyDown ?
338 &keyDownCommandsMap : &keyPressCommandsMap;
339 if (const char* commandString = commandMap->get(mapKey))
340 m_pendingEditorCommands.append(commandString);
341 }
342
343 commandList.append(m_pendingEditorCommands);
344 }
345
isActive()346 bool WebView::isActive()
347 {
348 return m_isPageActive;
349 }
350
close()351 void WebView::close()
352 {
353 m_page->close();
354 }
355
356 // PageClient's pure virtual functions
createDrawingAreaProxy()357 PassOwnPtr<DrawingAreaProxy> WebView::createDrawingAreaProxy()
358 {
359 return ChunkedUpdateDrawingAreaProxy::create(this, m_page.get());
360 }
361
setViewNeedsDisplay(const WebCore::IntRect &)362 void WebView::setViewNeedsDisplay(const WebCore::IntRect&)
363 {
364 notImplemented();
365 }
366
displayView()367 void WebView::displayView()
368 {
369 notImplemented();
370 }
371
scrollView(const WebCore::IntRect & scrollRect,const WebCore::IntSize & scrollOffset)372 void WebView::scrollView(const WebCore::IntRect& scrollRect, const WebCore::IntSize& scrollOffset)
373 {
374 notImplemented();
375 }
376
viewSize()377 WebCore::IntSize WebView::viewSize()
378 {
379 GtkAllocation allocation;
380 gtk_widget_get_allocation(m_viewWidget, &allocation);
381 return IntSize(allocation.width, allocation.height);
382 }
383
isViewWindowActive()384 bool WebView::isViewWindowActive()
385 {
386 notImplemented();
387 return true;
388 }
389
isViewFocused()390 bool WebView::isViewFocused()
391 {
392 notImplemented();
393 return true;
394 }
395
isViewVisible()396 bool WebView::isViewVisible()
397 {
398 notImplemented();
399 return true;
400 }
401
isViewInWindow()402 bool WebView::isViewInWindow()
403 {
404 notImplemented();
405 return true;
406 }
407
processDidCrash()408 void WebView::WebView::processDidCrash()
409 {
410 notImplemented();
411 }
412
didRelaunchProcess()413 void WebView::didRelaunchProcess()
414 {
415 notImplemented();
416 }
417
takeFocus(bool)418 void WebView::takeFocus(bool)
419 {
420 notImplemented();
421 }
422
toolTipChanged(const String &,const String &)423 void WebView::toolTipChanged(const String&, const String&)
424 {
425 notImplemented();
426 }
427
setCursor(const Cursor & cursor)428 void WebView::setCursor(const Cursor& cursor)
429 {
430 // [GTK] Widget::setCursor() gets called frequently
431 // http://bugs.webkit.org/show_bug.cgi?id=16388
432 // Setting the cursor may be an expensive operation in some backends,
433 // so don't re-set the cursor if it's already set to the target value.
434 GdkWindow* window = gtk_widget_get_window(m_viewWidget);
435 GdkCursor* currentCursor = gdk_window_get_cursor(window);
436 GdkCursor* newCursor = cursor.platformCursor().get();
437 if (currentCursor != newCursor)
438 gdk_window_set_cursor(window, newCursor);
439 }
440
setViewportArguments(const WebCore::ViewportArguments &)441 void WebView::setViewportArguments(const WebCore::ViewportArguments&)
442 {
443 notImplemented();
444 }
445
registerEditCommand(PassRefPtr<WebEditCommandProxy>,WebPageProxy::UndoOrRedo)446 void WebView::registerEditCommand(PassRefPtr<WebEditCommandProxy>, WebPageProxy::UndoOrRedo)
447 {
448 notImplemented();
449 }
450
clearAllEditCommands()451 void WebView::clearAllEditCommands()
452 {
453 notImplemented();
454 }
455
canUndoRedo(WebPageProxy::UndoOrRedo)456 bool WebView::canUndoRedo(WebPageProxy::UndoOrRedo)
457 {
458 notImplemented();
459 return false;
460 }
461
executeUndoRedo(WebPageProxy::UndoOrRedo)462 void WebView::executeUndoRedo(WebPageProxy::UndoOrRedo)
463 {
464 notImplemented();
465 }
466
convertToDeviceSpace(const FloatRect & viewRect)467 FloatRect WebView::convertToDeviceSpace(const FloatRect& viewRect)
468 {
469 notImplemented();
470 return viewRect;
471 }
472
convertToUserSpace(const FloatRect & viewRect)473 FloatRect WebView::convertToUserSpace(const FloatRect& viewRect)
474 {
475 notImplemented();
476 return viewRect;
477 }
478
windowToScreen(const IntRect & rect)479 IntRect WebView::windowToScreen(const IntRect& rect)
480 {
481 notImplemented();
482 return IntRect();
483 }
484
doneWithKeyEvent(const NativeWebKeyboardEvent &,bool wasEventHandled)485 void WebView::doneWithKeyEvent(const NativeWebKeyboardEvent&, bool wasEventHandled)
486 {
487 notImplemented();
488 }
489
didNotHandleKeyEvent(const NativeWebKeyboardEvent & event)490 void WebView::didNotHandleKeyEvent(const NativeWebKeyboardEvent& event)
491 {
492 notImplemented();
493 }
494
createPopupMenuProxy(WebPageProxy *)495 PassRefPtr<WebPopupMenuProxy> WebView::createPopupMenuProxy(WebPageProxy*)
496 {
497 notImplemented();
498 return 0;
499 }
500
createContextMenuProxy(WebPageProxy *)501 PassRefPtr<WebContextMenuProxy> WebView::createContextMenuProxy(WebPageProxy*)
502 {
503 notImplemented();
504 return 0;
505 }
506
setFindIndicator(PassRefPtr<FindIndicator>,bool fadeOut)507 void WebView::setFindIndicator(PassRefPtr<FindIndicator>, bool fadeOut)
508 {
509 notImplemented();
510 }
511
512 #if USE(ACCELERATED_COMPOSITING)
pageDidEnterAcceleratedCompositing()513 void WebView::pageDidEnterAcceleratedCompositing()
514 {
515 notImplemented();
516 }
517
pageDidLeaveAcceleratedCompositing()518 void WebView::pageDidLeaveAcceleratedCompositing()
519 {
520 notImplemented();
521 }
522 #endif // USE(ACCELERATED_COMPOSITING)
523
didCommitLoadForMainFrame(bool useCustomRepresentation)524 void WebView::didCommitLoadForMainFrame(bool useCustomRepresentation)
525 {
526 }
527
didFinishLoadingDataForCustomRepresentation(const String & suggestedFilename,const CoreIPC::DataReference &)528 void WebView::didFinishLoadingDataForCustomRepresentation(const String& suggestedFilename, const CoreIPC::DataReference&)
529 {
530 }
531
customRepresentationZoomFactor()532 double WebView::customRepresentationZoomFactor()
533 {
534 notImplemented();
535 return 0;
536 }
537
setCustomRepresentationZoomFactor(double)538 void WebView::setCustomRepresentationZoomFactor(double)
539 {
540 notImplemented();
541 }
542
pageClosed()543 void WebView::pageClosed()
544 {
545 notImplemented();
546 }
547
didChangeScrollbarsForMainFrame() const548 void WebView::didChangeScrollbarsForMainFrame() const
549 {
550 }
551
flashBackingStoreUpdates(const Vector<IntRect> &)552 void WebView::flashBackingStoreUpdates(const Vector<IntRect>&)
553 {
554 notImplemented();
555 }
556
findStringInCustomRepresentation(const String &,FindOptions,unsigned)557 void WebView::findStringInCustomRepresentation(const String&, FindOptions, unsigned)
558 {
559 notImplemented();
560 }
561
countStringMatchesInCustomRepresentation(const String &,FindOptions,unsigned)562 void WebView::countStringMatchesInCustomRepresentation(const String&, FindOptions, unsigned)
563 {
564 notImplemented();
565 }
566
567 } // namespace WebKit
568