e72546664c018ee26fc57bbc092455bb31f60328
[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 handleMouseEvent(const WebMouseEvent& mouseEvent, Page* page)
631 {
632     Frame* frame = page->mainFrame();
633     if (!frame->view())
634         return false;
635
636     PlatformMouseEvent platformMouseEvent = platform(mouseEvent);
637
638     switch (platformMouseEvent.eventType()) {
639         case WebCore::MouseEventPressed:
640         {
641             if (platformMouseEvent.button() == WebCore::RightButton)
642                 page->contextMenuController()->clearContextMenu();
643             
644             bool handled = frame->eventHandler()->handleMousePressEvent(platformMouseEvent);
645             
646             if (platformMouseEvent.button() == WebCore::RightButton) {
647                 handled = frame->eventHandler()->sendContextMenuEvent(platformMouseEvent);
648                 if (handled)
649                     page->chrome()->showContextMenu();
650             }
651
652             return handled;
653         }
654         case WebCore::MouseEventReleased:
655             return frame->eventHandler()->handleMouseReleaseEvent(platformMouseEvent);
656         case WebCore::MouseEventMoved:
657             return frame->eventHandler()->mouseMoved(platformMouseEvent);
658         default:
659             ASSERT_NOT_REACHED();
660             return false;
661     }
662 }
663
664 void WebPage::mouseEvent(const WebMouseEvent& mouseEvent)
665 {
666     bool handled = false;
667     
668     if (m_pageOverlay) {
669         // Let the page overlay handle the event.
670         handled = m_pageOverlay->mouseEvent(mouseEvent);
671     }
672
673     if (!handled) {
674         CurrentEvent currentEvent(mouseEvent);
675
676         handled = handleMouseEvent(mouseEvent, m_page.get());
677     }
678
679     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(mouseEvent.type()), handled));
680 }
681
682 static bool handleWheelEvent(const WebWheelEvent& wheelEvent, Page* page)
683 {
684     Frame* frame = page->mainFrame();
685     if (!frame->view())
686         return false;
687
688     PlatformWheelEvent platformWheelEvent = platform(wheelEvent);
689     return frame->eventHandler()->handleWheelEvent(platformWheelEvent);
690 }
691
692 void WebPage::wheelEvent(const WebWheelEvent& wheelEvent)
693 {
694     CurrentEvent currentEvent(wheelEvent);
695
696     bool handled = handleWheelEvent(wheelEvent, m_page.get());
697     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(wheelEvent.type()), handled));
698 }
699
700 static bool handleKeyEvent(const WebKeyboardEvent& keyboardEvent, Page* page)
701 {
702     if (!page->mainFrame()->view())
703         return false;
704
705     if (keyboardEvent.type() == WebEvent::Char && keyboardEvent.isSystemKey())
706         return page->focusController()->focusedOrMainFrame()->eventHandler()->handleAccessKey(platform(keyboardEvent));
707     return page->focusController()->focusedOrMainFrame()->eventHandler()->keyEvent(platform(keyboardEvent));
708 }
709
710 void WebPage::keyEvent(const WebKeyboardEvent& keyboardEvent)
711 {
712     CurrentEvent currentEvent(keyboardEvent);
713
714     bool handled = handleKeyEvent(keyboardEvent, m_page.get());
715     if (!handled)
716         handled = performDefaultBehaviorForKeyEvent(keyboardEvent);
717
718     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(keyboardEvent.type()), handled));
719 }
720
721 void WebPage::validateMenuItem(const String& commandName)
722 {
723     bool isEnabled = false;
724     int32_t state = 0;
725     Frame* frame = m_page->focusController()->focusedOrMainFrame();
726     if (frame) {
727         Editor::Command command = frame->editor()->command(commandName);
728         state = command.state();
729         isEnabled = command.isSupported() && command.isEnabled();
730     }
731
732     send(Messages::WebPageProxy::DidValidateMenuItem(commandName, isEnabled, state));
733 }
734
735 void WebPage::executeEditCommand(const String& commandName)
736 {
737     executeEditingCommand(commandName, String());
738 }
739
740 #if ENABLE(TOUCH_EVENTS)
741 static bool handleTouchEvent(const WebTouchEvent& touchEvent, Page* page)
742 {
743     Frame* frame = page->mainFrame();
744     if (!frame->view())
745         return false;
746
747     return frame->eventHandler()->handleTouchEvent(platform(touchEvent));
748 }
749
750 void WebPage::touchEvent(const WebTouchEvent& touchEvent)
751 {
752     CurrentEvent currentEvent(touchEvent);
753
754     bool handled = handleTouchEvent(touchEvent, m_page.get());
755
756     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(touchEvent.type()), handled));
757 }
758 #endif
759
760 void WebPage::setActive(bool isActive)
761 {
762     m_page->focusController()->setActive(isActive);
763
764 #if PLATFORM(MAC)    
765     // Tell all our plug-in views that the window focus changed.
766     for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
767         (*it)->setWindowIsFocused(isActive);
768 #endif
769 }
770
771 void WebPage::setDrawsBackground(bool drawsBackground)
772 {
773     if (m_drawsBackground == drawsBackground)
774         return;
775
776     m_drawsBackground = drawsBackground;
777
778     for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
779         if (FrameView* view = coreFrame->view())
780             view->setTransparent(!drawsBackground);
781     }
782
783     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize));
784 }
785
786 void WebPage::setDrawsTransparentBackground(bool drawsTransparentBackground)
787 {
788     if (m_drawsTransparentBackground == drawsTransparentBackground)
789         return;
790
791     m_drawsTransparentBackground = drawsTransparentBackground;
792
793     Color backgroundColor = drawsTransparentBackground ? Color::transparent : Color::white;
794     for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
795         if (FrameView* view = coreFrame->view())
796             view->setBaseBackgroundColor(backgroundColor);
797     }
798
799     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize));
800 }
801
802 void WebPage::setFocused(bool isFocused)
803 {
804     m_page->focusController()->setFocused(isFocused);
805 }
806
807 void WebPage::setWindowResizerSize(const IntSize& windowResizerSize)
808 {
809     if (m_windowResizerSize == windowResizerSize)
810         return;
811
812     m_windowResizerSize = windowResizerSize;
813
814     for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
815         FrameView* view = coreFrame->view();
816         if (view)
817             view->windowResizerRectChanged();
818     }
819 }
820
821 void WebPage::setIsInWindow(bool isInWindow)
822 {
823     if (!isInWindow) {
824         m_page->setCanStartMedia(false);
825         m_page->willMoveOffscreen();
826     } else {
827         m_page->setCanStartMedia(true);
828         m_page->didMoveOnscreen();
829     }
830 }
831
832 void WebPage::didReceivePolicyDecision(uint64_t frameID, uint64_t listenerID, uint32_t policyAction, uint64_t downloadID)
833 {
834     WebFrame* frame = WebProcess::shared().webFrame(frameID);
835     if (!frame)
836         return;
837     frame->didReceivePolicyDecision(listenerID, static_cast<PolicyAction>(policyAction), downloadID);
838 }
839
840 void WebPage::show()
841 {
842     send(Messages::WebPageProxy::ShowPage());
843 }
844
845 void WebPage::setCustomUserAgent(const String& customUserAgent)
846 {
847     m_customUserAgent = customUserAgent;
848 }
849
850 String WebPage::userAgent() const
851 {
852     if (!m_customUserAgent.isEmpty())
853         return m_customUserAgent;
854
855     // FIXME: This should be based on an application name.
856     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";
857 }
858
859 IntRect WebPage::windowResizerRect() const
860 {
861     if (m_windowResizerSize.isEmpty())
862         return IntRect();
863
864     IntSize frameViewSize;
865     if (Frame* coreFrame = m_mainFrame->coreFrame()) {
866         if (FrameView* view = coreFrame->view())
867             frameViewSize = view->size();
868     }
869
870     return IntRect(frameViewSize.width() - m_windowResizerSize.width(), frameViewSize.height() - m_windowResizerSize.height(), 
871                    m_windowResizerSize.width(), m_windowResizerSize.height());
872 }
873
874 void WebPage::runJavaScriptInMainFrame(const String& script, uint64_t callbackID)
875 {
876     // NOTE: We need to be careful when running scripts that the objects we depend on don't
877     // disappear during script execution.
878
879     JSLock lock(SilenceAssertionsOnly);
880     JSValue resultValue = m_mainFrame->coreFrame()->script()->executeScript(script, true).jsValue();
881     String resultString;
882     if (resultValue)
883         resultString = ustringToString(resultValue.toString(m_mainFrame->coreFrame()->script()->globalObject(mainThreadNormalWorld())->globalExec()));
884
885     send(Messages::WebPageProxy::DidRunJavaScriptInMainFrame(resultString, callbackID));
886 }
887
888 void WebPage::getContentsAsString(uint64_t callbackID)
889 {
890     String resultString = m_mainFrame->contentsAsString();
891     send(Messages::WebPageProxy::DidGetContentsAsString(resultString, callbackID));
892 }
893
894 void WebPage::getRenderTreeExternalRepresentation(uint64_t callbackID)
895 {
896     String resultString = renderTreeExternalRepresentation();
897     send(Messages::WebPageProxy::DidGetRenderTreeExternalRepresentation(resultString, callbackID));
898 }
899
900 void WebPage::getSourceForFrame(uint64_t frameID, uint64_t callbackID)
901 {
902     String resultString;
903     if (WebFrame* frame = WebProcess::shared().webFrame(frameID))
904        resultString = frame->source();
905
906     send(Messages::WebPageProxy::DidGetSourceForFrame(resultString, callbackID));
907 }
908
909 void WebPage::preferencesDidChange(const WebPreferencesStore& store)
910 {
911     WebPreferencesStore::removeTestRunnerOverrides();
912     updatePreferences(store);
913 }
914
915 void WebPage::updatePreferences(const WebPreferencesStore& store)
916 {
917     Settings* settings = m_page->settings();
918
919     m_tabToLinks = store.getBoolValueForKey(WebPreferencesKey::tabsToLinksKey());
920
921     // FIXME: This should be generated from macro expansion for all preferences,
922     // but we currently don't match the naming of WebCore exactly so we are
923     // handrolling the boolean and integer preferences until that is fixed.
924
925 #define INITIALIZE_SETTINGS(KeyUpper, KeyLower, TypeName, Type, DefaultValue) settings->set##KeyUpper(store.get##TypeName##ValueForKey(WebPreferencesKey::KeyLower##Key()));
926
927     FOR_EACH_WEBKIT_STRING_PREFERENCE(INITIALIZE_SETTINGS)
928
929 #undef INITIALIZE_SETTINGS
930
931     settings->setJavaScriptEnabled(store.getBoolValueForKey(WebPreferencesKey::javaScriptEnabledKey()));
932     settings->setLoadsImagesAutomatically(store.getBoolValueForKey(WebPreferencesKey::loadsImagesAutomaticallyKey()));
933     settings->setPluginsEnabled(store.getBoolValueForKey(WebPreferencesKey::pluginsEnabledKey()));
934     settings->setJavaEnabled(store.getBoolValueForKey(WebPreferencesKey::javaEnabledKey()));
935     settings->setOfflineWebApplicationCacheEnabled(store.getBoolValueForKey(WebPreferencesKey::offlineWebApplicationCacheEnabledKey()));
936     settings->setLocalStorageEnabled(store.getBoolValueForKey(WebPreferencesKey::localStorageEnabledKey()));
937     settings->setXSSAuditorEnabled(store.getBoolValueForKey(WebPreferencesKey::xssAuditorEnabledKey()));
938     settings->setFrameFlatteningEnabled(store.getBoolValueForKey(WebPreferencesKey::frameFlatteningEnabledKey()));
939     settings->setPrivateBrowsingEnabled(store.getBoolValueForKey(WebPreferencesKey::privateBrowsingEnabledKey()));
940     settings->setDeveloperExtrasEnabled(store.getBoolValueForKey(WebPreferencesKey::developerExtrasEnabledKey()));
941     settings->setTextAreasAreResizable(store.getBoolValueForKey(WebPreferencesKey::textAreasAreResizableKey()));
942     settings->setNeedsSiteSpecificQuirks(store.getBoolValueForKey(WebPreferencesKey::needsSiteSpecificQuirksKey()));
943     settings->setJavaScriptCanOpenWindowsAutomatically(store.getBoolValueForKey(WebPreferencesKey::javaScriptCanOpenWindowsAutomaticallyKey()));
944     settings->setForceFTPDirectoryListings(store.getBoolValueForKey(WebPreferencesKey::forceFTPDirectoryListingsKey()));
945     settings->setMinimumFontSize(store.getUInt32ValueForKey(WebPreferencesKey::minimumFontSizeKey()));
946     settings->setMinimumLogicalFontSize(store.getUInt32ValueForKey(WebPreferencesKey::minimumLogicalFontSizeKey()));
947     settings->setDefaultFontSize(store.getUInt32ValueForKey(WebPreferencesKey::defaultFontSizeKey()));
948     settings->setDefaultFixedFontSize(store.getUInt32ValueForKey(WebPreferencesKey::defaultFixedFontSizeKey()));
949
950 #if PLATFORM(WIN)
951     // Temporarily turn off accelerated compositing until we have a good solution for rendering it.
952     settings->setAcceleratedCompositingEnabled(false);
953 #else
954     settings->setAcceleratedCompositingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedCompositingEnabledKey()));
955 #endif
956     settings->setShowDebugBorders(store.getBoolValueForKey(WebPreferencesKey::compositingBordersVisibleKey()));
957     settings->setShowRepaintCounter(store.getBoolValueForKey(WebPreferencesKey::compositingRepaintCountersVisibleKey()));
958
959 #if ENABLE(DATABASE)
960     AbstractDatabase::setIsAvailable(store.getBoolValueForKey(WebPreferencesKey::databasesEnabledKey()));
961 #endif
962     
963     platformPreferencesDidChange(store);
964 }
965
966 #if ENABLE(INSPECTOR)
967 WebInspector* WebPage::inspector()
968 {
969     if (m_isClosed)
970         return 0;
971     if (!m_inspector)
972         m_inspector = adoptPtr(new WebInspector(this));
973     return m_inspector.get();
974 }
975 #endif
976
977 #if !PLATFORM(MAC)
978 bool WebPage::handleEditingKeyboardEvent(KeyboardEvent* evt)
979 {
980     Node* node = evt->target()->toNode();
981     ASSERT(node);
982     Frame* frame = node->document()->frame();
983     ASSERT(frame);
984
985     const PlatformKeyboardEvent* keyEvent = evt->keyEvent();
986     if (!keyEvent)
987         return false;
988
989     Editor::Command command = frame->editor()->command(interpretKeyEvent(evt));
990
991     if (keyEvent->type() == PlatformKeyboardEvent::RawKeyDown) {
992         // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated,
993         // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated
994         // (e.g. Tab that inserts a Tab character, or Enter).
995         return !command.isTextInsertion() && command.execute(evt);
996     }
997
998     if (command.execute(evt))
999         return true;
1000
1001     // Don't insert null or control characters as they can result in unexpected behaviour
1002     if (evt->charCode() < ' ')
1003         return false;
1004
1005     return frame->editor()->insertText(evt->keyEvent()->text(), evt);
1006 }
1007 #endif
1008     
1009 WebEditCommand* WebPage::webEditCommand(uint64_t commandID)
1010 {
1011     return m_editCommandMap.get(commandID).get();
1012 }
1013
1014 void WebPage::addWebEditCommand(uint64_t commandID, WebEditCommand* command)
1015 {
1016     m_editCommandMap.set(commandID, command);
1017 }
1018
1019 void WebPage::removeWebEditCommand(uint64_t commandID)
1020 {
1021     m_editCommandMap.remove(commandID);
1022 }
1023
1024 void WebPage::unapplyEditCommand(uint64_t commandID)
1025 {
1026     WebEditCommand* command = webEditCommand(commandID);
1027     if (!command)
1028         return;
1029
1030     command->command()->unapply();
1031 }
1032
1033 void WebPage::reapplyEditCommand(uint64_t commandID)
1034 {
1035     WebEditCommand* command = webEditCommand(commandID);
1036     if (!command)
1037         return;
1038
1039     m_isInRedo = true;
1040     command->command()->reapply();
1041     m_isInRedo = false;
1042 }
1043
1044 void WebPage::didRemoveEditCommand(uint64_t commandID)
1045 {
1046     removeWebEditCommand(commandID);
1047 }
1048
1049 void WebPage::setActivePopupMenu(WebPopupMenu* menu)
1050 {
1051     m_activePopupMenu = menu;
1052 }
1053
1054 bool WebPage::findStringFromInjectedBundle(const String& target, FindOptions options)
1055 {
1056     return m_page->findString(target, options);
1057 }
1058
1059 void WebPage::findString(const String& string, uint32_t options, uint32_t maxMatchCount)
1060 {
1061     m_findController.findString(string, static_cast<FindOptions>(options), maxMatchCount);
1062 }
1063
1064 void WebPage::hideFindUI()
1065 {
1066     m_findController.hideFindUI();
1067 }
1068
1069 void WebPage::countStringMatches(const String& string, uint32_t options, uint32_t maxMatchCount)
1070 {
1071     m_findController.countStringMatches(string, static_cast<FindOptions>(options), maxMatchCount);
1072 }
1073
1074 void WebPage::didChangeSelectedIndexForActivePopupMenu(int32_t newIndex)
1075 {
1076     if (!m_activePopupMenu)
1077         return;
1078
1079     m_activePopupMenu->didChangeSelectedIndex(newIndex);
1080     m_activePopupMenu = 0;
1081 }
1082
1083 void WebPage::didSelectItemFromActiveContextMenu(const WebContextMenuItemData& item)
1084 {
1085     ASSERT(m_contextMenu);
1086     m_contextMenu->itemSelected(item);
1087     m_contextMenu = 0;
1088 }
1089
1090 #if PLATFORM(MAC)
1091
1092 void WebPage::addPluginView(PluginView* pluginView)
1093 {
1094     ASSERT(!m_pluginViews.contains(pluginView));
1095
1096     m_pluginViews.add(pluginView);
1097 }
1098
1099 void WebPage::removePluginView(PluginView* pluginView)
1100 {
1101     ASSERT(m_pluginViews.contains(pluginView));
1102
1103     m_pluginViews.remove(pluginView);
1104 }
1105
1106 void WebPage::setWindowIsVisible(bool windowIsVisible)
1107 {
1108     m_windowIsVisible = windowIsVisible;
1109
1110     // Tell all our plug-in views that the window visibility changed.
1111     for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
1112         (*it)->setWindowIsVisible(windowIsVisible);
1113 }
1114
1115 void WebPage::windowAndViewFramesChanged(const WebCore::IntRect& windowFrameInScreenCoordinates, const WebCore::IntRect& viewFrameInWindowCoordinates)
1116 {
1117     m_windowFrameInScreenCoordinates = windowFrameInScreenCoordinates;
1118     m_viewFrameInWindowCoordinates = viewFrameInWindowCoordinates;
1119
1120     // Tell all our plug-in views that the window and view frames have changed.
1121     for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
1122         (*it)->windowAndViewFramesChanged(windowFrameInScreenCoordinates, viewFrameInWindowCoordinates);
1123 }
1124
1125 bool WebPage::windowIsFocused() const
1126 {
1127     return m_page->focusController()->isActive();
1128 }
1129
1130 #endif
1131
1132 void WebPage::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
1133 {
1134     if (messageID.is<CoreIPC::MessageClassDrawingArea>()) {
1135         if (m_drawingArea)
1136             m_drawingArea->didReceiveMessage(connection, messageID, arguments);
1137         return;
1138     }
1139
1140 #if ENABLE(INSPECTOR)
1141     if (messageID.is<CoreIPC::MessageClassWebInspector>()) {
1142         if (WebInspector* inspector = this->inspector())
1143             inspector->didReceiveWebInspectorMessage(connection, messageID, arguments);
1144         return;
1145     }
1146 #endif
1147
1148     didReceiveWebPageMessage(connection, messageID, arguments);
1149 }
1150
1151 InjectedBundleBackForwardList* WebPage::backForwardList()
1152 {
1153     if (!m_backForwardList)
1154         m_backForwardList = InjectedBundleBackForwardList::create(this);
1155     return m_backForwardList.get();
1156 }
1157
1158 #if PLATFORM(QT)
1159 void WebPage::findZoomableAreaForPoint(const WebCore::IntPoint& point)
1160 {
1161     const int minimumZoomTargetWidth = 100;
1162
1163     Frame* mainframe = m_mainFrame->coreFrame();
1164     HitTestResult result = mainframe->eventHandler()->hitTestResultAtPoint(mainframe->view()->windowToContents(point), /*allowShadowContent*/ false, /*ignoreClipping*/ true);
1165
1166     Node* node = result.innerNode();
1167     while (node && node->getRect().width() < minimumZoomTargetWidth)
1168         node = node->parentNode();
1169
1170     IntRect zoomableArea;
1171     if (node)
1172         zoomableArea = node->getRect();
1173     send(Messages::WebPageProxy::DidFindZoomableArea(zoomableArea));
1174 }
1175 #endif
1176
1177 WebPage::SandboxExtensionTracker::~SandboxExtensionTracker()
1178 {
1179     invalidate();
1180 }
1181
1182 void WebPage::SandboxExtensionTracker::invalidate()
1183 {
1184     if (m_pendingProvisionalSandboxExtension) {
1185         m_pendingProvisionalSandboxExtension->invalidate();
1186         m_pendingProvisionalSandboxExtension = 0;
1187     }
1188
1189     if (m_provisionalSandboxExtension) {
1190         m_provisionalSandboxExtension->invalidate();
1191         m_provisionalSandboxExtension = 0;
1192     }
1193
1194     if (m_committedSandboxExtension) {
1195         m_committedSandboxExtension->invalidate();
1196         m_committedSandboxExtension = 0;
1197     }
1198 }
1199
1200 void WebPage::SandboxExtensionTracker::beginLoad(WebFrame* frame, const SandboxExtension::Handle& handle)
1201 {
1202     ASSERT(frame->isMainFrame());
1203
1204     ASSERT(!m_pendingProvisionalSandboxExtension);
1205     m_pendingProvisionalSandboxExtension = SandboxExtension::create(handle);
1206 }
1207
1208 void WebPage::SandboxExtensionTracker::didStartProvisionalLoad(WebFrame* frame)
1209 {
1210     if (!frame->isMainFrame())
1211         return;
1212
1213     ASSERT(!m_provisionalSandboxExtension);
1214
1215     m_provisionalSandboxExtension = m_pendingProvisionalSandboxExtension.release();
1216     if (!m_provisionalSandboxExtension)
1217         return;
1218
1219     m_provisionalSandboxExtension->consume();
1220 }
1221
1222 void WebPage::SandboxExtensionTracker::didCommitProvisionalLoad(WebFrame* frame)
1223 {
1224     if (!frame->isMainFrame())
1225         return;
1226     
1227     ASSERT(!m_pendingProvisionalSandboxExtension);
1228
1229     // The provisional load has been committed. Invalidate the currently committed sandbox
1230     // extension and make the provisional sandbox extension the committed sandbox extension.
1231     if (m_committedSandboxExtension)
1232         m_committedSandboxExtension->invalidate();
1233
1234     m_committedSandboxExtension = m_provisionalSandboxExtension.release();
1235 }
1236
1237 void WebPage::SandboxExtensionTracker::didFailProvisionalLoad(WebFrame* frame)
1238 {
1239     if (!frame->isMainFrame())
1240         return;
1241
1242     ASSERT(!m_pendingProvisionalSandboxExtension);
1243     if (!m_provisionalSandboxExtension)
1244         return;
1245
1246     m_provisionalSandboxExtension->invalidate();
1247     m_provisionalSandboxExtension = 0;
1248 }
1249
1250 } // namespace WebKit