2010-12-09 Maciej Stachowiak <mjs@apple.com>
[WebKit.git] / WebKit2 / WebProcess / WebPage / WebPage.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "WebPage.h"
27
28 #include "Arguments.h"
29 #include "DrawingArea.h"
30 #include "InjectedBundle.h"
31 #include "InjectedBundleBackForwardList.h"
32 #include "MessageID.h"
33 #include "NetscapePlugin.h"
34 #include "PageOverlay.h"
35 #include "PluginProcessConnection.h"
36 #include "PluginProcessConnectionManager.h"
37 #include "PluginProxy.h"
38 #include "PluginView.h"
39 #include "WebBackForwardListProxy.h"
40 #include "WebChromeClient.h"
41 #include "WebContextMenu.h"
42 #include "WebContextMenuClient.h"
43 #include "WebContextMessages.h"
44 #include "WebCoreArgumentCoders.h"
45 #include "WebDragClient.h"
46 #include "WebEditorClient.h"
47 #include "WebEvent.h"
48 #include "WebEventConversion.h"
49 #include "WebFrame.h"
50 #include "WebInspector.h"
51 #include "WebInspectorClient.h"
52 #include "WebPageCreationParameters.h"
53 #include "WebPageGroupProxy.h"
54 #include "WebPageProxyMessages.h"
55 #include "WebPopupMenu.h"
56 #include "WebPreferencesStore.h"
57 #include "WebProcess.h"
58 #include "WebProcessProxyMessageKinds.h"
59 #include "WebProcessProxyMessages.h"
60 #include <WebCore/AbstractDatabase.h>
61 #include <WebCore/Chrome.h>
62 #include <WebCore/ContextMenuController.h>
63 #include <WebCore/EventHandler.h>
64 #include <WebCore/FocusController.h>
65 #include <WebCore/Frame.h>
66 #include <WebCore/FrameLoaderTypes.h>
67 #include <WebCore/FrameView.h>
68 #include <WebCore/HistoryItem.h>
69 #include <WebCore/KeyboardEvent.h>
70 #include <WebCore/Page.h>
71 #include <WebCore/PlatformKeyboardEvent.h>
72 #include <WebCore/RenderTreeAsText.h>
73 #include <WebCore/ResourceRequest.h>
74 #include <WebCore/Settings.h>
75 #include <WebCore/SharedBuffer.h>
76 #include <WebCore/SubstituteData.h>
77 #include <runtime/JSLock.h>
78 #include <runtime/JSValue.h>
79
80 #if ENABLE(PLUGIN_PROCESS)
81 // FIXME: This is currently Mac-specific!
82 #include "MachPort.h"
83 #endif
84
85 #if PLATFORM(QT)
86 #include "HitTestResult.h"
87 #endif
88
89 #ifndef NDEBUG
90 #include <wtf/RefCountedLeakCounter.h>
91 #endif
92
93 using namespace JSC;
94 using namespace WebCore;
95
96 namespace WebKit {
97
98 #ifndef NDEBUG
99 static WTF::RefCountedLeakCounter webPageCounter("WebPage");
100 #endif
101
102 PassRefPtr<WebPage> WebPage::create(uint64_t pageID, const WebPageCreationParameters& parameters)
103 {
104     RefPtr<WebPage> page = adoptRef(new WebPage(pageID, parameters));
105
106     if (page->pageGroup()->isVisibleToInjectedBundle() && WebProcess::shared().injectedBundle())
107         WebProcess::shared().injectedBundle()->didCreatePage(page.get());
108
109     return page.release();
110 }
111
112 WebPage::WebPage(uint64_t pageID, const WebPageCreationParameters& parameters)
113     : m_viewSize(parameters.viewSize)
114     , m_drawsBackground(true)
115     , m_drawsTransparentBackground(false)
116     , m_isInRedo(false)
117     , m_isClosed(false)
118     , m_tabToLinks(false)
119 #if PLATFORM(MAC)
120     , m_windowIsVisible(false)
121 #elif PLATFORM(WIN)
122     , m_nativeWindow(parameters.nativeWindow)
123 #endif
124     , m_findController(this)
125     , m_pageID(pageID)
126 {
127     ASSERT(m_pageID);
128
129     Page::PageClients pageClients;
130     pageClients.chromeClient = new WebChromeClient(this);
131     pageClients.contextMenuClient = new WebContextMenuClient(this);
132     pageClients.editorClient = new WebEditorClient(this);
133     pageClients.dragClient = new WebDragClient(this);
134 #if ENABLE(INSPECTOR)
135     pageClients.inspectorClient = new WebInspectorClient(this);
136 #endif
137     pageClients.backForwardClient = WebBackForwardListProxy::create(this);
138     m_page = adoptPtr(new Page(pageClients));
139
140     // Qt does not yet call setIsInWindow. Until it does, just leave
141     // this line out so plug-ins and video will work. Eventually all platforms
142     // should call setIsInWindow and this comment and #if should be removed,
143     // leaving behind the setCanStartMedia call.
144 #if !PLATFORM(QT)
145     m_page->setCanStartMedia(false);
146 #endif
147
148     updatePreferences(parameters.store);
149
150     m_pageGroup = WebProcess::shared().webPageGroup(parameters.pageGroupData);
151     m_page->setGroupName(m_pageGroup->identifier());
152
153     platformInitialize();
154     Settings::setMinDOMTimerInterval(0.004);
155
156     m_drawingArea = DrawingArea::create(parameters.drawingAreaInfo.type, parameters.drawingAreaInfo.identifier, this);
157     m_mainFrame = WebFrame::createMainFrame(this);
158
159     setDrawsBackground(parameters.drawsBackground);
160     setDrawsTransparentBackground(parameters.drawsTransparentBackground);
161
162 #ifndef NDEBUG
163     webPageCounter.increment();
164 #endif
165 }
166
167 WebPage::~WebPage()
168 {
169     if (m_backForwardList)
170         m_backForwardList->detach();
171
172     ASSERT(!m_page);
173
174     m_sandboxExtensionTracker.invalidate();
175
176 #if PLATFORM(MAC)
177     ASSERT(m_pluginViews.isEmpty());
178 #endif
179
180 #ifndef NDEBUG
181     webPageCounter.decrement();
182 #endif
183 }
184
185 CoreIPC::Connection* WebPage::connection() const
186 {
187     return WebProcess::shared().connection();
188 }
189
190 void WebPage::initializeInjectedBundleContextMenuClient(WKBundlePageContextMenuClient* client)
191 {
192     m_contextMenuClient.initialize(client);
193 }
194
195 void WebPage::initializeInjectedBundleEditorClient(WKBundlePageEditorClient* client)
196 {
197     m_editorClient.initialize(client);
198 }
199
200 void WebPage::initializeInjectedBundleFormClient(WKBundlePageFormClient* client)
201 {
202     m_formClient.initialize(client);
203 }
204
205 void WebPage::initializeInjectedBundleLoaderClient(WKBundlePageLoaderClient* client)
206 {
207     m_loaderClient.initialize(client);
208 }
209
210 void WebPage::initializeInjectedBundleUIClient(WKBundlePageUIClient* client)
211 {
212     m_uiClient.initialize(client);
213 }
214
215 PassRefPtr<Plugin> WebPage::createPlugin(const Plugin::Parameters& parameters)
216 {
217     String pluginPath;
218
219     if (!WebProcess::shared().connection()->sendSync(
220             Messages::WebContext::GetPluginPath(parameters.mimeType, parameters.url.string()), 
221             Messages::WebContext::GetPluginPath::Reply(pluginPath), 0)) {
222         return 0;
223     }
224
225     if (pluginPath.isNull())
226         return 0;
227
228 #if ENABLE(PLUGIN_PROCESS)
229     PluginProcessConnection* pluginProcessConnection = PluginProcessConnectionManager::shared().getPluginProcessConnection(pluginPath);
230
231     if (!pluginProcessConnection)
232         return 0;
233
234     return PluginProxy::create(pluginProcessConnection);
235 #else
236     return NetscapePlugin::create(NetscapePluginModule::getOrCreate(pluginPath));
237 #endif
238 }
239
240 String WebPage::renderTreeExternalRepresentation() const
241 {
242     return externalRepresentation(m_mainFrame->coreFrame(), RenderAsTextBehaviorNormal);
243 }
244
245 void WebPage::executeEditingCommand(const String& commandName, const String& argument)
246 {
247     Frame* frame = m_page->focusController()->focusedOrMainFrame();
248     if (!frame)
249         return;
250     frame->editor()->command(commandName).execute(argument);
251 }
252
253 bool WebPage::isEditingCommandEnabled(const String& commandName)
254 {
255     Frame* frame = m_page->focusController()->focusedOrMainFrame();
256     if (!frame)
257         return false;
258     
259     Editor::Command command = frame->editor()->command(commandName);
260     return command.isSupported() && command.isEnabled();
261 }
262     
263 void WebPage::clearMainFrameName()
264 {
265     mainFrame()->coreFrame()->tree()->clearName();
266 }
267
268 #if USE(ACCELERATED_COMPOSITING)
269 void WebPage::changeAcceleratedCompositingMode(WebCore::GraphicsLayer* layer)
270 {
271     if (m_isClosed)
272         return;
273
274     bool compositing = layer;
275     
276     // Tell the UI process that accelerated compositing changed. It may respond by changing
277     // drawing area types.
278     DrawingAreaInfo newDrawingAreaInfo;
279
280     if (!WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::DidChangeAcceleratedCompositing(compositing), Messages::WebPageProxy::DidChangeAcceleratedCompositing::Reply(newDrawingAreaInfo), m_pageID))
281         return;
282     
283     if (newDrawingAreaInfo.type != drawingArea()->info().type) {
284         m_drawingArea = 0;
285         if (newDrawingAreaInfo.type != DrawingAreaInfo::None) {
286             m_drawingArea = DrawingArea::create(newDrawingAreaInfo.type, newDrawingAreaInfo.identifier, this);
287             m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize));
288         }
289     }
290 }
291
292 void WebPage::enterAcceleratedCompositingMode(GraphicsLayer* layer)
293 {
294     changeAcceleratedCompositingMode(layer);
295     m_drawingArea->setRootCompositingLayer(layer);
296 }
297
298 void WebPage::exitAcceleratedCompositingMode()
299 {
300     changeAcceleratedCompositingMode(0);
301 }
302 #endif
303
304 void WebPage::close()
305 {
306     if (m_isClosed)
307         return;
308
309     m_isClosed = true;
310
311     if (pageGroup()->isVisibleToInjectedBundle() && WebProcess::shared().injectedBundle())
312         WebProcess::shared().injectedBundle()->willDestroyPage(this);
313
314 #if ENABLE(INSPECTOR)
315     m_inspector = 0;
316 #endif
317
318     if (m_activePopupMenu) {
319         m_activePopupMenu->disconnectFromPage();
320         m_activePopupMenu = 0;
321     }
322
323     m_sandboxExtensionTracker.invalidate();
324
325     m_mainFrame->coreFrame()->loader()->detachFromParent();
326     m_page.clear();
327
328     m_drawingArea->onPageClose();
329     m_drawingArea.clear();
330
331     WebProcess::shared().removeWebPage(m_pageID);
332 }
333
334 void WebPage::tryClose()
335 {
336     if (!m_mainFrame->coreFrame()->loader()->shouldClose())
337         return;
338
339     sendClose();
340 }
341
342 void WebPage::sendClose()
343 {
344     send(Messages::WebPageProxy::ClosePage());
345 }
346
347 void WebPage::loadURL(const String& url, const SandboxExtension::Handle& sandboxExtensionHandle)
348 {
349     loadURLRequest(ResourceRequest(KURL(KURL(), url)), sandboxExtensionHandle);
350 }
351
352 void WebPage::loadURLRequest(const ResourceRequest& request, const SandboxExtension::Handle& sandboxExtensionHandle)
353 {
354     m_sandboxExtensionTracker.beginLoad(m_mainFrame.get(), sandboxExtensionHandle);
355     m_mainFrame->coreFrame()->loader()->load(request, false);
356 }
357
358 void WebPage::loadData(PassRefPtr<SharedBuffer> sharedBuffer, const String& MIMEType, const String& encodingName, const KURL& baseURL, const KURL& unreachableURL)
359 {
360     ResourceRequest request(baseURL);
361     SubstituteData substituteData(sharedBuffer, MIMEType, encodingName, unreachableURL);
362     m_mainFrame->coreFrame()->loader()->load(request, substituteData, false);
363 }
364
365 void WebPage::loadHTMLString(const String& htmlString, const String& baseURLString)
366 {
367     RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(htmlString.characters()), htmlString.length() * sizeof(UChar));
368     KURL baseURL = baseURLString.isEmpty() ? blankURL() : KURL(KURL(), baseURLString);
369     loadData(sharedBuffer, "text/html", "utf-16", baseURL, KURL());
370 }
371
372 void WebPage::loadAlternateHTMLString(const String& htmlString, const String& baseURLString, const String& unreachableURLString)
373 {
374     RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(htmlString.characters()), htmlString.length() * sizeof(UChar));
375     KURL baseURL = baseURLString.isEmpty() ? blankURL() : KURL(KURL(), baseURLString);
376     KURL unreachableURL = unreachableURLString.isEmpty() ? KURL() : KURL(KURL(), unreachableURLString)  ;
377     loadData(sharedBuffer, "text/html", "utf-16", baseURL, unreachableURL);
378 }
379
380 void WebPage::loadPlainTextString(const String& string)
381 {
382     RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(string.characters()), string.length() * sizeof(UChar));
383     loadData(sharedBuffer, "text/plain", "utf-16", blankURL(), KURL());
384 }
385
386 void WebPage::stopLoading()
387 {
388     m_mainFrame->coreFrame()->loader()->stopForUserCancel();
389 }
390
391 void WebPage::reload(bool reloadFromOrigin)
392 {
393     m_mainFrame->coreFrame()->loader()->reload(reloadFromOrigin);
394 }
395
396 void WebPage::goForward(uint64_t backForwardItemID)
397 {
398     HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
399     m_page->goToItem(item, FrameLoadTypeForward);
400 }
401
402 void WebPage::goBack(uint64_t backForwardItemID)
403 {
404     HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
405     m_page->goToItem(item, FrameLoadTypeBack);
406 }
407
408 void WebPage::goToBackForwardItem(uint64_t backForwardItemID)
409 {
410     HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
411     m_page->goToItem(item, FrameLoadTypeIndexedBackForward);
412 }
413
414 void WebPage::layoutIfNeeded()
415 {
416     if (m_mainFrame->coreFrame()->view())
417         m_mainFrame->coreFrame()->view()->updateLayoutAndStyleIfNeededRecursive();
418 }
419
420 void WebPage::setSize(const WebCore::IntSize& viewSize)
421 {
422 #if ENABLE(TILED_BACKING_STORE)
423     // If we are resizing to content ignore external attempts.
424     if (!m_resizesToContentsLayoutSize.isEmpty())
425         return;
426 #endif
427
428     if (m_viewSize == viewSize)
429         return;
430
431     Frame* frame = m_page->mainFrame();
432     
433     frame->view()->resize(viewSize);
434     frame->view()->setNeedsLayout();
435     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), viewSize));
436     
437     m_viewSize = viewSize;
438 }
439
440 #if ENABLE(TILED_BACKING_STORE)
441 void WebPage::setActualVisibleContentRect(const IntRect& rect)
442 {
443     Frame* frame = m_page->mainFrame();
444
445     frame->view()->setActualVisibleContentRect(rect);
446 }
447
448 void WebPage::setResizesToContentsUsingLayoutSize(const IntSize& targetLayoutSize)
449 {
450     if (m_resizesToContentsLayoutSize == targetLayoutSize)
451         return;
452
453     m_resizesToContentsLayoutSize = targetLayoutSize;
454
455     Frame* frame = m_page->mainFrame();
456     if (m_resizesToContentsLayoutSize.isEmpty()) {
457         frame->view()->setDelegatesScrolling(false);
458         frame->view()->setUseFixedLayout(false);
459         frame->view()->setPaintsEntireContents(false);
460     } else {
461         frame->view()->setDelegatesScrolling(true);
462         frame->view()->setUseFixedLayout(true);
463         frame->view()->setPaintsEntireContents(true);
464         frame->view()->setFixedLayoutSize(m_resizesToContentsLayoutSize);
465     }
466     frame->view()->forceLayout();
467 }
468
469 void WebPage::resizeToContentsIfNeeded()
470 {
471     if (m_resizesToContentsLayoutSize.isEmpty())
472         return;
473
474     Frame* frame = m_page->mainFrame();
475
476     IntSize contentSize = frame->view()->contentsSize();
477     if (contentSize == m_viewSize)
478         return;
479
480     m_viewSize = contentSize;
481     frame->view()->resize(m_viewSize);
482     frame->view()->setNeedsLayout();
483 }
484 #endif
485
486 void WebPage::drawRect(GraphicsContext& graphicsContext, const IntRect& rect)
487 {
488     graphicsContext.save();
489     graphicsContext.clip(rect);
490     m_mainFrame->coreFrame()->view()->paint(&graphicsContext, rect);
491     graphicsContext.restore();
492
493     if (m_pageOverlay) {
494         graphicsContext.save();
495         graphicsContext.clip(rect);
496         m_pageOverlay->drawRect(graphicsContext, rect);
497         graphicsContext.restore();
498     }
499 }
500
501 double WebPage::textZoomFactor() const
502 {
503     Frame* frame = m_mainFrame->coreFrame();
504     if (!frame)
505         return 1;
506     return frame->textZoomFactor();
507 }
508
509 void WebPage::setTextZoomFactor(double zoomFactor)
510 {
511     Frame* frame = m_mainFrame->coreFrame();
512     if (!frame)
513         return;
514     frame->setTextZoomFactor(static_cast<float>(zoomFactor));
515 }
516
517 double WebPage::pageZoomFactor() const
518 {
519     Frame* frame = m_mainFrame->coreFrame();
520     if (!frame)
521         return 1;
522     return frame->pageZoomFactor();
523 }
524
525 void WebPage::setPageZoomFactor(double zoomFactor)
526 {
527     Frame* frame = m_mainFrame->coreFrame();
528     if (!frame)
529         return;
530     frame->setPageZoomFactor(static_cast<float>(zoomFactor));
531 }
532
533 void WebPage::setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor)
534 {
535     Frame* frame = m_mainFrame->coreFrame();
536     if (!frame)
537         return;
538     return frame->setPageAndTextZoomFactors(static_cast<float>(pageZoomFactor), static_cast<float>(textZoomFactor));
539 }
540
541 void WebPage::scaleWebView(double scale, const IntPoint& origin)
542 {
543     Frame* frame = m_mainFrame->coreFrame();
544     if (!frame)
545         return;
546     frame->scalePage(scale, origin);
547 }
548
549 double WebPage::viewScaleFactor() const
550 {
551     Frame* frame = m_mainFrame->coreFrame();
552     if (!frame)
553         return 1;
554     return frame->pageScaleFactor();
555 }
556
557 void WebPage::installPageOverlay(PassRefPtr<PageOverlay> pageOverlay)
558 {
559     if (m_pageOverlay)
560         pageOverlay->setPage(0);
561
562     m_pageOverlay = pageOverlay;
563     m_pageOverlay->setPage(this);
564     m_pageOverlay->setNeedsDisplay();
565 }
566
567 void WebPage::uninstallPageOverlay(PageOverlay* pageOverlay)
568 {
569     if (pageOverlay != m_pageOverlay)
570         return;
571
572     m_pageOverlay->setPage(0);
573     m_pageOverlay = nullptr;
574     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize));
575 }
576
577 void WebPage::pageDidScroll()
578 {
579     // Hide the find indicator.
580     m_findController.hideFindIndicator();
581
582     m_uiClient.pageDidScroll(this);
583
584     send(Messages::WebPageProxy::PageDidScroll());
585 }
586
587 #if ENABLE(TILED_BACKING_STORE)
588 void WebPage::pageDidRequestScroll(const IntSize& delta)
589 {
590     send(Messages::WebPageProxy::PageDidRequestScroll(delta));
591 }
592 #endif
593
594 WebContextMenu* WebPage::contextMenu()
595 {
596     if (!m_contextMenu)
597         m_contextMenu = WebContextMenu::create(this);
598     return m_contextMenu.get();
599 }
600
601 // Events 
602
603 static const WebEvent* g_currentEvent = 0;
604
605 // FIXME: WebPage::currentEvent is used by the plug-in code to avoid having to convert from DOM events back to
606 // WebEvents. When we get the event handling sorted out, this should go away and the Widgets should get the correct
607 // platform events passed to the event handler code.
608 const WebEvent* WebPage::currentEvent()
609 {
610     return g_currentEvent;
611 }
612
613 class CurrentEvent {
614 public:
615     explicit CurrentEvent(const WebEvent& event)
616         : m_previousCurrentEvent(g_currentEvent)
617     {
618         g_currentEvent = &event;
619     }
620
621     ~CurrentEvent()
622     {
623         g_currentEvent = m_previousCurrentEvent;
624     }
625
626 private:
627     const WebEvent* m_previousCurrentEvent;
628 };
629
630 static bool isContextClick(const PlatformMouseEvent& event)
631 {
632     if (event.button() == WebCore::RightButton)
633         return true;
634
635 #if PLATFORM(MAC)
636     // FIXME: this really should be about OSX-style UI, not about the Mac port
637     if (event.button() == WebCore::LeftButton && event.ctrlKey())
638         return true;
639 #endif
640
641     return false;
642 }
643
644 static bool handleMouseEvent(const WebMouseEvent& mouseEvent, Page* page)
645 {
646     Frame* frame = page->mainFrame();
647     if (!frame->view())
648         return false;
649
650     PlatformMouseEvent platformMouseEvent = platform(mouseEvent);
651
652     switch (platformMouseEvent.eventType()) {
653         case WebCore::MouseEventPressed:
654         {
655             if (isContextClick(platformMouseEvent))
656                 page->contextMenuController()->clearContextMenu();
657             
658             bool handled = frame->eventHandler()->handleMousePressEvent(platformMouseEvent);
659             
660             if (isContextClick(platformMouseEvent)) {
661                 handled = frame->eventHandler()->sendContextMenuEvent(platformMouseEvent);
662                 if (handled)
663                     page->chrome()->showContextMenu();
664             }
665
666             return handled;
667         }
668         case WebCore::MouseEventReleased:
669             return frame->eventHandler()->handleMouseReleaseEvent(platformMouseEvent);
670         case WebCore::MouseEventMoved:
671             return frame->eventHandler()->mouseMoved(platformMouseEvent);
672         default:
673             ASSERT_NOT_REACHED();
674             return false;
675     }
676 }
677
678 void WebPage::mouseEvent(const WebMouseEvent& mouseEvent)
679 {
680     bool handled = false;
681     
682     if (m_pageOverlay) {
683         // Let the page overlay handle the event.
684         handled = m_pageOverlay->mouseEvent(mouseEvent);
685     }
686
687     if (!handled) {
688         CurrentEvent currentEvent(mouseEvent);
689
690         handled = handleMouseEvent(mouseEvent, m_page.get());
691     }
692
693     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(mouseEvent.type()), handled));
694 }
695
696 static bool handleWheelEvent(const WebWheelEvent& wheelEvent, Page* page)
697 {
698     Frame* frame = page->mainFrame();
699     if (!frame->view())
700         return false;
701
702     PlatformWheelEvent platformWheelEvent = platform(wheelEvent);
703     return frame->eventHandler()->handleWheelEvent(platformWheelEvent);
704 }
705
706 void WebPage::wheelEvent(const WebWheelEvent& wheelEvent)
707 {
708     CurrentEvent currentEvent(wheelEvent);
709
710     bool handled = handleWheelEvent(wheelEvent, m_page.get());
711     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(wheelEvent.type()), handled));
712 }
713
714 static bool handleKeyEvent(const WebKeyboardEvent& keyboardEvent, Page* page)
715 {
716     if (!page->mainFrame()->view())
717         return false;
718
719     if (keyboardEvent.type() == WebEvent::Char && keyboardEvent.isSystemKey())
720         return page->focusController()->focusedOrMainFrame()->eventHandler()->handleAccessKey(platform(keyboardEvent));
721     return page->focusController()->focusedOrMainFrame()->eventHandler()->keyEvent(platform(keyboardEvent));
722 }
723
724 void WebPage::keyEvent(const WebKeyboardEvent& keyboardEvent)
725 {
726     CurrentEvent currentEvent(keyboardEvent);
727
728     bool handled = handleKeyEvent(keyboardEvent, m_page.get());
729     if (!handled)
730         handled = performDefaultBehaviorForKeyEvent(keyboardEvent);
731
732     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(keyboardEvent.type()), handled));
733 }
734
735 void WebPage::validateMenuItem(const String& commandName)
736 {
737     bool isEnabled = false;
738     int32_t state = 0;
739     Frame* frame = m_page->focusController()->focusedOrMainFrame();
740     if (frame) {
741         Editor::Command command = frame->editor()->command(commandName);
742         state = command.state();
743         isEnabled = command.isSupported() && command.isEnabled();
744     }
745
746     send(Messages::WebPageProxy::DidValidateMenuItem(commandName, isEnabled, state));
747 }
748
749 void WebPage::executeEditCommand(const String& commandName)
750 {
751     executeEditingCommand(commandName, String());
752 }
753
754 #if ENABLE(TOUCH_EVENTS)
755 static bool handleTouchEvent(const WebTouchEvent& touchEvent, Page* page)
756 {
757     Frame* frame = page->mainFrame();
758     if (!frame->view())
759         return false;
760
761     return frame->eventHandler()->handleTouchEvent(platform(touchEvent));
762 }
763
764 void WebPage::touchEvent(const WebTouchEvent& touchEvent)
765 {
766     CurrentEvent currentEvent(touchEvent);
767
768     bool handled = handleTouchEvent(touchEvent, m_page.get());
769
770     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(touchEvent.type()), handled));
771 }
772 #endif
773
774 void WebPage::setActive(bool isActive)
775 {
776     m_page->focusController()->setActive(isActive);
777
778 #if PLATFORM(MAC)    
779     // Tell all our plug-in views that the window focus changed.
780     for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
781         (*it)->setWindowIsFocused(isActive);
782 #endif
783 }
784
785 void WebPage::setDrawsBackground(bool drawsBackground)
786 {
787     if (m_drawsBackground == drawsBackground)
788         return;
789
790     m_drawsBackground = drawsBackground;
791
792     for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
793         if (FrameView* view = coreFrame->view())
794             view->setTransparent(!drawsBackground);
795     }
796
797     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize));
798 }
799
800 void WebPage::setDrawsTransparentBackground(bool drawsTransparentBackground)
801 {
802     if (m_drawsTransparentBackground == drawsTransparentBackground)
803         return;
804
805     m_drawsTransparentBackground = drawsTransparentBackground;
806
807     Color backgroundColor = drawsTransparentBackground ? Color::transparent : Color::white;
808     for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
809         if (FrameView* view = coreFrame->view())
810             view->setBaseBackgroundColor(backgroundColor);
811     }
812
813     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize));
814 }
815
816 void WebPage::setFocused(bool isFocused)
817 {
818     m_page->focusController()->setFocused(isFocused);
819 }
820
821 void WebPage::setWindowResizerSize(const IntSize& windowResizerSize)
822 {
823     if (m_windowResizerSize == windowResizerSize)
824         return;
825
826     m_windowResizerSize = windowResizerSize;
827
828     for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
829         FrameView* view = coreFrame->view();
830         if (view)
831             view->windowResizerRectChanged();
832     }
833 }
834
835 void WebPage::setIsInWindow(bool isInWindow)
836 {
837     if (!isInWindow) {
838         m_page->setCanStartMedia(false);
839         m_page->willMoveOffscreen();
840     } else {
841         m_page->setCanStartMedia(true);
842         m_page->didMoveOnscreen();
843     }
844 }
845
846 void WebPage::didReceivePolicyDecision(uint64_t frameID, uint64_t listenerID, uint32_t policyAction, uint64_t downloadID)
847 {
848     WebFrame* frame = WebProcess::shared().webFrame(frameID);
849     if (!frame)
850         return;
851     frame->didReceivePolicyDecision(listenerID, static_cast<PolicyAction>(policyAction), downloadID);
852 }
853
854 void WebPage::show()
855 {
856     send(Messages::WebPageProxy::ShowPage());
857 }
858
859 void WebPage::setCustomUserAgent(const String& customUserAgent)
860 {
861     m_customUserAgent = customUserAgent;
862 }
863
864 String WebPage::userAgent() const
865 {
866     if (!m_customUserAgent.isEmpty())
867         return m_customUserAgent;
868
869     // FIXME: This should be based on an application name.
870     return "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6; en-us) AppleWebKit/531.4 (KHTML, like Gecko) Version/4.0.3 Safari/531.4";
871 }
872
873 IntRect WebPage::windowResizerRect() const
874 {
875     if (m_windowResizerSize.isEmpty())
876         return IntRect();
877
878     IntSize frameViewSize;
879     if (Frame* coreFrame = m_mainFrame->coreFrame()) {
880         if (FrameView* view = coreFrame->view())
881             frameViewSize = view->size();
882     }
883
884     return IntRect(frameViewSize.width() - m_windowResizerSize.width(), frameViewSize.height() - m_windowResizerSize.height(), 
885                    m_windowResizerSize.width(), m_windowResizerSize.height());
886 }
887
888 void WebPage::runJavaScriptInMainFrame(const String& script, uint64_t callbackID)
889 {
890     // NOTE: We need to be careful when running scripts that the objects we depend on don't
891     // disappear during script execution.
892
893     JSLock lock(SilenceAssertionsOnly);
894     JSValue resultValue = m_mainFrame->coreFrame()->script()->executeScript(script, true).jsValue();
895     String resultString;
896     if (resultValue)
897         resultString = ustringToString(resultValue.toString(m_mainFrame->coreFrame()->script()->globalObject(mainThreadNormalWorld())->globalExec()));
898
899     send(Messages::WebPageProxy::DidRunJavaScriptInMainFrame(resultString, callbackID));
900 }
901
902 void WebPage::getContentsAsString(uint64_t callbackID)
903 {
904     String resultString = m_mainFrame->contentsAsString();
905     send(Messages::WebPageProxy::DidGetContentsAsString(resultString, callbackID));
906 }
907
908 void WebPage::getRenderTreeExternalRepresentation(uint64_t callbackID)
909 {
910     String resultString = renderTreeExternalRepresentation();
911     send(Messages::WebPageProxy::DidGetRenderTreeExternalRepresentation(resultString, callbackID));
912 }
913
914 void WebPage::getSourceForFrame(uint64_t frameID, uint64_t callbackID)
915 {
916     String resultString;
917     if (WebFrame* frame = WebProcess::shared().webFrame(frameID))
918        resultString = frame->source();
919
920     send(Messages::WebPageProxy::DidGetSourceForFrame(resultString, callbackID));
921 }
922
923 void WebPage::preferencesDidChange(const WebPreferencesStore& store)
924 {
925     WebPreferencesStore::removeTestRunnerOverrides();
926     updatePreferences(store);
927 }
928
929 void WebPage::updatePreferences(const WebPreferencesStore& store)
930 {
931     Settings* settings = m_page->settings();
932
933     m_tabToLinks = store.getBoolValueForKey(WebPreferencesKey::tabsToLinksKey());
934
935     // FIXME: This should be generated from macro expansion for all preferences,
936     // but we currently don't match the naming of WebCore exactly so we are
937     // handrolling the boolean and integer preferences until that is fixed.
938
939 #define INITIALIZE_SETTINGS(KeyUpper, KeyLower, TypeName, Type, DefaultValue) settings->set##KeyUpper(store.get##TypeName##ValueForKey(WebPreferencesKey::KeyLower##Key()));
940
941     FOR_EACH_WEBKIT_STRING_PREFERENCE(INITIALIZE_SETTINGS)
942
943 #undef INITIALIZE_SETTINGS
944
945     settings->setJavaScriptEnabled(store.getBoolValueForKey(WebPreferencesKey::javaScriptEnabledKey()));
946     settings->setLoadsImagesAutomatically(store.getBoolValueForKey(WebPreferencesKey::loadsImagesAutomaticallyKey()));
947     settings->setPluginsEnabled(store.getBoolValueForKey(WebPreferencesKey::pluginsEnabledKey()));
948     settings->setJavaEnabled(store.getBoolValueForKey(WebPreferencesKey::javaEnabledKey()));
949     settings->setOfflineWebApplicationCacheEnabled(store.getBoolValueForKey(WebPreferencesKey::offlineWebApplicationCacheEnabledKey()));
950     settings->setLocalStorageEnabled(store.getBoolValueForKey(WebPreferencesKey::localStorageEnabledKey()));
951     settings->setXSSAuditorEnabled(store.getBoolValueForKey(WebPreferencesKey::xssAuditorEnabledKey()));
952     settings->setFrameFlatteningEnabled(store.getBoolValueForKey(WebPreferencesKey::frameFlatteningEnabledKey()));
953     settings->setPrivateBrowsingEnabled(store.getBoolValueForKey(WebPreferencesKey::privateBrowsingEnabledKey()));
954     settings->setDeveloperExtrasEnabled(store.getBoolValueForKey(WebPreferencesKey::developerExtrasEnabledKey()));
955     settings->setTextAreasAreResizable(store.getBoolValueForKey(WebPreferencesKey::textAreasAreResizableKey()));
956     settings->setNeedsSiteSpecificQuirks(store.getBoolValueForKey(WebPreferencesKey::needsSiteSpecificQuirksKey()));
957     settings->setJavaScriptCanOpenWindowsAutomatically(store.getBoolValueForKey(WebPreferencesKey::javaScriptCanOpenWindowsAutomaticallyKey()));
958     settings->setForceFTPDirectoryListings(store.getBoolValueForKey(WebPreferencesKey::forceFTPDirectoryListingsKey()));
959     settings->setMinimumFontSize(store.getUInt32ValueForKey(WebPreferencesKey::minimumFontSizeKey()));
960     settings->setMinimumLogicalFontSize(store.getUInt32ValueForKey(WebPreferencesKey::minimumLogicalFontSizeKey()));
961     settings->setDefaultFontSize(store.getUInt32ValueForKey(WebPreferencesKey::defaultFontSizeKey()));
962     settings->setDefaultFixedFontSize(store.getUInt32ValueForKey(WebPreferencesKey::defaultFixedFontSizeKey()));
963
964 #if PLATFORM(WIN)
965     // Temporarily turn off accelerated compositing until we have a good solution for rendering it.
966     settings->setAcceleratedCompositingEnabled(false);
967 #else
968     settings->setAcceleratedCompositingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedCompositingEnabledKey()));
969 #endif
970     settings->setShowDebugBorders(store.getBoolValueForKey(WebPreferencesKey::compositingBordersVisibleKey()));
971     settings->setShowRepaintCounter(store.getBoolValueForKey(WebPreferencesKey::compositingRepaintCountersVisibleKey()));
972
973 #if ENABLE(DATABASE)
974     AbstractDatabase::setIsAvailable(store.getBoolValueForKey(WebPreferencesKey::databasesEnabledKey()));
975 #endif
976     
977     platformPreferencesDidChange(store);
978 }
979
980 #if ENABLE(INSPECTOR)
981 WebInspector* WebPage::inspector()
982 {
983     if (m_isClosed)
984         return 0;
985     if (!m_inspector)
986         m_inspector = adoptPtr(new WebInspector(this));
987     return m_inspector.get();
988 }
989 #endif
990
991 #if !PLATFORM(MAC)
992 bool WebPage::handleEditingKeyboardEvent(KeyboardEvent* evt)
993 {
994     Node* node = evt->target()->toNode();
995     ASSERT(node);
996     Frame* frame = node->document()->frame();
997     ASSERT(frame);
998
999     const PlatformKeyboardEvent* keyEvent = evt->keyEvent();
1000     if (!keyEvent)
1001         return false;
1002
1003     Editor::Command command = frame->editor()->command(interpretKeyEvent(evt));
1004
1005     if (keyEvent->type() == PlatformKeyboardEvent::RawKeyDown) {
1006         // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated,
1007         // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated
1008         // (e.g. Tab that inserts a Tab character, or Enter).
1009         return !command.isTextInsertion() && command.execute(evt);
1010     }
1011
1012     if (command.execute(evt))
1013         return true;
1014
1015     // Don't insert null or control characters as they can result in unexpected behaviour
1016     if (evt->charCode() < ' ')
1017         return false;
1018
1019     return frame->editor()->insertText(evt->keyEvent()->text(), evt);
1020 }
1021 #endif
1022     
1023 WebEditCommand* WebPage::webEditCommand(uint64_t commandID)
1024 {
1025     return m_editCommandMap.get(commandID).get();
1026 }
1027
1028 void WebPage::addWebEditCommand(uint64_t commandID, WebEditCommand* command)
1029 {
1030     m_editCommandMap.set(commandID, command);
1031 }
1032
1033 void WebPage::removeWebEditCommand(uint64_t commandID)
1034 {
1035     m_editCommandMap.remove(commandID);
1036 }
1037
1038 void WebPage::unapplyEditCommand(uint64_t commandID)
1039 {
1040     WebEditCommand* command = webEditCommand(commandID);
1041     if (!command)
1042         return;
1043
1044     command->command()->unapply();
1045 }
1046
1047 void WebPage::reapplyEditCommand(uint64_t commandID)
1048 {
1049     WebEditCommand* command = webEditCommand(commandID);
1050     if (!command)
1051         return;
1052
1053     m_isInRedo = true;
1054     command->command()->reapply();
1055     m_isInRedo = false;
1056 }
1057
1058 void WebPage::didRemoveEditCommand(uint64_t commandID)
1059 {
1060     removeWebEditCommand(commandID);
1061 }
1062
1063 void WebPage::setActivePopupMenu(WebPopupMenu* menu)
1064 {
1065     m_activePopupMenu = menu;
1066 }
1067
1068 bool WebPage::findStringFromInjectedBundle(const String& target, FindOptions options)
1069 {
1070     return m_page->findString(target, options);
1071 }
1072
1073 void WebPage::findString(const String& string, uint32_t options, uint32_t maxMatchCount)
1074 {
1075     m_findController.findString(string, static_cast<FindOptions>(options), maxMatchCount);
1076 }
1077
1078 void WebPage::hideFindUI()
1079 {
1080     m_findController.hideFindUI();
1081 }
1082
1083 void WebPage::countStringMatches(const String& string, uint32_t options, uint32_t maxMatchCount)
1084 {
1085     m_findController.countStringMatches(string, static_cast<FindOptions>(options), maxMatchCount);
1086 }
1087
1088 void WebPage::didChangeSelectedIndexForActivePopupMenu(int32_t newIndex)
1089 {
1090     if (!m_activePopupMenu)
1091         return;
1092
1093     m_activePopupMenu->didChangeSelectedIndex(newIndex);
1094     m_activePopupMenu = 0;
1095 }
1096
1097 void WebPage::didSelectItemFromActiveContextMenu(const WebContextMenuItemData& item)
1098 {
1099     ASSERT(m_contextMenu);
1100     m_contextMenu->itemSelected(item);
1101     m_contextMenu = 0;
1102 }
1103
1104 #if PLATFORM(MAC)
1105
1106 void WebPage::addPluginView(PluginView* pluginView)
1107 {
1108     ASSERT(!m_pluginViews.contains(pluginView));
1109
1110     m_pluginViews.add(pluginView);
1111 }
1112
1113 void WebPage::removePluginView(PluginView* pluginView)
1114 {
1115     ASSERT(m_pluginViews.contains(pluginView));
1116
1117     m_pluginViews.remove(pluginView);
1118 }
1119
1120 void WebPage::setWindowIsVisible(bool windowIsVisible)
1121 {
1122     m_windowIsVisible = windowIsVisible;
1123
1124     // Tell all our plug-in views that the window visibility changed.
1125     for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
1126         (*it)->setWindowIsVisible(windowIsVisible);
1127 }
1128
1129 void WebPage::windowAndViewFramesChanged(const WebCore::IntRect& windowFrameInScreenCoordinates, const WebCore::IntRect& viewFrameInWindowCoordinates)
1130 {
1131     m_windowFrameInScreenCoordinates = windowFrameInScreenCoordinates;
1132     m_viewFrameInWindowCoordinates = viewFrameInWindowCoordinates;
1133
1134     // Tell all our plug-in views that the window and view frames have changed.
1135     for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
1136         (*it)->windowAndViewFramesChanged(windowFrameInScreenCoordinates, viewFrameInWindowCoordinates);
1137 }
1138
1139 bool WebPage::windowIsFocused() const
1140 {
1141     return m_page->focusController()->isActive();
1142 }
1143
1144 #endif
1145
1146 void WebPage::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
1147 {
1148     if (messageID.is<CoreIPC::MessageClassDrawingArea>()) {
1149         if (m_drawingArea)
1150             m_drawingArea->didReceiveMessage(connection, messageID, arguments);
1151         return;
1152     }
1153
1154 #if ENABLE(INSPECTOR)
1155     if (messageID.is<CoreIPC::MessageClassWebInspector>()) {
1156         if (WebInspector* inspector = this->inspector())
1157             inspector->didReceiveWebInspectorMessage(connection, messageID, arguments);
1158         return;
1159     }
1160 #endif
1161
1162     didReceiveWebPageMessage(connection, messageID, arguments);
1163 }
1164
1165 InjectedBundleBackForwardList* WebPage::backForwardList()
1166 {
1167     if (!m_backForwardList)
1168         m_backForwardList = InjectedBundleBackForwardList::create(this);
1169     return m_backForwardList.get();
1170 }
1171
1172 #if PLATFORM(QT)
1173 void WebPage::findZoomableAreaForPoint(const WebCore::IntPoint& point)
1174 {
1175     const int minimumZoomTargetWidth = 100;
1176
1177     Frame* mainframe = m_mainFrame->coreFrame();
1178     HitTestResult result = mainframe->eventHandler()->hitTestResultAtPoint(mainframe->view()->windowToContents(point), /*allowShadowContent*/ false, /*ignoreClipping*/ true);
1179
1180     Node* node = result.innerNode();
1181     while (node && node->getRect().width() < minimumZoomTargetWidth)
1182         node = node->parentNode();
1183
1184     IntRect zoomableArea;
1185     if (node)
1186         zoomableArea = node->getRect();
1187     send(Messages::WebPageProxy::DidFindZoomableArea(zoomableArea));
1188 }
1189 #endif
1190
1191 WebPage::SandboxExtensionTracker::~SandboxExtensionTracker()
1192 {
1193     invalidate();
1194 }
1195
1196 void WebPage::SandboxExtensionTracker::invalidate()
1197 {
1198     if (m_pendingProvisionalSandboxExtension) {
1199         m_pendingProvisionalSandboxExtension->invalidate();
1200         m_pendingProvisionalSandboxExtension = 0;
1201     }
1202
1203     if (m_provisionalSandboxExtension) {
1204         m_provisionalSandboxExtension->invalidate();
1205         m_provisionalSandboxExtension = 0;
1206     }
1207
1208     if (m_committedSandboxExtension) {
1209         m_committedSandboxExtension->invalidate();
1210         m_committedSandboxExtension = 0;
1211     }
1212 }
1213
1214 void WebPage::SandboxExtensionTracker::beginLoad(WebFrame* frame, const SandboxExtension::Handle& handle)
1215 {
1216     ASSERT(frame->isMainFrame());
1217
1218     ASSERT(!m_pendingProvisionalSandboxExtension);
1219     m_pendingProvisionalSandboxExtension = SandboxExtension::create(handle);
1220 }
1221
1222 void WebPage::SandboxExtensionTracker::didStartProvisionalLoad(WebFrame* frame)
1223 {
1224     if (!frame->isMainFrame())
1225         return;
1226
1227     ASSERT(!m_provisionalSandboxExtension);
1228
1229     m_provisionalSandboxExtension = m_pendingProvisionalSandboxExtension.release();
1230     if (!m_provisionalSandboxExtension)
1231         return;
1232
1233     m_provisionalSandboxExtension->consume();
1234 }
1235
1236 void WebPage::SandboxExtensionTracker::didCommitProvisionalLoad(WebFrame* frame)
1237 {
1238     if (!frame->isMainFrame())
1239         return;
1240     
1241     ASSERT(!m_pendingProvisionalSandboxExtension);
1242
1243     // The provisional load has been committed. Invalidate the currently committed sandbox
1244     // extension and make the provisional sandbox extension the committed sandbox extension.
1245     if (m_committedSandboxExtension)
1246         m_committedSandboxExtension->invalidate();
1247
1248     m_committedSandboxExtension = m_provisionalSandboxExtension.release();
1249 }
1250
1251 void WebPage::SandboxExtensionTracker::didFailProvisionalLoad(WebFrame* frame)
1252 {
1253     if (!frame->isMainFrame())
1254         return;
1255
1256     ASSERT(!m_pendingProvisionalSandboxExtension);
1257     if (!m_provisionalSandboxExtension)
1258         return;
1259
1260     m_provisionalSandboxExtension->invalidate();
1261     m_provisionalSandboxExtension = 0;
1262 }
1263
1264 } // namespace WebKit