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