OSDN Git Service

Merge WebKit at r84325: Initial merge by git.
[android-x86/external-webkit.git] / Source / WebKit / chromium / src / WebViewImpl.cpp
1 /*
2  * Copyright (C) 2010 Google 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 are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32 #include "WebViewImpl.h"
33
34 #include "AutoFillPopupMenuClient.h"
35 #include "AXObjectCache.h"
36 #include "BackForwardListChromium.h"
37 #include "CSSStyleSelector.h"
38 #include "CSSValueKeywords.h"
39 #include "Chrome.h"
40 #include "ColorSpace.h"
41 #include "CompositionUnderlineVectorBuilder.h"
42 #include "ContextMenu.h"
43 #include "ContextMenuController.h"
44 #include "ContextMenuItem.h"
45 #include "Cursor.h"
46 #include "DOMUtilitiesPrivate.h"
47 #include "DeviceOrientationClientProxy.h"
48 #include "Document.h"
49 #include "DocumentLoader.h"
50 #include "DragController.h"
51 #include "DragData.h"
52 #include "DragScrollTimer.h"
53 #include "Editor.h"
54 #include "EventHandler.h"
55 #include "Extensions3D.h"
56 #include "FocusController.h"
57 #include "FontDescription.h"
58 #include "FrameLoader.h"
59 #include "FrameTree.h"
60 #include "FrameView.h"
61 #include "GeolocationClientProxy.h"
62 #include "GraphicsContext.h"
63 #include "GraphicsContext3D.h"
64 #include "GraphicsContext3DInternal.h"
65 #include "HTMLInputElement.h"
66 #include "HTMLMediaElement.h"
67 #include "HTMLNames.h"
68 #include "HitTestResult.h"
69 #include "Image.h"
70 #include "ImageBuffer.h"
71 #include "InspectorController.h"
72 #include "KeyboardCodes.h"
73 #include "KeyboardEvent.h"
74 #include "MIMETypeRegistry.h"
75 #include "NodeRenderStyle.h"
76 #include "Page.h"
77 #include "PageGroup.h"
78 #include "PageGroupLoadDeferrer.h"
79 #include "Pasteboard.h"
80 #include "PlatformContextSkia.h"
81 #include "PlatformKeyboardEvent.h"
82 #include "PlatformMouseEvent.h"
83 #include "PlatformThemeChromiumGtk.h"
84 #include "PlatformWheelEvent.h"
85 #include "PopupMenuChromium.h"
86 #include "PopupMenuClient.h"
87 #include "ProgressTracker.h"
88 #include "RenderView.h"
89 #include "ResourceHandle.h"
90 #include "SecurityOrigin.h"
91 #include "SelectionController.h"
92 #include "Settings.h"
93 #include "SpeechInputClientImpl.h"
94 #include "Timer.h"
95 #include "TraceEvent.h"
96 #include "TypingCommand.h"
97 #include "UserGestureIndicator.h"
98 #include "Vector.h"
99 #include "WebAccessibilityObject.h"
100 #include "WebAutoFillClient.h"
101 #include "WebDevToolsAgentImpl.h"
102 #include "WebDevToolsAgentPrivate.h"
103 #include "WebDragData.h"
104 #include "WebFrameImpl.h"
105 #include "WebGraphicsContext3D.h"
106 #include "WebImage.h"
107 #include "WebInputElement.h"
108 #include "WebInputEvent.h"
109 #include "WebInputEventConversion.h"
110 #include "WebKit.h"
111 #include "WebKitClient.h"
112 #include "WebMediaPlayerAction.h"
113 #include "WebNode.h"
114 #include "WebPlugin.h"
115 #include "WebPluginContainerImpl.h"
116 #include "WebPoint.h"
117 #include "WebPopupMenuImpl.h"
118 #include "WebRect.h"
119 #include "WebRuntimeFeatures.h"
120 #include "WebSettingsImpl.h"
121 #include "WebString.h"
122 #include "WebVector.h"
123 #include "WebViewClient.h"
124 #include "cc/CCHeadsUpDisplay.h"
125 #include <wtf/ByteArray.h>
126 #include <wtf/CurrentTime.h>
127 #include <wtf/RefPtr.h>
128
129 #if USE(CG)
130 #include <CoreGraphics/CGBitmapContext.h>
131 #include <CoreGraphics/CGContext.h>
132 #endif
133
134 #if OS(WINDOWS)
135 #include "RenderThemeChromiumWin.h"
136 #else
137 #if OS(LINUX) || OS(FREEBSD)
138 #include "RenderThemeChromiumLinux.h"
139 #endif
140 #include "RenderTheme.h"
141 #endif
142
143 // Get rid of WTF's pow define so we can use std::pow.
144 #undef pow
145 #include <cmath> // for std::pow
146
147 using namespace WebCore;
148
149 namespace {
150
151 GraphicsContext3D::Attributes getCompositorContextAttributes()
152 {
153     // Explicitly disable antialiasing for the compositor. As of the time of
154     // this writing, the only platform that supported antialiasing for the
155     // compositor was Mac OS X, because the on-screen OpenGL context creation
156     // code paths on Windows and Linux didn't yet have multisampling support.
157     // Mac OS X essentially always behaves as though it's rendering offscreen.
158     // Multisampling has a heavy cost especially on devices with relatively low
159     // fill rate like most notebooks, and the Mac implementation would need to
160     // be optimized to resolve directly into the IOSurface shared between the
161     // GPU and browser processes. For these reasons and to avoid platform
162     // disparities we explicitly disable antialiasing.
163     GraphicsContext3D::Attributes attributes;
164     attributes.antialias = false;
165     return attributes;
166 }
167
168 } // anonymous namespace
169
170 namespace WebKit {
171
172 // Change the text zoom level by kTextSizeMultiplierRatio each time the user
173 // zooms text in or out (ie., change by 20%).  The min and max values limit
174 // text zoom to half and 3x the original text size.  These three values match
175 // those in Apple's port in WebKit/WebKit/WebView/WebView.mm
176 const double WebView::textSizeMultiplierRatio = 1.2;
177 const double WebView::minTextSizeMultiplier = 0.5;
178 const double WebView::maxTextSizeMultiplier = 3.0;
179
180
181 // The group name identifies a namespace of pages.  Page group is used on OSX
182 // for some programs that use HTML views to display things that don't seem like
183 // web pages to the user (so shouldn't have visited link coloring).  We only use
184 // one page group.
185 const char* pageGroupName = "default";
186
187 // Used to defer all page activity in cases where the embedder wishes to run
188 // a nested event loop. Using a stack enables nesting of message loop invocations.
189 static Vector<PageGroupLoadDeferrer*> pageGroupLoadDeferrerStack;
190
191 // Ensure that the WebDragOperation enum values stay in sync with the original
192 // DragOperation constants.
193 #define COMPILE_ASSERT_MATCHING_ENUM(coreName) \
194     COMPILE_ASSERT(int(coreName) == int(Web##coreName), dummy##coreName)
195 COMPILE_ASSERT_MATCHING_ENUM(DragOperationNone);
196 COMPILE_ASSERT_MATCHING_ENUM(DragOperationCopy);
197 COMPILE_ASSERT_MATCHING_ENUM(DragOperationLink);
198 COMPILE_ASSERT_MATCHING_ENUM(DragOperationGeneric);
199 COMPILE_ASSERT_MATCHING_ENUM(DragOperationPrivate);
200 COMPILE_ASSERT_MATCHING_ENUM(DragOperationMove);
201 COMPILE_ASSERT_MATCHING_ENUM(DragOperationDelete);
202 COMPILE_ASSERT_MATCHING_ENUM(DragOperationEvery);
203
204 static const PopupContainerSettings autoFillPopupSettings = {
205     false, // setTextOnIndexChange
206     false, // acceptOnAbandon
207     true, // loopSelectionNavigation
208     false // restrictWidthOfListBox (For security reasons show the entire entry
209           // so the user doesn't enter information he did not intend to.)
210 };
211
212 static bool shouldUseExternalPopupMenus = false;
213
214 // WebView ----------------------------------------------------------------
215
216 WebView* WebView::create(WebViewClient* client)
217 {
218     // Keep runtime flag for device motion turned off until it's implemented.
219     WebRuntimeFeatures::enableDeviceMotion(false);
220
221     // Pass the WebViewImpl's self-reference to the caller.
222     return adoptRef(new WebViewImpl(client)).leakRef();
223 }
224
225 void WebView::setUseExternalPopupMenus(bool useExternalPopupMenus)
226 {
227     shouldUseExternalPopupMenus = useExternalPopupMenus;
228 }
229
230 void WebView::updateVisitedLinkState(unsigned long long linkHash)
231 {
232     Page::visitedStateChanged(PageGroup::pageGroup(pageGroupName), linkHash);
233 }
234
235 void WebView::resetVisitedLinkState()
236 {
237     Page::allVisitedStateChanged(PageGroup::pageGroup(pageGroupName));
238 }
239
240 void WebView::willEnterModalLoop()
241 {
242     PageGroup* pageGroup = PageGroup::pageGroup(pageGroupName);
243     ASSERT(pageGroup);
244
245     if (pageGroup->pages().isEmpty())
246         pageGroupLoadDeferrerStack.append(static_cast<PageGroupLoadDeferrer*>(0));
247     else {
248         // Pick any page in the page group since we are deferring all pages.
249         pageGroupLoadDeferrerStack.append(new PageGroupLoadDeferrer(*pageGroup->pages().begin(), true));
250     }
251 }
252
253 void WebView::didExitModalLoop()
254 {
255     ASSERT(pageGroupLoadDeferrerStack.size());
256
257     delete pageGroupLoadDeferrerStack.last();
258     pageGroupLoadDeferrerStack.removeLast();
259 }
260
261 void WebViewImpl::initializeMainFrame(WebFrameClient* frameClient)
262 {
263     // NOTE: The WebFrameImpl takes a reference to itself within InitMainFrame
264     // and releases that reference once the corresponding Frame is destroyed.
265     RefPtr<WebFrameImpl> frame = WebFrameImpl::create(frameClient);
266
267     frame->initializeAsMainFrame(this);
268
269     // Restrict the access to the local file system
270     // (see WebView.mm WebView::_commonInitializationWithFrameName).
271     SecurityOrigin::setLocalLoadPolicy(SecurityOrigin::AllowLocalLoadsForLocalOnly);
272 }
273
274 void WebViewImpl::setDevToolsAgentClient(WebDevToolsAgentClient* devToolsClient) 
275 {
276     if (devToolsClient)
277         m_devToolsAgent = new WebDevToolsAgentImpl(this, devToolsClient);
278     else
279         m_devToolsAgent.clear();
280 }
281
282 void WebViewImpl::setAutoFillClient(WebAutoFillClient* autoFillClient)
283 {
284     m_autoFillClient = autoFillClient;
285 }
286
287 void WebViewImpl::setSpellCheckClient(WebSpellCheckClient* spellCheckClient)
288 {
289     m_spellCheckClient = spellCheckClient;
290 }
291
292 WebViewImpl::WebViewImpl(WebViewClient* client)
293     : m_client(client)
294     , m_autoFillClient(0)
295     , m_spellCheckClient(0)
296     , m_chromeClientImpl(this)
297     , m_contextMenuClientImpl(this)
298     , m_dragClientImpl(this)
299     , m_editorClientImpl(this)
300     , m_inspectorClientImpl(this)
301     , m_observedNewNavigation(false)
302 #ifndef NDEBUG
303     , m_newNavigationLoader(0)
304 #endif
305     , m_zoomLevel(0)
306     , m_minimumZoomLevel(zoomFactorToZoomLevel(minTextSizeMultiplier))
307     , m_maximumZoomLevel(zoomFactorToZoomLevel(maxTextSizeMultiplier))
308     , m_contextMenuAllowed(false)
309     , m_doingDragAndDrop(false)
310     , m_ignoreInputEvents(false)
311     , m_suppressNextKeypressEvent(false)
312     , m_initialNavigationPolicy(WebNavigationPolicyIgnore)
313     , m_imeAcceptEvents(true)
314     , m_operationsAllowed(WebDragOperationNone)
315     , m_dragOperation(WebDragOperationNone)
316     , m_autoFillPopupShowing(false)
317     , m_autoFillPopupClient(0)
318     , m_autoFillPopup(0)
319     , m_isTransparent(false)
320     , m_tabsToLinks(false)
321     , m_dragScrollTimer(new DragScrollTimer())
322 #if USE(ACCELERATED_COMPOSITING)
323     , m_layerRenderer(0)
324     , m_isAcceleratedCompositingActive(false)
325     , m_compositorCreationFailed(false)
326     , m_recreatingGraphicsContext(false)
327 #endif
328 #if ENABLE(INPUT_SPEECH)
329     , m_speechInputClient(SpeechInputClientImpl::create(client))
330 #endif
331     , m_deviceOrientationClientProxy(new DeviceOrientationClientProxy(client ? client->deviceOrientationClient() : 0))
332     , m_geolocationClientProxy(new GeolocationClientProxy(client ? client->geolocationClient() : 0))
333 {
334     // WebKit/win/WebView.cpp does the same thing, except they call the
335     // KJS specific wrapper around this method. We need to have threading
336     // initialized because CollatorICU requires it.
337     WTF::initializeThreading();
338     WTF::initializeMainThread();
339
340     // set to impossible point so we always get the first mouse pos
341     m_lastMousePosition = WebPoint(-1, -1);
342
343     Page::PageClients pageClients;
344     pageClients.chromeClient = &m_chromeClientImpl;
345     pageClients.contextMenuClient = &m_contextMenuClientImpl;
346     pageClients.editorClient = &m_editorClientImpl;
347     pageClients.dragClient = &m_dragClientImpl;
348     pageClients.inspectorClient = &m_inspectorClientImpl;
349 #if ENABLE(INPUT_SPEECH)
350     pageClients.speechInputClient = m_speechInputClient.get();
351 #endif
352     pageClients.deviceOrientationClient = m_deviceOrientationClientProxy.get();
353     pageClients.geolocationClient = m_geolocationClientProxy.get();
354     pageClients.backForwardClient = BackForwardListChromium::create(this);
355
356     m_page.set(new Page(pageClients));
357
358     m_geolocationClientProxy->setController(m_page->geolocationController());
359
360     m_page->setGroupName(pageGroupName);
361
362     m_inspectorSettingsMap.set(new SettingsMap);
363 }
364
365 WebViewImpl::~WebViewImpl()
366 {
367     ASSERT(!m_page);
368 }
369
370 RenderTheme* WebViewImpl::theme() const
371 {
372     return m_page.get() ? m_page->theme() : RenderTheme::defaultTheme().get();
373 }
374
375 WebFrameImpl* WebViewImpl::mainFrameImpl()
376 {
377     return m_page.get() ? WebFrameImpl::fromFrame(m_page->mainFrame()) : 0;
378 }
379
380 bool WebViewImpl::tabKeyCyclesThroughElements() const
381 {
382     ASSERT(m_page.get());
383     return m_page->tabKeyCyclesThroughElements();
384 }
385
386 void WebViewImpl::setTabKeyCyclesThroughElements(bool value)
387 {
388     if (m_page)
389         m_page->setTabKeyCyclesThroughElements(value);
390 }
391
392 void WebViewImpl::mouseMove(const WebMouseEvent& event)
393 {
394     if (!mainFrameImpl() || !mainFrameImpl()->frameView())
395         return;
396
397     m_lastMousePosition = WebPoint(event.x, event.y);
398
399     // We call mouseMoved here instead of handleMouseMovedEvent because we need
400     // our ChromeClientImpl to receive changes to the mouse position and
401     // tooltip text, and mouseMoved handles all of that.
402     mainFrameImpl()->frame()->eventHandler()->mouseMoved(
403         PlatformMouseEventBuilder(mainFrameImpl()->frameView(), event));
404 }
405
406 void WebViewImpl::mouseLeave(const WebMouseEvent& event)
407 {
408     // This event gets sent as the main frame is closing.  In that case, just
409     // ignore it.
410     if (!mainFrameImpl() || !mainFrameImpl()->frameView())
411         return;
412
413     m_client->setMouseOverURL(WebURL());
414
415     mainFrameImpl()->frame()->eventHandler()->handleMouseMoveEvent(
416         PlatformMouseEventBuilder(mainFrameImpl()->frameView(), event));
417 }
418
419 void WebViewImpl::mouseDown(const WebMouseEvent& event)
420 {
421     if (!mainFrameImpl() || !mainFrameImpl()->frameView())
422         return;
423
424     // If there is a select popup open, close it as the user is clicking on
425     // the page (outside of the popup).  We also save it so we can prevent a
426     // click on the select element from immediately reopening the popup.
427     RefPtr<WebCore::PopupContainer> selectPopup;
428     if (event.button == WebMouseEvent::ButtonLeft) {
429         selectPopup = m_selectPopup;
430         hideSelectPopup();
431         ASSERT(!m_selectPopup);
432     }
433
434     m_lastMouseDownPoint = WebPoint(event.x, event.y);
435
436     RefPtr<Node> clickedNode;
437     if (event.button == WebMouseEvent::ButtonLeft) {
438         IntPoint point(event.x, event.y);
439         point = m_page->mainFrame()->view()->windowToContents(point);
440         HitTestResult result(m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(point, false));
441         Node* hitNode = result.innerNonSharedNode();
442
443         // Take capture on a mouse down on a plugin so we can send it mouse events.
444         if (hitNode && hitNode->renderer() && hitNode->renderer()->isEmbeddedObject())
445             m_mouseCaptureNode = hitNode;
446
447         // If a text field that has focus is clicked again, we should display the
448         // AutoFill popup.
449         RefPtr<Node> focusedNode = focusedWebCoreNode();
450         if (focusedNode.get() && toHTMLInputElement(focusedNode.get())) {
451             if (hitNode == focusedNode) {
452                 // Already focused text field was clicked, let's remember this.  If
453                 // focus has not changed after the mouse event is processed, we'll
454                 // trigger the autocomplete.
455                 clickedNode = focusedNode;
456             }
457         }
458     }
459
460     mainFrameImpl()->frame()->loader()->resetMultipleFormSubmissionProtection();
461
462     mainFrameImpl()->frame()->eventHandler()->handleMousePressEvent(
463         PlatformMouseEventBuilder(mainFrameImpl()->frameView(), event));
464
465     if (clickedNode.get() && clickedNode == focusedWebCoreNode()) {
466         // Focus has not changed, show the AutoFill popup.
467         static_cast<EditorClientImpl*>(m_page->editorClient())->
468             showFormAutofillForNode(clickedNode.get());
469     }
470     if (m_selectPopup && m_selectPopup == selectPopup) {
471         // That click triggered a select popup which is the same as the one that
472         // was showing before the click.  It means the user clicked the select
473         // while the popup was showing, and as a result we first closed then
474         // immediately reopened the select popup.  It needs to be closed.
475         hideSelectPopup();
476     }
477
478     // Dispatch the contextmenu event regardless of if the click was swallowed.
479     // On Windows, we handle it on mouse up, not down.
480 #if OS(DARWIN)
481     if (event.button == WebMouseEvent::ButtonRight
482         || (event.button == WebMouseEvent::ButtonLeft
483             && event.modifiers & WebMouseEvent::ControlKey))
484         mouseContextMenu(event);
485 #elif OS(LINUX) || OS(FREEBSD)
486     if (event.button == WebMouseEvent::ButtonRight)
487         mouseContextMenu(event);
488 #endif
489 }
490
491 void WebViewImpl::mouseContextMenu(const WebMouseEvent& event)
492 {
493     if (!mainFrameImpl() || !mainFrameImpl()->frameView())
494         return;
495
496     m_page->contextMenuController()->clearContextMenu();
497
498     PlatformMouseEventBuilder pme(mainFrameImpl()->frameView(), event);
499
500     // Find the right target frame. See issue 1186900.
501     HitTestResult result = hitTestResultForWindowPos(pme.pos());
502     Frame* targetFrame;
503     if (result.innerNonSharedNode())
504         targetFrame = result.innerNonSharedNode()->document()->frame();
505     else
506         targetFrame = m_page->focusController()->focusedOrMainFrame();
507
508 #if OS(WINDOWS)
509     targetFrame->view()->setCursor(pointerCursor());
510 #endif
511
512     m_contextMenuAllowed = true;
513     targetFrame->eventHandler()->sendContextMenuEvent(pme);
514     m_contextMenuAllowed = false;
515     // Actually showing the context menu is handled by the ContextMenuClient
516     // implementation...
517 }
518
519 void WebViewImpl::mouseUp(const WebMouseEvent& event)
520 {
521     if (!mainFrameImpl() || !mainFrameImpl()->frameView())
522         return;
523
524 #if OS(LINUX) || OS(FREEBSD)
525     // If the event was a middle click, attempt to copy text into the focused
526     // frame. We execute this before we let the page have a go at the event
527     // because the page may change what is focused during in its event handler.
528     //
529     // This code is in the mouse up handler. There is some debate about putting
530     // this here, as opposed to the mouse down handler.
531     //   xterm: pastes on up.
532     //   GTK: pastes on down.
533     //   Firefox: pastes on up.
534     //   Midori: couldn't paste at all with 0.1.2
535     //
536     // There is something of a webcompat angle to this well, as highlighted by
537     // crbug.com/14608. Pages can clear text boxes 'onclick' and, if we paste on
538     // down then the text is pasted just before the onclick handler runs and
539     // clears the text box. So it's important this happens after the
540     // handleMouseReleaseEvent() earlier in this function
541     if (event.button == WebMouseEvent::ButtonMiddle) {
542         Frame* focused = focusedWebCoreFrame();
543         FrameView* view = m_page->mainFrame()->view();
544         IntPoint clickPoint(m_lastMouseDownPoint.x, m_lastMouseDownPoint.y);
545         IntPoint contentPoint = view->windowToContents(clickPoint);
546         HitTestResult hitTestResult = focused->eventHandler()->hitTestResultAtPoint(contentPoint, false, false, ShouldHitTestScrollbars);
547         // We don't want to send a paste when middle clicking a scroll bar or a
548         // link (which will navigate later in the code).  The main scrollbars
549         // have to be handled separately.
550         if (!hitTestResult.scrollbar() && !hitTestResult.isLiveLink() && focused && !view->scrollbarAtPoint(clickPoint)) {
551             Editor* editor = focused->editor();
552             Pasteboard* pasteboard = Pasteboard::generalPasteboard();
553             bool oldSelectionMode = pasteboard->isSelectionMode();
554             pasteboard->setSelectionMode(true);
555             editor->command(AtomicString("Paste")).execute();
556             pasteboard->setSelectionMode(oldSelectionMode);
557         }
558     }
559 #endif
560
561     mainFrameImpl()->frame()->eventHandler()->handleMouseReleaseEvent(
562         PlatformMouseEventBuilder(mainFrameImpl()->frameView(), event));
563
564 #if OS(WINDOWS)
565     // Dispatch the contextmenu event regardless of if the click was swallowed.
566     // On Mac/Linux, we handle it on mouse down, not up.
567     if (event.button == WebMouseEvent::ButtonRight)
568         mouseContextMenu(event);
569 #endif
570 }
571
572 bool WebViewImpl::mouseWheel(const WebMouseWheelEvent& event)
573 {
574     PlatformWheelEventBuilder platformEvent(mainFrameImpl()->frameView(), event);
575     return mainFrameImpl()->frame()->eventHandler()->handleWheelEvent(platformEvent);
576 }
577
578 bool WebViewImpl::keyEvent(const WebKeyboardEvent& event)
579 {
580     ASSERT((event.type == WebInputEvent::RawKeyDown)
581         || (event.type == WebInputEvent::KeyDown)
582         || (event.type == WebInputEvent::KeyUp));
583
584     // Please refer to the comments explaining the m_suppressNextKeypressEvent
585     // member.
586     // The m_suppressNextKeypressEvent is set if the KeyDown is handled by
587     // Webkit. A keyDown event is typically associated with a keyPress(char)
588     // event and a keyUp event. We reset this flag here as this is a new keyDown
589     // event.
590     m_suppressNextKeypressEvent = false;
591
592     // Give any select popup a chance at consuming the key event.
593     if (selectPopupHandleKeyEvent(event))
594         return true;
595
596     // Give Autocomplete a chance to consume the key events it is interested in.
597     if (autocompleteHandleKeyEvent(event))
598         return true;
599
600     Frame* frame = focusedWebCoreFrame();
601     if (!frame)
602         return false;
603
604     EventHandler* handler = frame->eventHandler();
605     if (!handler)
606         return keyEventDefault(event);
607
608 #if OS(WINDOWS) || OS(LINUX) || OS(FREEBSD)
609     const WebInputEvent::Type contextMenuTriggeringEventType =
610 #if OS(WINDOWS)
611         WebInputEvent::KeyUp;
612 #elif OS(LINUX) || OS(FREEBSD)
613         WebInputEvent::RawKeyDown;
614 #endif
615
616     bool isUnmodifiedMenuKey = !(event.modifiers & WebInputEvent::InputModifiers) && event.windowsKeyCode == VKEY_APPS;
617     bool isShiftF10 = event.modifiers == WebInputEvent::ShiftKey && event.windowsKeyCode == VKEY_F10;
618     if ((isUnmodifiedMenuKey || isShiftF10) && event.type == contextMenuTriggeringEventType) {
619         sendContextMenuEvent(event);
620         return true;
621     }
622 #endif // OS(WINDOWS) || OS(LINUX) || OS(FREEBSD)
623
624     PlatformKeyboardEventBuilder evt(event);
625
626     if (handler->keyEvent(evt)) {
627         if (WebInputEvent::RawKeyDown == event.type) {
628             // Suppress the next keypress event unless the focused node is a plug-in node.
629             // (Flash needs these keypress events to handle non-US keyboards.)
630             Node* node = frame->document()->focusedNode();
631             if (!node || !node->renderer() || !node->renderer()->isEmbeddedObject())
632                 m_suppressNextKeypressEvent = true;
633         }
634         return true;
635     }
636
637     return keyEventDefault(event);
638 }
639
640 bool WebViewImpl::selectPopupHandleKeyEvent(const WebKeyboardEvent& event)
641 {
642     if (!m_selectPopup)
643         return false;
644
645     return m_selectPopup->handleKeyEvent(PlatformKeyboardEventBuilder(event));
646 }
647
648 bool WebViewImpl::autocompleteHandleKeyEvent(const WebKeyboardEvent& event)
649 {
650     if (!m_autoFillPopupShowing
651         // Home and End should be left to the text field to process.
652         || event.windowsKeyCode == VKEY_HOME
653         || event.windowsKeyCode == VKEY_END)
654       return false;
655
656     // Pressing delete triggers the removal of the selected suggestion from the DB.
657     if (event.windowsKeyCode == VKEY_DELETE
658         && m_autoFillPopup->selectedIndex() != -1) {
659         Node* node = focusedWebCoreNode();
660         if (!node || (node->nodeType() != Node::ELEMENT_NODE)) {
661             ASSERT_NOT_REACHED();
662             return false;
663         }
664         Element* element = static_cast<Element*>(node);
665         if (!element->hasLocalName(HTMLNames::inputTag)) {
666             ASSERT_NOT_REACHED();
667             return false;
668         }
669
670         int selectedIndex = m_autoFillPopup->selectedIndex();
671
672         if (!m_autoFillPopupClient->canRemoveSuggestionAtIndex(selectedIndex))
673             return false;
674
675         WebString name = WebInputElement(static_cast<HTMLInputElement*>(element)).nameForAutofill();
676         WebString value = m_autoFillPopupClient->itemText(selectedIndex);
677         m_autoFillClient->removeAutocompleteSuggestion(name, value);
678         // Update the entries in the currently showing popup to reflect the
679         // deletion.
680         m_autoFillPopupClient->removeSuggestionAtIndex(selectedIndex);
681         refreshAutoFillPopup();
682         return false;
683     }
684
685     if (!m_autoFillPopup->isInterestedInEventForKey(event.windowsKeyCode))
686         return false;
687
688     if (m_autoFillPopup->handleKeyEvent(PlatformKeyboardEventBuilder(event))) {
689         // We need to ignore the next Char event after this otherwise pressing
690         // enter when selecting an item in the menu will go to the page.
691         if (WebInputEvent::RawKeyDown == event.type)
692             m_suppressNextKeypressEvent = true;
693         return true;
694     }
695
696     return false;
697 }
698
699 bool WebViewImpl::charEvent(const WebKeyboardEvent& event)
700 {
701     ASSERT(event.type == WebInputEvent::Char);
702
703     // Please refer to the comments explaining the m_suppressNextKeypressEvent
704     // member.  The m_suppressNextKeypressEvent is set if the KeyDown is
705     // handled by Webkit. A keyDown event is typically associated with a
706     // keyPress(char) event and a keyUp event. We reset this flag here as it
707     // only applies to the current keyPress event.
708     bool suppress = m_suppressNextKeypressEvent;
709     m_suppressNextKeypressEvent = false;
710
711     Frame* frame = focusedWebCoreFrame();
712     if (!frame)
713         return suppress;
714
715     EventHandler* handler = frame->eventHandler();
716     if (!handler)
717         return suppress || keyEventDefault(event);
718
719     PlatformKeyboardEventBuilder evt(event);
720     if (!evt.isCharacterKey())
721         return true;
722
723     // Accesskeys are triggered by char events and can't be suppressed.
724     if (handler->handleAccessKey(evt))
725         return true;
726
727     // Safari 3.1 does not pass off windows system key messages (WM_SYSCHAR) to
728     // the eventHandler::keyEvent. We mimic this behavior on all platforms since
729     // for now we are converting other platform's key events to windows key
730     // events.
731     if (evt.isSystemKey())
732         return false;
733
734     if (!suppress && !handler->keyEvent(evt))
735         return keyEventDefault(event);
736
737     return true;
738 }
739
740 #if ENABLE(TOUCH_EVENTS)
741 bool WebViewImpl::touchEvent(const WebTouchEvent& event)
742 {
743     if (!mainFrameImpl() || !mainFrameImpl()->frameView())
744         return false;
745
746     PlatformTouchEventBuilder touchEventBuilder(mainFrameImpl()->frameView(), event);
747     return mainFrameImpl()->frame()->eventHandler()->handleTouchEvent(touchEventBuilder);
748 }
749 #endif
750
751 #if OS(WINDOWS) || OS(LINUX) || OS(FREEBSD)
752 // Mac has no way to open a context menu based on a keyboard event.
753 bool WebViewImpl::sendContextMenuEvent(const WebKeyboardEvent& event)
754 {
755     // The contextMenuController() holds onto the last context menu that was
756     // popped up on the page until a new one is created. We need to clear
757     // this menu before propagating the event through the DOM so that we can
758     // detect if we create a new menu for this event, since we won't create
759     // a new menu if the DOM swallows the event and the defaultEventHandler does
760     // not run.
761     page()->contextMenuController()->clearContextMenu();
762
763     m_contextMenuAllowed = true;
764     Frame* focusedFrame = page()->focusController()->focusedOrMainFrame();
765     bool handled = focusedFrame->eventHandler()->sendContextMenuEventForKey();
766     m_contextMenuAllowed = false;
767     return handled;
768 }
769 #endif
770
771 bool WebViewImpl::keyEventDefault(const WebKeyboardEvent& event)
772 {
773     Frame* frame = focusedWebCoreFrame();
774     if (!frame)
775         return false;
776
777     switch (event.type) {
778     case WebInputEvent::Char:
779         if (event.windowsKeyCode == VKEY_SPACE) {
780             int keyCode = ((event.modifiers & WebInputEvent::ShiftKey) ? VKEY_PRIOR : VKEY_NEXT);
781             return scrollViewWithKeyboard(keyCode, event.modifiers);
782         }
783         break;
784     case WebInputEvent::RawKeyDown:
785         if (event.modifiers == WebInputEvent::ControlKey) {
786             switch (event.windowsKeyCode) {
787 #if !OS(DARWIN)
788             case 'A':
789                 focusedFrame()->executeCommand(WebString::fromUTF8("SelectAll"));
790                 return true;
791             case VKEY_INSERT:
792             case 'C':
793                 focusedFrame()->executeCommand(WebString::fromUTF8("Copy"));
794                 return true;
795 #endif
796             // Match FF behavior in the sense that Ctrl+home/end are the only Ctrl
797             // key combinations which affect scrolling. Safari is buggy in the
798             // sense that it scrolls the page for all Ctrl+scrolling key
799             // combinations. For e.g. Ctrl+pgup/pgdn/up/down, etc.
800             case VKEY_HOME:
801             case VKEY_END:
802                 break;
803             default:
804                 return false;
805             }
806         }
807         if (!event.isSystemKey && !(event.modifiers & WebInputEvent::ShiftKey))
808             return scrollViewWithKeyboard(event.windowsKeyCode, event.modifiers);
809         break;
810     default:
811         break;
812     }
813     return false;
814 }
815
816 bool WebViewImpl::scrollViewWithKeyboard(int keyCode, int modifiers)
817 {
818     ScrollDirection scrollDirection;
819     ScrollGranularity scrollGranularity;
820 #if OS(DARWIN)
821     // Control-Up/Down should be PageUp/Down on Mac.
822     if (modifiers & WebMouseEvent::ControlKey) {
823       if (keyCode == VKEY_UP)
824         keyCode = VKEY_PRIOR;
825       else if (keyCode == VKEY_DOWN)
826         keyCode = VKEY_NEXT;
827     }
828 #endif
829     if (!mapKeyCodeForScroll(keyCode, &scrollDirection, &scrollGranularity))
830         return false;
831     return propagateScroll(scrollDirection, scrollGranularity);
832 }
833
834 bool WebViewImpl::mapKeyCodeForScroll(int keyCode,
835                                       WebCore::ScrollDirection* scrollDirection,
836                                       WebCore::ScrollGranularity* scrollGranularity)
837 {
838     switch (keyCode) {
839     case VKEY_LEFT:
840         *scrollDirection = ScrollLeft;
841         *scrollGranularity = ScrollByLine;
842         break;
843     case VKEY_RIGHT:
844         *scrollDirection = ScrollRight;
845         *scrollGranularity = ScrollByLine;
846         break;
847     case VKEY_UP:
848         *scrollDirection = ScrollUp;
849         *scrollGranularity = ScrollByLine;
850         break;
851     case VKEY_DOWN:
852         *scrollDirection = ScrollDown;
853         *scrollGranularity = ScrollByLine;
854         break;
855     case VKEY_HOME:
856         *scrollDirection = ScrollUp;
857         *scrollGranularity = ScrollByDocument;
858         break;
859     case VKEY_END:
860         *scrollDirection = ScrollDown;
861         *scrollGranularity = ScrollByDocument;
862         break;
863     case VKEY_PRIOR:  // page up
864         *scrollDirection = ScrollUp;
865         *scrollGranularity = ScrollByPage;
866         break;
867     case VKEY_NEXT:  // page down
868         *scrollDirection = ScrollDown;
869         *scrollGranularity = ScrollByPage;
870         break;
871     default:
872         return false;
873     }
874
875     return true;
876 }
877
878 void WebViewImpl::hideSelectPopup()
879 {
880     if (m_selectPopup.get())
881         m_selectPopup->hidePopup();
882 }
883
884 bool WebViewImpl::propagateScroll(ScrollDirection scrollDirection,
885                                   ScrollGranularity scrollGranularity)
886 {
887     Frame* frame = focusedWebCoreFrame();
888     if (!frame)
889         return false;
890
891     bool scrollHandled = frame->eventHandler()->scrollOverflow(scrollDirection, scrollGranularity);
892     Frame* currentFrame = frame;
893     while (!scrollHandled && currentFrame) {
894         scrollHandled = currentFrame->view()->scroll(scrollDirection, scrollGranularity);
895         currentFrame = currentFrame->tree()->parent();
896     }
897     return scrollHandled;
898 }
899
900 void  WebViewImpl::popupOpened(WebCore::PopupContainer* popupContainer)
901 {
902     if (popupContainer->popupType() == WebCore::PopupContainer::Select) {
903         ASSERT(!m_selectPopup);
904         m_selectPopup = popupContainer;
905     }
906 }
907
908 void  WebViewImpl::popupClosed(WebCore::PopupContainer* popupContainer)
909 {
910     if (popupContainer->popupType() == WebCore::PopupContainer::Select) {
911         ASSERT(m_selectPopup.get());
912         m_selectPopup = 0;
913     }
914 }
915
916 void WebViewImpl::hideAutoFillPopup()
917 {
918     if (m_autoFillPopupShowing) {
919         m_autoFillPopup->hidePopup();
920         m_autoFillPopupShowing = false;
921     }
922 }
923
924 Frame* WebViewImpl::focusedWebCoreFrame() const
925 {
926     return m_page.get() ? m_page->focusController()->focusedOrMainFrame() : 0;
927 }
928
929 WebViewImpl* WebViewImpl::fromPage(Page* page)
930 {
931     if (!page)
932         return 0;
933
934     return static_cast<ChromeClientImpl*>(page->chrome()->client())->webView();
935 }
936
937 // WebWidget ------------------------------------------------------------------
938
939 void WebViewImpl::close()
940 {
941     RefPtr<WebFrameImpl> mainFrameImpl;
942
943     if (m_page.get()) {
944         // Initiate shutdown for the entire frameset.  This will cause a lot of
945         // notifications to be sent.
946         if (m_page->mainFrame()) {
947             mainFrameImpl = WebFrameImpl::fromFrame(m_page->mainFrame());
948             m_page->mainFrame()->loader()->frameDetached();
949         }
950         m_page.clear();
951     }
952
953     // Should happen after m_page.clear().
954     if (m_devToolsAgent.get())
955         m_devToolsAgent.clear();
956
957     // Reset the delegate to prevent notifications being sent as we're being
958     // deleted.
959     m_client = 0;
960
961     deref();  // Balances ref() acquired in WebView::create
962 }
963
964 void WebViewImpl::resize(const WebSize& newSize)
965 {
966     if (m_size == newSize)
967         return;
968     m_size = newSize;
969
970     if (mainFrameImpl()->frameView()) {
971         mainFrameImpl()->frameView()->resize(m_size.width, m_size.height);
972         mainFrameImpl()->frame()->eventHandler()->sendResizeEvent();
973     }
974
975     if (m_client) {
976         if (isAcceleratedCompositingActive()) {
977 #if USE(ACCELERATED_COMPOSITING)
978             updateLayerRendererViewport();
979 #endif
980         } else {
981             WebRect damagedRect(0, 0, m_size.width, m_size.height);
982             m_client->didInvalidateRect(damagedRect);
983         }
984     }
985
986 #if USE(ACCELERATED_COMPOSITING)
987     if (m_layerRenderer && isAcceleratedCompositingActive()) {
988         m_layerRenderer->resizeOnscreenContent(IntSize(std::max(1, m_size.width),
989                                                        std::max(1, m_size.height)));
990     }
991 #endif
992 }
993
994 void WebViewImpl::animate()
995 {
996 #if ENABLE(REQUEST_ANIMATION_FRAME)
997     WebFrameImpl* webframe = mainFrameImpl();
998     if (webframe) {
999         FrameView* view = webframe->frameView();
1000         if (view)
1001             view->serviceScriptedAnimations(convertSecondsToDOMTimeStamp(currentTime()));
1002     }
1003 #endif
1004 }
1005
1006 void WebViewImpl::layout()
1007 {
1008 #if USE(ACCELERATED_COMPOSITING)
1009     // FIXME: RTL style not supported by the compositor yet.
1010     if (isAcceleratedCompositingActive() && pageHasRTLStyle())
1011         setIsAcceleratedCompositingActive(false);
1012 #endif
1013
1014     WebFrameImpl* webframe = mainFrameImpl();
1015     if (webframe) {
1016         // In order for our child HWNDs (NativeWindowWidgets) to update properly,
1017         // they need to be told that we are updating the screen.  The problem is
1018         // that the native widgets need to recalculate their clip region and not
1019         // overlap any of our non-native widgets.  To force the resizing, call
1020         // setFrameRect().  This will be a quick operation for most frames, but
1021         // the NativeWindowWidgets will update a proper clipping region.
1022         FrameView* view = webframe->frameView();
1023         if (view)
1024             view->setFrameRect(view->frameRect());
1025
1026         // setFrameRect may have the side-effect of causing existing page
1027         // layout to be invalidated, so layout needs to be called last.
1028
1029         webframe->layout();
1030     }
1031 }
1032
1033 #if USE(ACCELERATED_COMPOSITING)
1034 void WebViewImpl::doPixelReadbackToCanvas(WebCanvas* canvas, const IntRect& rect)
1035 {
1036 #if USE(SKIA)
1037     PlatformContextSkia context(canvas);
1038
1039     // PlatformGraphicsContext is actually a pointer to PlatformContextSkia
1040     GraphicsContext gc(reinterpret_cast<PlatformGraphicsContext*>(&context));
1041     int bitmapHeight = canvas->getDevice()->accessBitmap(false).height();
1042 #elif USE(CG)
1043     GraphicsContext gc(canvas);
1044     int bitmapHeight = CGBitmapContextGetHeight(reinterpret_cast<CGContextRef>(canvas));
1045 #else
1046     notImplemented();
1047 #endif
1048     // Compute rect to sample from inverted GPU buffer.
1049     IntRect invertRect(rect.x(), bitmapHeight - rect.maxY(), rect.width(), rect.height());
1050
1051     OwnPtr<ImageBuffer> imageBuffer(ImageBuffer::create(rect.size()));
1052     RefPtr<ByteArray> pixelArray(ByteArray::create(rect.width() * rect.height() * 4));
1053     if (imageBuffer.get() && pixelArray.get()) {
1054         m_layerRenderer->getFramebufferPixels(pixelArray->data(), invertRect);
1055         imageBuffer->putPremultipliedImageData(pixelArray.get(), rect.size(), IntRect(IntPoint(), rect.size()), IntPoint());
1056         gc.save();
1057         gc.translate(IntSize(0, bitmapHeight));
1058         gc.scale(FloatSize(1.0f, -1.0f));
1059         // Use invertRect in next line, so that transform above inverts it back to
1060         // desired destination rect.
1061         gc.drawImageBuffer(imageBuffer.get(), ColorSpaceDeviceRGB, invertRect.location());
1062         gc.restore();
1063     }
1064 }
1065 #endif
1066
1067 void WebViewImpl::paint(WebCanvas* canvas, const WebRect& rect)
1068 {
1069     if (isAcceleratedCompositingActive()) {
1070 #if USE(ACCELERATED_COMPOSITING)
1071         doComposite();
1072
1073         // If a canvas was passed in, we use it to grab a copy of the
1074         // freshly-rendered pixels.
1075         if (canvas) {
1076             // Clip rect to the confines of the rootLayerTexture.
1077             IntRect resizeRect(rect);
1078             resizeRect.intersect(IntRect(IntPoint(), m_layerRenderer->viewportSize()));
1079             doPixelReadbackToCanvas(canvas, resizeRect);
1080         }
1081 #endif
1082     } else {
1083         WebFrameImpl* webframe = mainFrameImpl();
1084         if (webframe)
1085             webframe->paint(canvas, rect);
1086     }
1087 }
1088
1089 void WebViewImpl::themeChanged()
1090 {
1091     if (!page())
1092         return;
1093     FrameView* view = page()->mainFrame()->view();
1094
1095     WebRect damagedRect(0, 0, m_size.width, m_size.height);
1096     view->invalidateRect(damagedRect);
1097 }
1098
1099 void WebViewImpl::composite(bool finish)
1100 {
1101 #if USE(ACCELERATED_COMPOSITING)
1102     TRACE_EVENT("WebViewImpl::composite", this, 0);
1103     if (m_recreatingGraphicsContext) {
1104         // reallocateRenderer will request a repaint whether or not it succeeded
1105         // in creating a new context.
1106         reallocateRenderer();
1107         m_recreatingGraphicsContext = false;
1108         return;
1109     }
1110     doComposite();
1111
1112     // Finish if requested.
1113     if (finish)
1114         m_layerRenderer->finish();
1115
1116     // Put result onscreen.
1117     m_layerRenderer->present();
1118
1119     GraphicsContext3D* context = m_layerRenderer->context();
1120     if (context->getExtensions()->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR) {
1121         // Trying to recover the context right here will not work if GPU process
1122         // died. This is because GpuChannelHost::OnErrorMessage will only be
1123         // called at the next iteration of the message loop, reverting our
1124         // recovery attempts here. Instead, we detach the root layer from the
1125         // renderer, recreate the renderer at the next message loop iteration
1126         // and request a repaint yet again.
1127         m_recreatingGraphicsContext = true;
1128         setRootLayerNeedsDisplay();
1129     }
1130 #endif
1131 }
1132
1133 const WebInputEvent* WebViewImpl::m_currentInputEvent = 0;
1134
1135 bool WebViewImpl::handleInputEvent(const WebInputEvent& inputEvent)
1136 {
1137     UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture);
1138
1139     // If we've started a drag and drop operation, ignore input events until
1140     // we're done.
1141     if (m_doingDragAndDrop)
1142         return true;
1143
1144     if (m_ignoreInputEvents)
1145         return true;
1146
1147     m_currentInputEvent = &inputEvent;
1148
1149     if (m_mouseCaptureNode.get() && WebInputEvent::isMouseEventType(inputEvent.type)) {
1150         const int mouseButtonModifierMask = WebInputEvent::LeftButtonDown | WebInputEvent::MiddleButtonDown | WebInputEvent::RightButtonDown;
1151         if (inputEvent.type == WebInputEvent::MouseDown ||
1152             (inputEvent.modifiers & mouseButtonModifierMask) == 0) {
1153             // It's possible the mouse was released and we didn't get the "up"
1154             // message. This can happen if a dialog pops up while the mouse is
1155             // held, for example. This will leave us "stuck" in capture mode.
1156             // If we get a new mouse down message or any other mouse message
1157             // where no "down" flags are set, we know the user is no longer
1158             // dragging and we can release the capture and fall through to the
1159             // regular event processing.
1160             mouseCaptureLost();
1161         } else {
1162             // Save m_mouseCaptureNode since mouseCaptureLost() will clear it.
1163             RefPtr<Node> node = m_mouseCaptureNode;
1164
1165             // Not all platforms call mouseCaptureLost() directly.
1166             if (inputEvent.type == WebInputEvent::MouseUp)
1167                 mouseCaptureLost();
1168
1169             AtomicString eventType;
1170             switch (inputEvent.type) {
1171             case WebInputEvent::MouseMove:
1172                 eventType = eventNames().mousemoveEvent;
1173                 break;
1174             case WebInputEvent::MouseLeave:
1175                 eventType = eventNames().mouseoutEvent;
1176                 break;
1177             case WebInputEvent::MouseDown:
1178                 eventType = eventNames().mousedownEvent;
1179                 break;
1180             case WebInputEvent::MouseUp:
1181                 eventType = eventNames().mouseupEvent;
1182                 break;
1183             default:
1184                 ASSERT_NOT_REACHED();
1185             }
1186
1187             node->dispatchMouseEvent(
1188                   PlatformMouseEventBuilder(mainFrameImpl()->frameView(), *static_cast<const WebMouseEvent*>(&inputEvent)),
1189                   eventType, static_cast<const WebMouseEvent*>(&inputEvent)->clickCount);
1190             m_currentInputEvent = 0;
1191             return true;
1192         }
1193     }
1194
1195     bool handled = true;
1196
1197     // FIXME: WebKit seems to always return false on mouse events processing
1198     // methods. For now we'll assume it has processed them (as we are only
1199     // interested in whether keyboard events are processed).
1200     switch (inputEvent.type) {
1201     case WebInputEvent::MouseMove:
1202         mouseMove(*static_cast<const WebMouseEvent*>(&inputEvent));
1203         break;
1204
1205     case WebInputEvent::MouseLeave:
1206         mouseLeave(*static_cast<const WebMouseEvent*>(&inputEvent));
1207         break;
1208
1209     case WebInputEvent::MouseWheel:
1210         handled = mouseWheel(*static_cast<const WebMouseWheelEvent*>(&inputEvent));
1211         break;
1212
1213     case WebInputEvent::MouseDown:
1214         mouseDown(*static_cast<const WebMouseEvent*>(&inputEvent));
1215         break;
1216
1217     case WebInputEvent::MouseUp:
1218         mouseUp(*static_cast<const WebMouseEvent*>(&inputEvent));
1219         break;
1220
1221     case WebInputEvent::RawKeyDown:
1222     case WebInputEvent::KeyDown:
1223     case WebInputEvent::KeyUp:
1224         handled = keyEvent(*static_cast<const WebKeyboardEvent*>(&inputEvent));
1225         break;
1226
1227     case WebInputEvent::Char:
1228         handled = charEvent(*static_cast<const WebKeyboardEvent*>(&inputEvent));
1229         break;
1230
1231 #if ENABLE(TOUCH_EVENTS)
1232     case WebInputEvent::TouchStart:
1233     case WebInputEvent::TouchMove:
1234     case WebInputEvent::TouchEnd:
1235     case WebInputEvent::TouchCancel:
1236         handled = touchEvent(*static_cast<const WebTouchEvent*>(&inputEvent));
1237         break;
1238 #endif
1239
1240     default:
1241         handled = false;
1242     }
1243
1244     m_currentInputEvent = 0;
1245
1246     return handled;
1247 }
1248
1249 void WebViewImpl::mouseCaptureLost()
1250 {
1251     m_mouseCaptureNode = 0;
1252 }
1253
1254 void WebViewImpl::setFocus(bool enable)
1255 {
1256     m_page->focusController()->setFocused(enable);
1257     if (enable) {
1258         // Note that we don't call setActive() when disabled as this cause extra
1259         // focus/blur events to be dispatched.
1260         m_page->focusController()->setActive(true);
1261         RefPtr<Frame> focusedFrame = m_page->focusController()->focusedFrame();
1262         if (focusedFrame) {
1263             Node* focusedNode = focusedFrame->document()->focusedNode();
1264             if (focusedNode && focusedNode->isElementNode()
1265                 && focusedFrame->selection()->selection().isNone()) {
1266                 // If the selection was cleared while the WebView was not
1267                 // focused, then the focus element shows with a focus ring but
1268                 // no caret and does respond to keyboard inputs.
1269                 Element* element = static_cast<Element*>(focusedNode);
1270                 if (element->isTextFormControl())
1271                     element->updateFocusAppearance(true);
1272                 else if (focusedNode->isContentEditable()) {
1273                     // updateFocusAppearance() selects all the text of
1274                     // contentseditable DIVs. So we set the selection explicitly
1275                     // instead. Note that this has the side effect of moving the
1276                     // caret back to the beginning of the text.
1277                     Position position(focusedNode, 0,
1278                                       Position::PositionIsOffsetInAnchor);
1279                     focusedFrame->selection()->setSelection(
1280                         VisibleSelection(position, SEL_DEFAULT_AFFINITY));
1281                 }
1282             }
1283         }
1284         m_imeAcceptEvents = true;
1285     } else {
1286         hideAutoFillPopup();
1287         hideSelectPopup();
1288
1289         // Clear focus on the currently focused frame if any.
1290         if (!m_page.get())
1291             return;
1292
1293         Frame* frame = m_page->mainFrame();
1294         if (!frame)
1295             return;
1296
1297         RefPtr<Frame> focusedFrame = m_page->focusController()->focusedFrame();
1298         if (focusedFrame.get()) {
1299             // Finish an ongoing composition to delete the composition node.
1300             Editor* editor = focusedFrame->editor();
1301             if (editor && editor->hasComposition())
1302                 editor->confirmComposition();
1303             m_imeAcceptEvents = false;
1304         }
1305     }
1306 }
1307
1308 bool WebViewImpl::setComposition(
1309     const WebString& text,
1310     const WebVector<WebCompositionUnderline>& underlines,
1311     int selectionStart,
1312     int selectionEnd)
1313 {
1314     Frame* focused = focusedWebCoreFrame();
1315     if (!focused || !m_imeAcceptEvents)
1316         return false;
1317     Editor* editor = focused->editor();
1318     if (!editor)
1319         return false;
1320
1321     // The input focus has been moved to another WebWidget object.
1322     // We should use this |editor| object only to complete the ongoing
1323     // composition.
1324     if (!editor->canEdit() && !editor->hasComposition())
1325         return false;
1326
1327     // We should verify the parent node of this IME composition node are
1328     // editable because JavaScript may delete a parent node of the composition
1329     // node. In this case, WebKit crashes while deleting texts from the parent
1330     // node, which doesn't exist any longer.
1331     PassRefPtr<Range> range = editor->compositionRange();
1332     if (range) {
1333         const Node* node = range->startContainer();
1334         if (!node || !node->isContentEditable())
1335             return false;
1336     }
1337
1338     // If we're not going to fire a keypress event, then the keydown event was
1339     // canceled.  In that case, cancel any existing composition.
1340     if (text.isEmpty() || m_suppressNextKeypressEvent) {
1341         // A browser process sent an IPC message which does not contain a valid
1342         // string, which means an ongoing composition has been canceled.
1343         // If the ongoing composition has been canceled, replace the ongoing
1344         // composition string with an empty string and complete it.
1345         String emptyString;
1346         Vector<CompositionUnderline> emptyUnderlines;
1347         editor->setComposition(emptyString, emptyUnderlines, 0, 0);
1348         return text.isEmpty();
1349     }
1350
1351     // When the range of composition underlines overlap with the range between
1352     // selectionStart and selectionEnd, WebKit somehow won't paint the selection
1353     // at all (see InlineTextBox::paint() function in InlineTextBox.cpp).
1354     // But the selection range actually takes effect.
1355     editor->setComposition(String(text),
1356                            CompositionUnderlineVectorBuilder(underlines),
1357                            selectionStart, selectionEnd);
1358
1359     return editor->hasComposition();
1360 }
1361
1362 bool WebViewImpl::confirmComposition()
1363 {
1364     return confirmComposition(WebString());
1365 }
1366
1367 bool WebViewImpl::confirmComposition(const WebString& text)
1368 {
1369     Frame* focused = focusedWebCoreFrame();
1370     if (!focused || !m_imeAcceptEvents)
1371         return false;
1372     Editor* editor = focused->editor();
1373     if (!editor || (!editor->hasComposition() && !text.length()))
1374         return false;
1375
1376     // We should verify the parent node of this IME composition node are
1377     // editable because JavaScript may delete a parent node of the composition
1378     // node. In this case, WebKit crashes while deleting texts from the parent
1379     // node, which doesn't exist any longer.
1380     PassRefPtr<Range> range = editor->compositionRange();
1381     if (range) {
1382         const Node* node = range->startContainer();
1383         if (!node || !node->isContentEditable())
1384             return false;
1385     }
1386
1387     if (editor->hasComposition()) {
1388         if (text.length())
1389             editor->confirmComposition(String(text));
1390         else
1391             editor->confirmComposition();
1392     } else
1393         editor->insertText(String(text), 0);
1394
1395     return true;
1396 }
1397
1398 WebTextInputType WebViewImpl::textInputType()
1399 {
1400     WebTextInputType type = WebTextInputTypeNone;
1401     const Frame* focused = focusedWebCoreFrame();
1402     if (!focused)
1403         return type;
1404
1405     const Editor* editor = focused->editor();
1406     if (!editor || !editor->canEdit())
1407         return type;
1408
1409     SelectionController* controller = focused->selection();
1410     if (!controller)
1411         return type;
1412
1413     const Node* node = controller->start().deprecatedNode();
1414     if (!node)
1415         return type;
1416
1417     // FIXME: Support more text input types when necessary, eg. Number,
1418     // Date, Email, URL, etc.
1419     if (controller->isInPasswordField())
1420         type = WebTextInputTypePassword;
1421     else if (node->shouldUseInputMethod())
1422         type = WebTextInputTypeText;
1423
1424     return type;
1425 }
1426
1427 WebRect WebViewImpl::caretOrSelectionBounds()
1428 {
1429     WebRect rect;
1430     const Frame* focused = focusedWebCoreFrame();
1431     if (!focused)
1432         return rect;
1433
1434     SelectionController* controller = focused->selection();
1435     if (!controller)
1436         return rect;
1437
1438     const FrameView* view = focused->view();
1439     if (!view)
1440         return rect;
1441
1442     const Node* node = controller->base().containerNode();
1443     if (!node || !node->renderer())
1444         return rect;
1445
1446     if (controller->isCaret())
1447         rect = view->contentsToWindow(controller->absoluteCaretBounds());
1448     else if (controller->isRange()) {
1449         node = controller->extent().containerNode();
1450         RefPtr<Range> range = controller->toNormalizedRange();
1451         if (!node || !node->renderer() || !range)
1452             return rect;
1453         rect = view->contentsToWindow(focused->editor()->firstRectForRange(range.get()));
1454     }
1455     return rect;
1456 }
1457
1458 bool WebViewImpl::selectionRange(WebPoint& start, WebPoint& end) const
1459 {
1460     const Frame* frame = focusedWebCoreFrame();
1461     if (!frame)
1462         return false;
1463     RefPtr<Range> selectedRange = frame->selection()->toNormalizedRange();
1464     RefPtr<Range> range(Range::create(selectedRange->startContainer()->document(),
1465                                       selectedRange->startContainer(),
1466                                       selectedRange->startOffset(),
1467                                       selectedRange->startContainer(),
1468                                       selectedRange->startOffset()));
1469
1470     IntRect rect = frame->editor()->firstRectForRange(range.get());
1471     start.x = rect.x();
1472     start.y = rect.y() + rect.height() - 1;
1473
1474     range = Range::create(selectedRange->endContainer()->document(),
1475                           selectedRange->endContainer(),
1476                           selectedRange->endOffset(),
1477                           selectedRange->endContainer(),
1478                           selectedRange->endOffset());
1479
1480     rect = frame->editor()->firstRectForRange(range.get());
1481     end.x = rect.x() + rect.width() - 1;
1482     end.y = rect.y() + rect.height() - 1;
1483
1484     start = frame->view()->contentsToWindow(start);
1485     end = frame->view()->contentsToWindow(end);
1486     return true;
1487 }
1488
1489 void WebViewImpl::setTextDirection(WebTextDirection direction)
1490 {
1491     // The Editor::setBaseWritingDirection() function checks if we can change
1492     // the text direction of the selected node and updates its DOM "dir"
1493     // attribute and its CSS "direction" property.
1494     // So, we just call the function as Safari does.
1495     const Frame* focused = focusedWebCoreFrame();
1496     if (!focused)
1497         return;
1498
1499     Editor* editor = focused->editor();
1500     if (!editor || !editor->canEdit())
1501         return;
1502
1503     switch (direction) {
1504     case WebTextDirectionDefault:
1505         editor->setBaseWritingDirection(NaturalWritingDirection);
1506         break;
1507
1508     case WebTextDirectionLeftToRight:
1509         editor->setBaseWritingDirection(LeftToRightWritingDirection);
1510         break;
1511
1512     case WebTextDirectionRightToLeft:
1513         editor->setBaseWritingDirection(RightToLeftWritingDirection);
1514         break;
1515
1516     default:
1517         notImplemented();
1518         break;
1519     }
1520 }
1521
1522 bool WebViewImpl::isAcceleratedCompositingActive() const
1523 {
1524 #if USE(ACCELERATED_COMPOSITING)
1525     return m_isAcceleratedCompositingActive;
1526 #else
1527     return false;
1528 #endif
1529 }
1530
1531 // WebView --------------------------------------------------------------------
1532
1533 WebSettings* WebViewImpl::settings()
1534 {
1535     if (!m_webSettings.get())
1536         m_webSettings.set(new WebSettingsImpl(m_page->settings()));
1537     ASSERT(m_webSettings.get());
1538     return m_webSettings.get();
1539 }
1540
1541 WebString WebViewImpl::pageEncoding() const
1542 {
1543     if (!m_page.get())
1544         return WebString();
1545
1546     return m_page->mainFrame()->document()->loader()->writer()->encoding();
1547 }
1548
1549 void WebViewImpl::setPageEncoding(const WebString& encodingName)
1550 {
1551     if (!m_page.get())
1552         return;
1553
1554     // Only change override encoding, don't change default encoding.
1555     // Note that the new encoding must be 0 if it isn't supposed to be set.
1556     String newEncodingName;
1557     if (!encodingName.isEmpty())
1558         newEncodingName = encodingName;
1559     m_page->mainFrame()->loader()->reloadWithOverrideEncoding(newEncodingName);
1560 }
1561
1562 bool WebViewImpl::dispatchBeforeUnloadEvent()
1563 {
1564     // FIXME: This should really cause a recursive depth-first walk of all
1565     // frames in the tree, calling each frame's onbeforeunload.  At the moment,
1566     // we're consistent with Safari 3.1, not IE/FF.
1567     Frame* frame = m_page->mainFrame();
1568     if (!frame)
1569         return true;
1570
1571     return frame->loader()->shouldClose();
1572 }
1573
1574 void WebViewImpl::dispatchUnloadEvent()
1575 {
1576     // Run unload handlers.
1577     m_page->mainFrame()->loader()->closeURL();
1578 }
1579
1580 WebFrame* WebViewImpl::mainFrame()
1581 {
1582     return mainFrameImpl();
1583 }
1584
1585 WebFrame* WebViewImpl::findFrameByName(
1586     const WebString& name, WebFrame* relativeToFrame)
1587 {
1588     if (!relativeToFrame)
1589         relativeToFrame = mainFrame();
1590     Frame* frame = static_cast<WebFrameImpl*>(relativeToFrame)->frame();
1591     frame = frame->tree()->find(name);
1592     return WebFrameImpl::fromFrame(frame);
1593 }
1594
1595 WebFrame* WebViewImpl::focusedFrame()
1596 {
1597     return WebFrameImpl::fromFrame(focusedWebCoreFrame());
1598 }
1599
1600 void WebViewImpl::setFocusedFrame(WebFrame* frame)
1601 {
1602     if (!frame) {
1603         // Clears the focused frame if any.
1604         Frame* frame = focusedWebCoreFrame();
1605         if (frame)
1606             frame->selection()->setFocused(false);
1607         return;
1608     }
1609     WebFrameImpl* frameImpl = static_cast<WebFrameImpl*>(frame);
1610     Frame* webcoreFrame = frameImpl->frame();
1611     webcoreFrame->page()->focusController()->setFocusedFrame(webcoreFrame);
1612 }
1613
1614 void WebViewImpl::setInitialFocus(bool reverse)
1615 {
1616     if (!m_page.get())
1617         return;
1618
1619     // Since we don't have a keyboard event, we'll create one.
1620     WebKeyboardEvent keyboardEvent;
1621     keyboardEvent.type = WebInputEvent::RawKeyDown;
1622     if (reverse)
1623         keyboardEvent.modifiers = WebInputEvent::ShiftKey;
1624
1625     // VK_TAB which is only defined on Windows.
1626     keyboardEvent.windowsKeyCode = 0x09;
1627     PlatformKeyboardEventBuilder platformEvent(keyboardEvent);
1628     RefPtr<KeyboardEvent> webkitEvent = KeyboardEvent::create(platformEvent, 0);
1629
1630     Frame* frame = page()->focusController()->focusedOrMainFrame();
1631     if (Document* document = frame->document())
1632         document->setFocusedNode(0);
1633     page()->focusController()->setInitialFocus(
1634         reverse ? FocusDirectionBackward : FocusDirectionForward,
1635         webkitEvent.get());
1636 }
1637
1638 void WebViewImpl::clearFocusedNode()
1639 {
1640     if (!m_page.get())
1641         return;
1642
1643     RefPtr<Frame> frame = m_page->mainFrame();
1644     if (!frame.get())
1645         return;
1646
1647     RefPtr<Document> document = frame->document();
1648     if (!document.get())
1649         return;
1650
1651     RefPtr<Node> oldFocusedNode = document->focusedNode();
1652
1653     // Clear the focused node.
1654     document->setFocusedNode(0);
1655
1656     if (!oldFocusedNode.get())
1657         return;
1658
1659     // If a text field has focus, we need to make sure the selection controller
1660     // knows to remove selection from it. Otherwise, the text field is still
1661     // processing keyboard events even though focus has been moved to the page and
1662     // keystrokes get eaten as a result.
1663     if (oldFocusedNode->hasTagName(HTMLNames::textareaTag)
1664         || (oldFocusedNode->hasTagName(HTMLNames::inputTag)
1665             && static_cast<HTMLInputElement*>(oldFocusedNode.get())->isTextField())) {
1666         // Clear the selection.
1667         SelectionController* selection = frame->selection();
1668         selection->clear();
1669     }
1670 }
1671
1672 void WebViewImpl::scrollFocusedNodeIntoView()
1673 {
1674     Node* focusedNode = focusedWebCoreNode();
1675     if (focusedNode && focusedNode->isElementNode()) {
1676         Element* elementNode = static_cast<Element*>(focusedNode);
1677         elementNode->scrollIntoViewIfNeeded(true);
1678     }
1679 }
1680
1681 double WebViewImpl::zoomLevel()
1682 {
1683     return m_zoomLevel;
1684 }
1685
1686 double WebViewImpl::setZoomLevel(bool textOnly, double zoomLevel)
1687 {
1688     if (zoomLevel < m_minimumZoomLevel)
1689         m_zoomLevel = m_minimumZoomLevel;
1690     else if (zoomLevel > m_maximumZoomLevel)
1691         m_zoomLevel = m_maximumZoomLevel;
1692     else
1693         m_zoomLevel = zoomLevel;
1694
1695     Frame* frame = mainFrameImpl()->frame();
1696     WebPluginContainerImpl* pluginContainer = WebFrameImpl::pluginContainerFromFrame(frame);
1697     if (pluginContainer)
1698         pluginContainer->plugin()->setZoomLevel(m_zoomLevel, textOnly);
1699     else {
1700         float zoomFactor = static_cast<float>(zoomLevelToZoomFactor(m_zoomLevel));
1701         if (textOnly)
1702             frame->setPageAndTextZoomFactors(1, zoomFactor);
1703         else
1704             frame->setPageAndTextZoomFactors(zoomFactor, 1);
1705     }
1706     return m_zoomLevel;
1707 }
1708
1709 void WebViewImpl::zoomLimitsChanged(double minimumZoomLevel,
1710                                     double maximumZoomLevel)
1711 {
1712     m_minimumZoomLevel = minimumZoomLevel;
1713     m_maximumZoomLevel = maximumZoomLevel;
1714     m_client->zoomLimitsChanged(m_minimumZoomLevel, m_maximumZoomLevel);
1715 }
1716
1717 void WebViewImpl::fullFramePluginZoomLevelChanged(double zoomLevel)
1718 {
1719     if (zoomLevel == m_zoomLevel)
1720         return;
1721
1722     m_zoomLevel = std::max(std::min(zoomLevel, m_maximumZoomLevel), m_minimumZoomLevel);
1723     m_client->zoomLevelChanged();
1724 }
1725
1726 double WebView::zoomLevelToZoomFactor(double zoomLevel)
1727 {
1728     return std::pow(textSizeMultiplierRatio, zoomLevel);
1729 }
1730
1731 double WebView::zoomFactorToZoomLevel(double factor)
1732 {
1733     // Since factor = 1.2^level, level = log(factor) / log(1.2)
1734     return log(factor) / log(textSizeMultiplierRatio);
1735 }
1736
1737 void WebViewImpl::performMediaPlayerAction(const WebMediaPlayerAction& action,
1738                                            const WebPoint& location)
1739 {
1740     HitTestResult result =
1741         hitTestResultForWindowPos(location);
1742     RefPtr<Node> node = result.innerNonSharedNode();
1743     if (!node->hasTagName(HTMLNames::videoTag) && !node->hasTagName(HTMLNames::audioTag))
1744       return;
1745
1746     RefPtr<HTMLMediaElement> mediaElement =
1747         static_pointer_cast<HTMLMediaElement>(node);
1748     switch (action.type) {
1749     case WebMediaPlayerAction::Play:
1750         if (action.enable)
1751             mediaElement->play(mediaElement->processingUserGesture());
1752         else
1753             mediaElement->pause(mediaElement->processingUserGesture());
1754         break;
1755     case WebMediaPlayerAction::Mute:
1756         mediaElement->setMuted(action.enable);
1757         break;
1758     case WebMediaPlayerAction::Loop:
1759         mediaElement->setLoop(action.enable);
1760         break;
1761     case WebMediaPlayerAction::Controls:
1762         mediaElement->setControls(action.enable);
1763         break;
1764     default:
1765         ASSERT_NOT_REACHED();
1766     }
1767 }
1768
1769 void WebViewImpl::copyImageAt(const WebPoint& point)
1770 {
1771     if (!m_page.get())
1772         return;
1773
1774     HitTestResult result = hitTestResultForWindowPos(point);
1775
1776     if (result.absoluteImageURL().isEmpty()) {
1777         // There isn't actually an image at these coordinates.  Might be because
1778         // the window scrolled while the context menu was open or because the page
1779         // changed itself between when we thought there was an image here and when
1780         // we actually tried to retreive the image.
1781         //
1782         // FIXME: implement a cache of the most recent HitTestResult to avoid having
1783         //        to do two hit tests.
1784         return;
1785     }
1786
1787     m_page->mainFrame()->editor()->copyImage(result);
1788 }
1789
1790 void WebViewImpl::dragSourceEndedAt(
1791     const WebPoint& clientPoint,
1792     const WebPoint& screenPoint,
1793     WebDragOperation operation)
1794 {
1795     PlatformMouseEvent pme(clientPoint,
1796                            screenPoint,
1797                            LeftButton, MouseEventMoved, 0, false, false, false,
1798                            false, 0);
1799     m_page->mainFrame()->eventHandler()->dragSourceEndedAt(pme,
1800         static_cast<DragOperation>(operation));
1801     m_dragScrollTimer->stop();
1802 }
1803
1804 void WebViewImpl::dragSourceMovedTo(
1805     const WebPoint& clientPoint,
1806     const WebPoint& screenPoint,
1807     WebDragOperation operation)
1808 {
1809     m_dragScrollTimer->triggerScroll(mainFrameImpl()->frameView(), clientPoint);
1810 }
1811
1812 void WebViewImpl::dragSourceSystemDragEnded()
1813 {
1814     // It's possible for us to get this callback while not doing a drag if
1815     // it's from a previous page that got unloaded.
1816     if (m_doingDragAndDrop) {
1817         m_page->dragController()->dragEnded();
1818         m_doingDragAndDrop = false;
1819     }
1820 }
1821
1822 WebDragOperation WebViewImpl::dragTargetDragEnter(
1823     const WebDragData& webDragData,
1824     const WebPoint& clientPoint,
1825     const WebPoint& screenPoint,
1826     WebDragOperationsMask operationsAllowed)
1827 {
1828     ASSERT(!m_currentDragData.get());
1829
1830     m_currentDragData = webDragData;
1831     m_operationsAllowed = operationsAllowed;
1832
1833     return dragTargetDragEnterOrOver(clientPoint, screenPoint, DragEnter);
1834 }
1835
1836 WebDragOperation WebViewImpl::dragTargetDragOver(
1837     const WebPoint& clientPoint,
1838     const WebPoint& screenPoint,
1839     WebDragOperationsMask operationsAllowed)
1840 {
1841     m_operationsAllowed = operationsAllowed;
1842
1843     return dragTargetDragEnterOrOver(clientPoint, screenPoint, DragOver);
1844 }
1845
1846 void WebViewImpl::dragTargetDragLeave()
1847 {
1848     ASSERT(m_currentDragData.get());
1849
1850     DragData dragData(
1851         m_currentDragData.get(),
1852         IntPoint(),
1853         IntPoint(),
1854         static_cast<DragOperation>(m_operationsAllowed));
1855
1856     m_page->dragController()->dragExited(&dragData);
1857
1858     // FIXME: why is the drag scroll timer not stopped here?
1859
1860     m_dragOperation = WebDragOperationNone;
1861     m_currentDragData = 0;
1862 }
1863
1864 void WebViewImpl::dragTargetDrop(const WebPoint& clientPoint,
1865                                  const WebPoint& screenPoint)
1866 {
1867     ASSERT(m_currentDragData.get());
1868
1869     // If this webview transitions from the "drop accepting" state to the "not
1870     // accepting" state, then our IPC message reply indicating that may be in-
1871     // flight, or else delayed by javascript processing in this webview.  If a
1872     // drop happens before our IPC reply has reached the browser process, then
1873     // the browser forwards the drop to this webview.  So only allow a drop to
1874     // proceed if our webview m_dragOperation state is not DragOperationNone.
1875
1876     if (m_dragOperation == WebDragOperationNone) { // IPC RACE CONDITION: do not allow this drop.
1877         dragTargetDragLeave();
1878         return;
1879     }
1880
1881     DragData dragData(
1882         m_currentDragData.get(),
1883         clientPoint,
1884         screenPoint,
1885         static_cast<DragOperation>(m_operationsAllowed));
1886
1887     m_page->dragController()->performDrag(&dragData);
1888
1889     m_dragOperation = WebDragOperationNone;
1890     m_currentDragData = 0;
1891
1892     m_dragScrollTimer->stop();
1893 }
1894
1895 WebDragOperation WebViewImpl::dragTargetDragEnterOrOver(const WebPoint& clientPoint, const WebPoint& screenPoint, DragAction dragAction)
1896 {
1897     ASSERT(m_currentDragData.get());
1898
1899     DragData dragData(
1900         m_currentDragData.get(),
1901         clientPoint,
1902         screenPoint,
1903         static_cast<DragOperation>(m_operationsAllowed));
1904
1905     DragOperation dropEffect;
1906     if (dragAction == DragEnter)
1907         dropEffect = m_page->dragController()->dragEntered(&dragData);
1908     else
1909         dropEffect = m_page->dragController()->dragUpdated(&dragData);
1910
1911     // Mask the drop effect operation against the drag source's allowed operations.
1912     if (!(dropEffect & dragData.draggingSourceOperationMask()))
1913         dropEffect = DragOperationNone;
1914
1915      m_dragOperation = static_cast<WebDragOperation>(dropEffect);
1916
1917     if (dragAction == DragOver)
1918         m_dragScrollTimer->triggerScroll(mainFrameImpl()->frameView(), clientPoint);
1919     else
1920         m_dragScrollTimer->stop();
1921
1922     return m_dragOperation;
1923 }
1924
1925 unsigned long WebViewImpl::createUniqueIdentifierForRequest()
1926 {
1927     if (m_page)
1928         return m_page->progress()->createUniqueIdentifier();
1929     return 0;
1930 }
1931
1932 void WebViewImpl::inspectElementAt(const WebPoint& point)
1933 {
1934     if (!m_page.get())
1935         return;
1936
1937     if (point.x == -1 || point.y == -1)
1938         m_page->inspectorController()->inspect(0);
1939     else {
1940         HitTestResult result = hitTestResultForWindowPos(point);
1941
1942         if (!result.innerNonSharedNode())
1943             return;
1944
1945         m_page->inspectorController()->inspect(result.innerNonSharedNode());
1946     }
1947 }
1948
1949 WebString WebViewImpl::inspectorSettings() const
1950 {
1951     return m_inspectorSettings;
1952 }
1953
1954 void WebViewImpl::setInspectorSettings(const WebString& settings)
1955 {
1956     m_inspectorSettings = settings;
1957 }
1958
1959 bool WebViewImpl::inspectorSetting(const WebString& key, WebString* value) const
1960 {
1961     if (!m_inspectorSettingsMap->contains(key))
1962         return false;
1963     *value = m_inspectorSettingsMap->get(key);
1964     return true;
1965 }
1966
1967 void WebViewImpl::setInspectorSetting(const WebString& key,
1968                                       const WebString& value)
1969 {
1970     m_inspectorSettingsMap->set(key, value);
1971     client()->didUpdateInspectorSetting(key, value);
1972 }
1973
1974 WebDevToolsAgent* WebViewImpl::devToolsAgent()
1975 {
1976     return m_devToolsAgent.get();
1977 }
1978
1979 WebAccessibilityObject WebViewImpl::accessibilityObject()
1980 {
1981     if (!mainFrameImpl())
1982         return WebAccessibilityObject();
1983
1984     Document* document = mainFrameImpl()->frame()->document();
1985     return WebAccessibilityObject(
1986         document->axObjectCache()->getOrCreate(document->renderer()));
1987 }
1988
1989 void WebViewImpl::applyAutoFillSuggestions(
1990     const WebNode& node,
1991     const WebVector<WebString>& names,
1992     const WebVector<WebString>& labels,
1993     const WebVector<WebString>& icons,
1994     const WebVector<int>& uniqueIDs,
1995     int separatorIndex)
1996 {
1997     ASSERT(names.size() == labels.size());
1998     ASSERT(names.size() == uniqueIDs.size());
1999     ASSERT(separatorIndex < static_cast<int>(names.size()));
2000
2001     if (names.isEmpty()) {
2002         hideAutoFillPopup();
2003         return;
2004     }
2005
2006     RefPtr<Node> focusedNode = focusedWebCoreNode();
2007     // If the node for which we queried the AutoFill suggestions is not the
2008     // focused node, then we have nothing to do.  FIXME: also check the
2009     // caret is at the end and that the text has not changed.
2010     if (!focusedNode || focusedNode != PassRefPtr<Node>(node)) {
2011         hideAutoFillPopup();
2012         return;
2013     }
2014
2015     HTMLInputElement* inputElem =
2016         static_cast<HTMLInputElement*>(focusedNode.get());
2017
2018     // The first time the AutoFill popup is shown we'll create the client and
2019     // the popup.
2020     if (!m_autoFillPopupClient.get())
2021         m_autoFillPopupClient.set(new AutoFillPopupMenuClient);
2022
2023     m_autoFillPopupClient->initialize(
2024         inputElem, names, labels, icons, uniqueIDs, separatorIndex);
2025
2026     if (!m_autoFillPopup.get()) {
2027         m_autoFillPopup = PopupContainer::create(m_autoFillPopupClient.get(),
2028                                                  PopupContainer::Suggestion,
2029                                                  autoFillPopupSettings);
2030     }
2031
2032     if (m_autoFillPopupShowing) {
2033         refreshAutoFillPopup();
2034     } else {
2035         m_autoFillPopup->showInRect(focusedNode->getRect(), focusedNode->ownerDocument()->view(), 0);
2036         m_autoFillPopupShowing = true;
2037     }
2038 }
2039
2040 void WebViewImpl::hidePopups()
2041 {
2042     hideSelectPopup();
2043     hideAutoFillPopup();
2044 }
2045
2046 void WebViewImpl::performCustomContextMenuAction(unsigned action)
2047 {
2048     if (!m_page)
2049         return;
2050     ContextMenu* menu = m_page->contextMenuController()->contextMenu();
2051     if (!menu)
2052         return;
2053     ContextMenuItem* item = menu->itemWithAction(static_cast<ContextMenuAction>(ContextMenuItemBaseCustomTag + action));
2054     if (item)
2055         m_page->contextMenuController()->contextMenuItemSelected(item);
2056     m_page->contextMenuController()->clearContextMenu();
2057 }
2058
2059 // WebView --------------------------------------------------------------------
2060
2061 void WebViewImpl::setIsTransparent(bool isTransparent)
2062 {
2063     // Set any existing frames to be transparent.
2064     Frame* frame = m_page->mainFrame();
2065     while (frame) {
2066         frame->view()->setTransparent(isTransparent);
2067         frame = frame->tree()->traverseNext();
2068     }
2069
2070     // Future frames check this to know whether to be transparent.
2071     m_isTransparent = isTransparent;
2072 }
2073
2074 bool WebViewImpl::isTransparent() const
2075 {
2076     return m_isTransparent;
2077 }
2078
2079 void WebViewImpl::setIsActive(bool active)
2080 {
2081     if (page() && page()->focusController())
2082         page()->focusController()->setActive(active);
2083 }
2084
2085 bool WebViewImpl::isActive() const
2086 {
2087     return (page() && page()->focusController()) ? page()->focusController()->isActive() : false;
2088 }
2089
2090 void WebViewImpl::setDomainRelaxationForbidden(bool forbidden, const WebString& scheme)
2091 {
2092     SecurityOrigin::setDomainRelaxationForbiddenForURLScheme(forbidden, String(scheme));
2093 }
2094
2095 void WebViewImpl::setScrollbarColors(unsigned inactiveColor,
2096                                      unsigned activeColor,
2097                                      unsigned trackColor) {
2098 #if OS(LINUX) || OS(FREEBSD)
2099     PlatformThemeChromiumGtk::setScrollbarColors(inactiveColor,
2100                                                  activeColor,
2101                                                  trackColor);
2102 #endif
2103 }
2104
2105 void WebViewImpl::setSelectionColors(unsigned activeBackgroundColor,
2106                                      unsigned activeForegroundColor,
2107                                      unsigned inactiveBackgroundColor,
2108                                      unsigned inactiveForegroundColor) {
2109 #if OS(LINUX) || OS(FREEBSD)
2110     RenderThemeChromiumLinux::setSelectionColors(activeBackgroundColor,
2111                                                  activeForegroundColor,
2112                                                  inactiveBackgroundColor,
2113                                                  inactiveForegroundColor);
2114     theme()->platformColorsDidChange();
2115 #endif
2116 }
2117
2118 void WebView::addUserScript(const WebString& sourceCode,
2119                             const WebVector<WebString>& patternsIn,
2120                             WebView::UserScriptInjectAt injectAt,
2121                             WebView::UserContentInjectIn injectIn)
2122 {
2123     OwnPtr<Vector<String> > patterns(new Vector<String>);
2124     for (size_t i = 0; i < patternsIn.size(); ++i)
2125         patterns->append(patternsIn[i]);
2126
2127     PageGroup* pageGroup = PageGroup::pageGroup(pageGroupName);
2128     RefPtr<DOMWrapperWorld> world(DOMWrapperWorld::create());
2129     pageGroup->addUserScriptToWorld(world.get(), sourceCode, WebURL(), patterns.release(), 0,
2130                                     static_cast<UserScriptInjectionTime>(injectAt),
2131                                     static_cast<UserContentInjectedFrames>(injectIn));
2132 }
2133
2134 void WebView::addUserStyleSheet(const WebString& sourceCode,
2135                                 const WebVector<WebString>& patternsIn,
2136                                 WebView::UserContentInjectIn injectIn,
2137                                 WebView::UserStyleInjectionTime injectionTime)
2138 {
2139     OwnPtr<Vector<String> > patterns(new Vector<String>);
2140     for (size_t i = 0; i < patternsIn.size(); ++i)
2141         patterns->append(patternsIn[i]);
2142
2143     PageGroup* pageGroup = PageGroup::pageGroup(pageGroupName);
2144     RefPtr<DOMWrapperWorld> world(DOMWrapperWorld::create());
2145
2146     // FIXME: Current callers always want the level to be "author". It probably makes sense to let
2147     // callers specify this though, since in other cases the caller will probably want "user" level.
2148     //
2149     // FIXME: It would be nice to populate the URL correctly, instead of passing an empty URL.
2150     pageGroup->addUserStyleSheetToWorld(world.get(), sourceCode, WebURL(), patterns.release(), 0,
2151                                         static_cast<UserContentInjectedFrames>(injectIn),
2152                                         UserStyleAuthorLevel,
2153                                         static_cast<WebCore::UserStyleInjectionTime>(injectionTime));
2154 }
2155
2156 void WebView::removeAllUserContent()
2157 {
2158     PageGroup* pageGroup = PageGroup::pageGroup(pageGroupName);
2159     pageGroup->removeAllUserContent();
2160 }
2161
2162 void WebViewImpl::didCommitLoad(bool* isNewNavigation)
2163 {
2164     if (isNewNavigation)
2165         *isNewNavigation = m_observedNewNavigation;
2166
2167 #ifndef NDEBUG
2168     ASSERT(!m_observedNewNavigation
2169         || m_page->mainFrame()->loader()->documentLoader() == m_newNavigationLoader);
2170     m_newNavigationLoader = 0;
2171 #endif
2172     m_observedNewNavigation = false;
2173 }
2174
2175 bool WebViewImpl::useExternalPopupMenus()
2176 {
2177     return shouldUseExternalPopupMenus;
2178 }
2179
2180 bool WebViewImpl::navigationPolicyFromMouseEvent(unsigned short button,
2181                                                  bool ctrl, bool shift,
2182                                                  bool alt, bool meta,
2183                                                  WebNavigationPolicy* policy)
2184 {
2185 #if OS(WINDOWS) || OS(LINUX) || OS(FREEBSD) || OS(SOLARIS)
2186     const bool newTabModifier = (button == 1) || ctrl;
2187 #elif OS(DARWIN)
2188     const bool newTabModifier = (button == 1) || meta;
2189 #endif
2190     if (!newTabModifier && !shift && !alt)
2191       return false;
2192
2193     ASSERT(policy);
2194     if (newTabModifier) {
2195         if (shift)
2196           *policy = WebNavigationPolicyNewForegroundTab;
2197         else
2198           *policy = WebNavigationPolicyNewBackgroundTab;
2199     } else {
2200         if (shift)
2201           *policy = WebNavigationPolicyNewWindow;
2202         else
2203           *policy = WebNavigationPolicyDownload;
2204     }
2205     return true;
2206 }
2207
2208 void WebViewImpl::startDragging(const WebDragData& dragData,
2209                                 WebDragOperationsMask mask,
2210                                 const WebImage& dragImage,
2211                                 const WebPoint& dragImageOffset)
2212 {
2213     if (!m_client)
2214         return;
2215     ASSERT(!m_doingDragAndDrop);
2216     m_doingDragAndDrop = true;
2217     m_client->startDragging(dragData, mask, dragImage, dragImageOffset);
2218 }
2219
2220 void WebViewImpl::observeNewNavigation()
2221 {
2222     m_observedNewNavigation = true;
2223 #ifndef NDEBUG
2224     m_newNavigationLoader = m_page->mainFrame()->loader()->documentLoader();
2225 #endif
2226 }
2227
2228 void WebViewImpl::setIgnoreInputEvents(bool newValue)
2229 {
2230     ASSERT(m_ignoreInputEvents != newValue);
2231     m_ignoreInputEvents = newValue;
2232 }
2233
2234 #if ENABLE(NOTIFICATIONS)
2235 NotificationPresenterImpl* WebViewImpl::notificationPresenterImpl()
2236 {
2237     if (!m_notificationPresenter.isInitialized() && m_client)
2238         m_notificationPresenter.initialize(m_client->notificationPresenter());
2239     return &m_notificationPresenter;
2240 }
2241 #endif
2242
2243 void WebViewImpl::refreshAutoFillPopup()
2244 {
2245     ASSERT(m_autoFillPopupShowing);
2246
2247     // Hide the popup if it has become empty.
2248     if (!m_autoFillPopupClient->listSize()) {
2249         hideAutoFillPopup();
2250         return;
2251     }
2252
2253     IntRect oldBounds = m_autoFillPopup->frameRect();
2254     m_autoFillPopup->refresh(focusedWebCoreNode()->getRect());
2255     IntRect newBounds = m_autoFillPopup->frameRect();
2256     // Let's resize the backing window if necessary.
2257     if (oldBounds != newBounds) {
2258         WebPopupMenuImpl* popupMenu =
2259             static_cast<WebPopupMenuImpl*>(m_autoFillPopup->client());
2260         if (popupMenu)
2261             popupMenu->client()->setWindowRect(newBounds);
2262     }
2263 }
2264
2265 Node* WebViewImpl::focusedWebCoreNode()
2266 {
2267     Frame* frame = m_page->focusController()->focusedFrame();
2268     if (!frame)
2269         return 0;
2270
2271     Document* document = frame->document();
2272     if (!document)
2273         return 0;
2274
2275     return document->focusedNode();
2276 }
2277
2278 HitTestResult WebViewImpl::hitTestResultForWindowPos(const IntPoint& pos)
2279 {
2280     IntPoint docPoint(m_page->mainFrame()->view()->windowToContents(pos));
2281     return m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(docPoint, false);
2282 }
2283
2284 void WebViewImpl::setTabsToLinks(bool enable)
2285 {
2286     m_tabsToLinks = enable;
2287 }
2288
2289 bool WebViewImpl::tabsToLinks() const
2290 {
2291     return m_tabsToLinks;
2292 }
2293
2294 #if USE(ACCELERATED_COMPOSITING)
2295 bool WebViewImpl::allowsAcceleratedCompositing()
2296 {
2297     return !m_compositorCreationFailed;
2298 }
2299
2300 bool WebViewImpl::pageHasRTLStyle() const
2301 {
2302     if (!page())
2303         return false;
2304     Document* document = page()->mainFrame()->document();
2305     if (!document)
2306         return false;
2307     RenderView* renderView = document->renderView();
2308     if (!renderView)
2309         return false;
2310     RenderStyle* style = renderView->style();
2311     if (!style)
2312         return false;
2313     return (style->direction() == RTL);
2314 }
2315
2316 void WebViewImpl::setRootGraphicsLayer(WebCore::PlatformLayer* layer)
2317 {
2318     // FIXME: RTL style not supported by the compositor yet.
2319     setIsAcceleratedCompositingActive(layer && !pageHasRTLStyle() ? true : false);
2320     if (m_layerRenderer)
2321         m_layerRenderer->setRootLayer(layer);
2322
2323     IntRect damagedRect(0, 0, m_size.width, m_size.height);
2324     if (m_isAcceleratedCompositingActive)
2325         invalidateRootLayerRect(damagedRect);
2326     else
2327         m_client->didInvalidateRect(damagedRect);
2328 }
2329
2330 void WebViewImpl::setRootLayerNeedsDisplay()
2331 {
2332     m_client->scheduleComposite();
2333 }
2334
2335
2336 void WebViewImpl::scrollRootLayerRect(const IntSize& scrollDelta, const IntRect& clipRect)
2337 {
2338     updateLayerRendererViewport();
2339     setRootLayerNeedsDisplay();
2340 }
2341
2342 void WebViewImpl::invalidateRootLayerRect(const IntRect& rect)
2343 {
2344     ASSERT(m_layerRenderer);
2345
2346     if (!page())
2347         return;
2348
2349     FrameView* view = page()->mainFrame()->view();
2350     IntRect dirtyRect = view->windowToContents(rect);
2351     updateLayerRendererViewport();
2352     m_layerRenderer->invalidateRootLayerRect(dirtyRect);
2353     setRootLayerNeedsDisplay();
2354 }
2355
2356 class WebViewImplContentPainter : public TilePaintInterface {
2357     WTF_MAKE_NONCOPYABLE(WebViewImplContentPainter);
2358 public:
2359     static PassOwnPtr<WebViewImplContentPainter*> create(WebViewImpl* webViewImpl)
2360     {
2361         return adoptPtr(new WebViewImplContentPainter(webViewImpl));
2362     }
2363
2364     virtual void paint(GraphicsContext& context, const IntRect& contentRect)
2365     {
2366         Page* page = m_webViewImpl->page();
2367         if (!page)
2368             return;
2369         FrameView* view = page->mainFrame()->view();
2370         view->paintContents(&context, contentRect);
2371     }
2372
2373 private:
2374     explicit WebViewImplContentPainter(WebViewImpl* webViewImpl)
2375         : m_webViewImpl(webViewImpl)
2376     {
2377     }
2378
2379     WebViewImpl* m_webViewImpl;
2380 };
2381
2382 void WebViewImpl::setIsAcceleratedCompositingActive(bool active)
2383 {
2384     PlatformBridge::histogramEnumeration("GPU.setIsAcceleratedCompositingActive", active * 2 + m_isAcceleratedCompositingActive, 4);
2385
2386     if (m_isAcceleratedCompositingActive == active)
2387         return;
2388
2389     if (!active) {
2390         m_isAcceleratedCompositingActive = false;
2391         // We need to finish all GL rendering before sending
2392         // didActivateAcceleratedCompositing(false) to prevent
2393         // flickering when compositing turns off.
2394         if (m_layerRenderer)
2395             m_layerRenderer->finish();
2396         m_client->didActivateAcceleratedCompositing(false);
2397     } else if (m_layerRenderer) {
2398         m_isAcceleratedCompositingActive = true;
2399         m_layerRenderer->resizeOnscreenContent(WebCore::IntSize(std::max(1, m_size.width),
2400                                                                 std::max(1, m_size.height)));
2401
2402         m_client->didActivateAcceleratedCompositing(true);
2403     } else {
2404         RefPtr<GraphicsContext3D> context = m_temporaryOnscreenGraphicsContext3D.release();
2405         if (!context) {
2406             context = GraphicsContext3D::create(getCompositorContextAttributes(), m_page->chrome(), GraphicsContext3D::RenderDirectlyToHostWindow);
2407             if (context)
2408                 context->reshape(std::max(1, m_size.width), std::max(1, m_size.height));
2409         }
2410
2411
2412         m_layerRenderer = LayerRendererChromium::create(context.release(), WebViewImplContentPainter::create(this));
2413         if (m_layerRenderer) {
2414             m_client->didActivateAcceleratedCompositing(true);
2415             m_isAcceleratedCompositingActive = true;
2416             m_compositorCreationFailed = false;
2417         } else {
2418             m_isAcceleratedCompositingActive = false;
2419             m_client->didActivateAcceleratedCompositing(false);
2420             m_compositorCreationFailed = true;
2421         }
2422     }
2423     if (page())
2424         page()->mainFrame()->view()->setClipsRepaints(!m_isAcceleratedCompositingActive);
2425 }
2426
2427 void WebViewImpl::doComposite()
2428 {
2429     ASSERT(m_layerRenderer);
2430     if (!m_layerRenderer) {
2431         setIsAcceleratedCompositingActive(false);
2432         return;
2433     }
2434
2435     ASSERT(isAcceleratedCompositingActive());
2436     if (!page())
2437         return;
2438
2439     m_layerRenderer->setCompositeOffscreen(settings()->compositeToTextureEnabled());
2440
2441     CCHeadsUpDisplay* hud = m_layerRenderer->headsUpDisplay();
2442     hud->setShowFPSCounter(settings()->showFPSCounter());
2443     hud->setShowPlatformLayerTree(settings()->showPlatformLayerTree());
2444
2445     m_layerRenderer->updateAndDrawLayers();
2446 }
2447
2448 void WebViewImpl::reallocateRenderer()
2449 {
2450     RefPtr<GraphicsContext3D> newContext = m_temporaryOnscreenGraphicsContext3D.get();
2451     WebGraphicsContext3D* webContext = GraphicsContext3DInternal::extractWebGraphicsContext3D(newContext.get());
2452     if (!newContext || !webContext || webContext->isContextLost())
2453         newContext = GraphicsContext3D::create(
2454             getCompositorContextAttributes(), m_page->chrome(), GraphicsContext3D::RenderDirectlyToHostWindow);
2455     // GraphicsContext3D::create might fail and return 0, in that case LayerRendererChromium::create will also return 0.
2456     RefPtr<LayerRendererChromium> layerRenderer = LayerRendererChromium::create(newContext, WebViewImplContentPainter::create(this));
2457
2458     // Reattach the root layer.  Child layers will get reattached as a side effect of updateLayersRecursive.
2459     if (layerRenderer) {
2460         m_layerRenderer->transferRootLayer(layerRenderer.get());
2461         m_layerRenderer = layerRenderer;
2462         // FIXME: In MacOS newContext->reshape method needs to be called to
2463         // allocate IOSurfaces. All calls to create a context followed by
2464         // reshape should really be extracted into one function; it is not
2465         // immediately obvious that GraphicsContext3D object will not
2466         // function properly until its reshape method is called.
2467         newContext->reshape(std::max(1, m_size.width), std::max(1, m_size.height));
2468         setRootGraphicsLayer(m_layerRenderer->rootLayer());
2469         // Forces ViewHostMsg_DidActivateAcceleratedCompositing to be sent so
2470         // that the browser process can reacquire surfaces.
2471         m_client->didActivateAcceleratedCompositing(true);
2472     } else
2473         setRootGraphicsLayer(0);
2474 }
2475 #endif
2476
2477 void WebViewImpl::updateLayerRendererViewport()
2478 {
2479     ASSERT(m_layerRenderer);
2480
2481     if (!page())
2482         return;
2483
2484     FrameView* view = page()->mainFrame()->view();
2485     IntRect contentRect = view->visibleContentRect(false);
2486     IntRect visibleRect = view->visibleContentRect(true);
2487     IntPoint scroll(view->scrollX(), view->scrollY());
2488
2489     m_layerRenderer->setViewport(visibleRect, contentRect, scroll);
2490 }
2491
2492 WebGraphicsContext3D* WebViewImpl::graphicsContext3D()
2493 {
2494 #if USE(ACCELERATED_COMPOSITING)
2495     if (m_page->settings()->acceleratedCompositingEnabled() && allowsAcceleratedCompositing()) {
2496         if (m_layerRenderer) {
2497             WebGraphicsContext3D* webContext = GraphicsContext3DInternal::extractWebGraphicsContext3D(m_layerRenderer->context());
2498             if (webContext && !webContext->isContextLost())
2499                 return webContext;
2500         }
2501         if (m_temporaryOnscreenGraphicsContext3D) {
2502             WebGraphicsContext3D* webContext = GraphicsContext3DInternal::extractWebGraphicsContext3D(m_temporaryOnscreenGraphicsContext3D.get());
2503             if (webContext && !webContext->isContextLost())
2504                 return webContext;
2505         }
2506         m_temporaryOnscreenGraphicsContext3D = GraphicsContext3D::create(getCompositorContextAttributes(), m_page->chrome(), GraphicsContext3D::RenderDirectlyToHostWindow);
2507         if (m_temporaryOnscreenGraphicsContext3D)
2508             m_temporaryOnscreenGraphicsContext3D->reshape(std::max(1, m_size.width), std::max(1, m_size.height));
2509         return GraphicsContext3DInternal::extractWebGraphicsContext3D(m_temporaryOnscreenGraphicsContext3D.get());
2510     }
2511 #endif
2512     return 0;
2513 }
2514
2515 } // namespace WebKit