c9cebcf305ebe8035436cf1d230d1321117bf6d2
[WebKit.git] / WebKit2 / WebProcess / WebPage / WebPage.cpp
1 /*
2  * Copyright (C) 2010, 2011 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 "DataReference.h"
30 #include "DrawingArea.h"
31 #include "InjectedBundle.h"
32 #include "InjectedBundleBackForwardList.h"
33 #include "MessageID.h"
34 #include "NetscapePlugin.h"
35 #include "PageOverlay.h"
36 #include "PluginProxy.h"
37 #include "PluginView.h"
38 #include "WebBackForwardListProxy.h"
39 #include "WebChromeClient.h"
40 #include "WebContextMenu.h"
41 #include "WebContextMenuClient.h"
42 #include "WebContextMessages.h"
43 #include "WebCoreArgumentCoders.h"
44 #include "WebDragClient.h"
45 #include "WebEditorClient.h"
46 #include "WebEvent.h"
47 #include "WebEventConversion.h"
48 #include "WebFrame.h"
49 #include "WebImage.h"
50 #include "WebInspector.h"
51 #include "WebInspectorClient.h"
52 #include "WebOpenPanelResultListener.h"
53 #include "WebPageCreationParameters.h"
54 #include "WebPageGroupProxy.h"
55 #include "WebPageProxyMessages.h"
56 #include "WebPopupMenu.h"
57 #include "WebPreferencesStore.h"
58 #include "WebProcess.h"
59 #include "WebProcessProxyMessageKinds.h"
60 #include "WebProcessProxyMessages.h"
61 #include <WebCore/AbstractDatabase.h>
62 #include <WebCore/ArchiveResource.h>
63 #include <WebCore/Chrome.h>
64 #include <WebCore/ContextMenuController.h>
65 #include <WebCore/DocumentFragment.h>
66 #include <WebCore/DocumentLoader.h>
67 #include <WebCore/DocumentMarkerController.h>
68 #include <WebCore/EventHandler.h>
69 #include <WebCore/FocusController.h>
70 #include <WebCore/Frame.h>
71 #include <WebCore/FrameLoaderTypes.h>
72 #include <WebCore/FrameView.h>
73 #include <WebCore/HistoryItem.h>
74 #include <WebCore/KeyboardEvent.h>
75 #include <WebCore/Page.h>
76 #include <WebCore/PlatformKeyboardEvent.h>
77 #include <WebCore/RenderTreeAsText.h>
78 #include <WebCore/ReplaceSelectionCommand.h>
79 #include <WebCore/ResourceRequest.h>
80 #include <WebCore/Settings.h>
81 #include <WebCore/SharedBuffer.h>
82 #include <WebCore/SubstituteData.h>
83 #include <WebCore/TextIterator.h>
84 #include <WebCore/markup.h>
85 #include <runtime/JSLock.h>
86 #include <runtime/JSValue.h>
87
88 #if PLATFORM(MAC) || PLATFORM(WIN)
89 #include <WebCore/LegacyWebArchive.h>
90 #endif
91
92 #if ENABLE(PLUGIN_PROCESS)
93 // FIXME: This is currently Mac-specific!
94 #include "MachPort.h"
95 #endif
96
97 #if PLATFORM(QT)
98 #include "HitTestResult.h"
99 #endif
100
101 #ifndef NDEBUG
102 #include <wtf/RefCountedLeakCounter.h>
103 #endif
104
105 using namespace JSC;
106 using namespace WebCore;
107
108 namespace WebKit {
109
110 #ifndef NDEBUG
111 static WTF::RefCountedLeakCounter webPageCounter("WebPage");
112 #endif
113
114 PassRefPtr<WebPage> WebPage::create(uint64_t pageID, const WebPageCreationParameters& parameters)
115 {
116     RefPtr<WebPage> page = adoptRef(new WebPage(pageID, parameters));
117
118     if (page->pageGroup()->isVisibleToInjectedBundle() && WebProcess::shared().injectedBundle())
119         WebProcess::shared().injectedBundle()->didCreatePage(page.get());
120
121     return page.release();
122 }
123
124 WebPage::WebPage(uint64_t pageID, const WebPageCreationParameters& parameters)
125     : m_viewSize(parameters.viewSize)
126     , m_drawsBackground(true)
127     , m_drawsTransparentBackground(false)
128     , m_isInRedo(false)
129     , m_isClosed(false)
130     , m_tabToLinks(false)
131 #if PLATFORM(MAC)
132     , m_windowIsVisible(false)
133     , m_isSmartInsertDeleteEnabled(parameters.isSmartInsertDeleteEnabled)
134 #elif PLATFORM(WIN)
135     , m_nativeWindow(parameters.nativeWindow)
136 #endif
137     , m_findController(this)
138     , m_pageID(pageID)
139 {
140     ASSERT(m_pageID);
141
142     Page::PageClients pageClients;
143     pageClients.chromeClient = new WebChromeClient(this);
144     pageClients.contextMenuClient = new WebContextMenuClient(this);
145     pageClients.editorClient = new WebEditorClient(this);
146     pageClients.dragClient = new WebDragClient(this);
147 #if ENABLE(INSPECTOR)
148     pageClients.inspectorClient = new WebInspectorClient(this);
149 #endif
150     pageClients.backForwardClient = WebBackForwardListProxy::create(this);
151     m_page = adoptPtr(new Page(pageClients));
152
153     // Qt does not yet call setIsInWindow. Until it does, just leave
154     // this line out so plug-ins and video will work. Eventually all platforms
155     // should call setIsInWindow and this comment and #if should be removed,
156     // leaving behind the setCanStartMedia call.
157 #if !PLATFORM(QT)
158     m_page->setCanStartMedia(false);
159 #endif
160
161     updatePreferences(parameters.store);
162
163     m_pageGroup = WebProcess::shared().webPageGroup(parameters.pageGroupData);
164     m_page->setGroupName(m_pageGroup->identifier());
165
166     platformInitialize();
167     Settings::setMinDOMTimerInterval(0.004);
168
169     m_drawingArea = DrawingArea::create(parameters.drawingAreaInfo.type, parameters.drawingAreaInfo.identifier, this);
170     m_mainFrame = WebFrame::createMainFrame(this);
171
172     setDrawsBackground(parameters.drawsBackground);
173     setDrawsTransparentBackground(parameters.drawsTransparentBackground);
174
175     m_userAgent = parameters.userAgent;
176
177 #ifndef NDEBUG
178     webPageCounter.increment();
179 #endif
180 }
181
182 WebPage::~WebPage()
183 {
184     if (m_backForwardList)
185         m_backForwardList->detach();
186
187     ASSERT(!m_page);
188
189     m_sandboxExtensionTracker.invalidate();
190
191 #if PLATFORM(MAC)
192     ASSERT(m_pluginViews.isEmpty());
193 #endif
194
195 #ifndef NDEBUG
196     webPageCounter.decrement();
197 #endif
198 }
199
200 void WebPage::dummy(bool&)
201 {
202 }
203
204 CoreIPC::Connection* WebPage::connection() const
205 {
206     return WebProcess::shared().connection();
207 }
208
209 void WebPage::initializeInjectedBundleContextMenuClient(WKBundlePageContextMenuClient* client)
210 {
211     m_contextMenuClient.initialize(client);
212 }
213
214 void WebPage::initializeInjectedBundleEditorClient(WKBundlePageEditorClient* client)
215 {
216     m_editorClient.initialize(client);
217 }
218
219 void WebPage::initializeInjectedBundleFormClient(WKBundlePageFormClient* client)
220 {
221     m_formClient.initialize(client);
222 }
223
224 void WebPage::initializeInjectedBundleLoaderClient(WKBundlePageLoaderClient* client)
225 {
226     m_loaderClient.initialize(client);
227 }
228
229 void WebPage::initializeInjectedBundleUIClient(WKBundlePageUIClient* client)
230 {
231     m_uiClient.initialize(client);
232 }
233
234 PassRefPtr<Plugin> WebPage::createPlugin(const Plugin::Parameters& parameters)
235 {
236     String pluginPath;
237
238     if (!WebProcess::shared().connection()->sendSync(
239             Messages::WebContext::GetPluginPath(parameters.mimeType, parameters.url.string()), 
240             Messages::WebContext::GetPluginPath::Reply(pluginPath), 0)) {
241         return 0;
242     }
243
244     if (pluginPath.isNull())
245         return 0;
246
247 #if ENABLE(PLUGIN_PROCESS)
248     return PluginProxy::create(pluginPath);
249 #else
250     return NetscapePlugin::create(NetscapePluginModule::getOrCreate(pluginPath));
251 #endif
252 }
253
254 String WebPage::renderTreeExternalRepresentation() const
255 {
256     return externalRepresentation(m_mainFrame->coreFrame(), RenderAsTextBehaviorNormal);
257 }
258
259 void WebPage::executeEditingCommand(const String& commandName, const String& argument)
260 {
261     Frame* frame = m_page->focusController()->focusedOrMainFrame();
262     if (!frame)
263         return;
264     frame->editor()->command(commandName).execute(argument);
265 }
266
267 bool WebPage::isEditingCommandEnabled(const String& commandName)
268 {
269     Frame* frame = m_page->focusController()->focusedOrMainFrame();
270     if (!frame)
271         return false;
272     
273     Editor::Command command = frame->editor()->command(commandName);
274     return command.isSupported() && command.isEnabled();
275 }
276     
277 void WebPage::clearMainFrameName()
278 {
279     mainFrame()->coreFrame()->tree()->clearName();
280 }
281
282 #if USE(ACCELERATED_COMPOSITING)
283 void WebPage::changeAcceleratedCompositingMode(WebCore::GraphicsLayer* layer)
284 {
285     if (m_isClosed)
286         return;
287
288     bool compositing = layer;
289     
290     // Tell the UI process that accelerated compositing changed. It may respond by changing
291     // drawing area types.
292     DrawingAreaInfo newDrawingAreaInfo;
293
294     if (!sendSync(Messages::WebPageProxy::DidChangeAcceleratedCompositing(compositing), Messages::WebPageProxy::DidChangeAcceleratedCompositing::Reply(newDrawingAreaInfo)))
295         return;
296     
297     if (newDrawingAreaInfo.type != drawingArea()->info().type) {
298         m_drawingArea = 0;
299         if (newDrawingAreaInfo.type != DrawingAreaInfo::None) {
300             m_drawingArea = DrawingArea::create(newDrawingAreaInfo.type, newDrawingAreaInfo.identifier, this);
301             m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize));
302         }
303     }
304 }
305
306 void WebPage::enterAcceleratedCompositingMode(GraphicsLayer* layer)
307 {
308     changeAcceleratedCompositingMode(layer);
309     m_drawingArea->setRootCompositingLayer(layer);
310 }
311
312 void WebPage::exitAcceleratedCompositingMode()
313 {
314     changeAcceleratedCompositingMode(0);
315 }
316 #endif
317
318 void WebPage::close()
319 {
320     if (m_isClosed)
321         return;
322
323     m_isClosed = true;
324
325     if (pageGroup()->isVisibleToInjectedBundle() && WebProcess::shared().injectedBundle())
326         WebProcess::shared().injectedBundle()->willDestroyPage(this);
327
328 #if ENABLE(INSPECTOR)
329     m_inspector = 0;
330 #endif
331
332     if (m_activePopupMenu) {
333         m_activePopupMenu->disconnectFromPage();
334         m_activePopupMenu = 0;
335     }
336
337     if (m_activeOpenPanelResultListener) {
338         m_activeOpenPanelResultListener->disconnectFromPage();
339         m_activeOpenPanelResultListener = 0;
340     }
341
342     m_sandboxExtensionTracker.invalidate();
343
344     m_mainFrame->coreFrame()->loader()->detachFromParent();
345     m_page.clear();
346
347     m_drawingArea->onPageClose();
348     m_drawingArea.clear();
349
350     WebProcess::shared().removeWebPage(m_pageID);
351 }
352
353 void WebPage::tryClose()
354 {
355     if (!m_mainFrame->coreFrame()->loader()->shouldClose())
356         return;
357
358     sendClose();
359 }
360
361 void WebPage::sendClose()
362 {
363     send(Messages::WebPageProxy::ClosePage());
364 }
365
366 void WebPage::loadURL(const String& url, const SandboxExtension::Handle& sandboxExtensionHandle)
367 {
368     loadURLRequest(ResourceRequest(KURL(KURL(), url)), sandboxExtensionHandle);
369 }
370
371 void WebPage::loadURLRequest(const ResourceRequest& request, const SandboxExtension::Handle& sandboxExtensionHandle)
372 {
373     m_sandboxExtensionTracker.beginLoad(m_mainFrame.get(), sandboxExtensionHandle);
374     m_mainFrame->coreFrame()->loader()->load(request, false);
375 }
376
377 void WebPage::loadData(PassRefPtr<SharedBuffer> sharedBuffer, const String& MIMEType, const String& encodingName, const KURL& baseURL, const KURL& unreachableURL)
378 {
379     ResourceRequest request(baseURL);
380     SubstituteData substituteData(sharedBuffer, MIMEType, encodingName, unreachableURL);
381     m_mainFrame->coreFrame()->loader()->load(request, substituteData, false);
382 }
383
384 void WebPage::loadHTMLString(const String& htmlString, const String& baseURLString)
385 {
386     RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(htmlString.characters()), htmlString.length() * sizeof(UChar));
387     KURL baseURL = baseURLString.isEmpty() ? blankURL() : KURL(KURL(), baseURLString);
388     loadData(sharedBuffer, "text/html", "utf-16", baseURL, KURL());
389 }
390
391 void WebPage::loadAlternateHTMLString(const String& htmlString, const String& baseURLString, const String& unreachableURLString)
392 {
393     RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(htmlString.characters()), htmlString.length() * sizeof(UChar));
394     KURL baseURL = baseURLString.isEmpty() ? blankURL() : KURL(KURL(), baseURLString);
395     KURL unreachableURL = unreachableURLString.isEmpty() ? KURL() : KURL(KURL(), unreachableURLString)  ;
396     loadData(sharedBuffer, "text/html", "utf-16", baseURL, unreachableURL);
397 }
398
399 void WebPage::loadPlainTextString(const String& string)
400 {
401     RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(string.characters()), string.length() * sizeof(UChar));
402     loadData(sharedBuffer, "text/plain", "utf-16", blankURL(), KURL());
403 }
404
405 void WebPage::stopLoading()
406 {
407     m_mainFrame->coreFrame()->loader()->stopForUserCancel();
408 }
409
410 void WebPage::reload(bool reloadFromOrigin)
411 {
412     m_mainFrame->coreFrame()->loader()->reload(reloadFromOrigin);
413 }
414
415 void WebPage::goForward(uint64_t backForwardItemID)
416 {
417     HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
418     m_page->goToItem(item, FrameLoadTypeForward);
419 }
420
421 void WebPage::goBack(uint64_t backForwardItemID)
422 {
423     HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
424     m_page->goToItem(item, FrameLoadTypeBack);
425 }
426
427 void WebPage::goToBackForwardItem(uint64_t backForwardItemID)
428 {
429     HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
430     m_page->goToItem(item, FrameLoadTypeIndexedBackForward);
431 }
432
433 void WebPage::layoutIfNeeded()
434 {
435     if (m_mainFrame->coreFrame()->view())
436         m_mainFrame->coreFrame()->view()->updateLayoutAndStyleIfNeededRecursive();
437 }
438
439 void WebPage::setSize(const WebCore::IntSize& viewSize)
440 {
441 #if ENABLE(TILED_BACKING_STORE)
442     // If we are resizing to content ignore external attempts.
443     if (!m_resizesToContentsLayoutSize.isEmpty())
444         return;
445 #endif
446
447     if (m_viewSize == viewSize)
448         return;
449
450     Frame* frame = m_page->mainFrame();
451     
452     frame->view()->resize(viewSize);
453     frame->view()->setNeedsLayout();
454     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), viewSize));
455     
456     m_viewSize = viewSize;
457 }
458
459 #if ENABLE(TILED_BACKING_STORE)
460 void WebPage::setActualVisibleContentRect(const IntRect& rect)
461 {
462     Frame* frame = m_page->mainFrame();
463
464     frame->view()->setActualVisibleContentRect(rect);
465 }
466
467 void WebPage::setResizesToContentsUsingLayoutSize(const IntSize& targetLayoutSize)
468 {
469     if (m_resizesToContentsLayoutSize == targetLayoutSize)
470         return;
471
472     m_resizesToContentsLayoutSize = targetLayoutSize;
473
474     Frame* frame = m_page->mainFrame();
475     if (m_resizesToContentsLayoutSize.isEmpty()) {
476         frame->view()->setDelegatesScrolling(false);
477         frame->view()->setUseFixedLayout(false);
478         frame->view()->setPaintsEntireContents(false);
479     } else {
480         frame->view()->setDelegatesScrolling(true);
481         frame->view()->setUseFixedLayout(true);
482         frame->view()->setPaintsEntireContents(true);
483         frame->view()->setFixedLayoutSize(m_resizesToContentsLayoutSize);
484     }
485     frame->view()->forceLayout();
486 }
487
488 void WebPage::resizeToContentsIfNeeded()
489 {
490     if (m_resizesToContentsLayoutSize.isEmpty())
491         return;
492
493     Frame* frame = m_page->mainFrame();
494
495     IntSize contentSize = frame->view()->contentsSize();
496     if (contentSize == m_viewSize)
497         return;
498
499     m_viewSize = contentSize;
500     frame->view()->resize(m_viewSize);
501     frame->view()->setNeedsLayout();
502 }
503 #endif
504
505 void WebPage::drawRect(GraphicsContext& graphicsContext, const IntRect& rect)
506 {
507     graphicsContext.save();
508     graphicsContext.clip(rect);
509     m_mainFrame->coreFrame()->view()->paint(&graphicsContext, rect);
510     graphicsContext.restore();
511
512     if (m_pageOverlay) {
513         graphicsContext.save();
514         graphicsContext.clip(rect);
515         m_pageOverlay->drawRect(graphicsContext, rect);
516         graphicsContext.restore();
517     }
518 }
519
520 double WebPage::textZoomFactor() const
521 {
522     Frame* frame = m_mainFrame->coreFrame();
523     if (!frame)
524         return 1;
525     return frame->textZoomFactor();
526 }
527
528 void WebPage::setTextZoomFactor(double zoomFactor)
529 {
530     Frame* frame = m_mainFrame->coreFrame();
531     if (!frame)
532         return;
533     frame->setTextZoomFactor(static_cast<float>(zoomFactor));
534 }
535
536 double WebPage::pageZoomFactor() const
537 {
538     Frame* frame = m_mainFrame->coreFrame();
539     if (!frame)
540         return 1;
541     return frame->pageZoomFactor();
542 }
543
544 void WebPage::setPageZoomFactor(double zoomFactor)
545 {
546     Frame* frame = m_mainFrame->coreFrame();
547     if (!frame)
548         return;
549     frame->setPageZoomFactor(static_cast<float>(zoomFactor));
550 }
551
552 void WebPage::setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor)
553 {
554     Frame* frame = m_mainFrame->coreFrame();
555     if (!frame)
556         return;
557     return frame->setPageAndTextZoomFactors(static_cast<float>(pageZoomFactor), static_cast<float>(textZoomFactor));
558 }
559
560 void WebPage::scaleWebView(double scale, const IntPoint& origin)
561 {
562     Frame* frame = m_mainFrame->coreFrame();
563     if (!frame)
564         return;
565     frame->scalePage(scale, origin);
566 }
567
568 double WebPage::viewScaleFactor() const
569 {
570     Frame* frame = m_mainFrame->coreFrame();
571     if (!frame)
572         return 1;
573     return frame->pageScaleFactor();
574 }
575
576 void WebPage::installPageOverlay(PassRefPtr<PageOverlay> pageOverlay)
577 {
578     if (m_pageOverlay)
579         pageOverlay->setPage(0);
580
581     m_pageOverlay = pageOverlay;
582     m_pageOverlay->setPage(this);
583     m_pageOverlay->setNeedsDisplay();
584 }
585
586 void WebPage::uninstallPageOverlay(PageOverlay* pageOverlay)
587 {
588     if (pageOverlay != m_pageOverlay)
589         return;
590
591     m_pageOverlay->setPage(0);
592     m_pageOverlay = nullptr;
593     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize));
594 }
595
596 PassRefPtr<WebImage> WebPage::snapshotInViewCoordinates(const IntRect& rect, ImageOptions options)
597 {
598     FrameView* frameView = m_mainFrame->coreFrame()->view();
599     if (!frameView)
600         return 0;
601
602     frameView->updateLayoutAndStyleIfNeededRecursive();
603
604     PaintBehavior oldBehavior = frameView->paintBehavior();
605     frameView->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
606
607     RefPtr<WebImage> snapshot = WebImage::create(rect.size(), options);
608     OwnPtr<WebCore::GraphicsContext> graphicsContext = snapshot->backingStore()->createGraphicsContext();
609
610     graphicsContext->save();
611     graphicsContext->translate(-rect.x(), -rect.y());
612     frameView->paint(graphicsContext.get(), rect);
613     graphicsContext->restore();
614
615     frameView->setPaintBehavior(oldBehavior);
616
617     return snapshot.release();
618 }
619
620 PassRefPtr<WebImage> WebPage::snapshotInDocumentCoordinates(const IntRect& rect, ImageOptions options)
621 {
622     FrameView* frameView = m_mainFrame->coreFrame()->view();
623     if (!frameView)
624         return 0;
625
626     frameView->updateLayoutAndStyleIfNeededRecursive();
627
628     PaintBehavior oldBehavior = frameView->paintBehavior();
629     frameView->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
630
631     RefPtr<WebImage> snapshot = WebImage::create(rect.size(), options);
632     OwnPtr<WebCore::GraphicsContext> graphicsContext = snapshot->backingStore()->createGraphicsContext();
633
634     graphicsContext->save();
635     graphicsContext->translate(-rect.x(), -rect.y());
636     frameView->paintContents(graphicsContext.get(), rect);
637     graphicsContext->restore();
638
639     frameView->setPaintBehavior(oldBehavior);
640
641     return snapshot.release();
642 }
643
644 void WebPage::pageDidScroll()
645 {
646     // Hide the find indicator.
647     m_findController.hideFindIndicator();
648
649     m_uiClient.pageDidScroll(this);
650
651     send(Messages::WebPageProxy::PageDidScroll());
652 }
653
654 #if ENABLE(TILED_BACKING_STORE)
655 void WebPage::pageDidRequestScroll(const IntSize& delta)
656 {
657     send(Messages::WebPageProxy::PageDidRequestScroll(delta));
658 }
659 #endif
660
661 WebContextMenu* WebPage::contextMenu()
662 {
663     if (!m_contextMenu)
664         m_contextMenu = WebContextMenu::create(this);
665     return m_contextMenu.get();
666 }
667
668 void WebPage::getLocationAndLengthFromRange(Range* range, uint64_t& location, uint64_t& length)
669 {
670     location = notFound;
671     length = 0;
672
673     if (!range || !range->startContainer())
674         return;
675
676     Element* selectionRoot = range->ownerDocument()->frame()->selection()->rootEditableElement();
677     Element* scope = selectionRoot ? selectionRoot : range->ownerDocument()->documentElement();
678     
679     // Mouse events may cause TSM to attempt to create an NSRange for a portion of the view
680     // that is not inside the current editable region.  These checks ensure we don't produce
681     // potentially invalid data when responding to such requests.
682     if (range->startContainer() != scope && !range->startContainer()->isDescendantOf(scope))
683         return;
684     if (range->endContainer() != scope && !range->endContainer()->isDescendantOf(scope))
685         return;
686
687     RefPtr<Range> testRange = Range::create(scope->document(), scope, 0, range->startContainer(), range->startOffset());
688     ASSERT(testRange->startContainer() == scope);
689     location = TextIterator::rangeLength(testRange.get());
690     
691     ExceptionCode ec;
692     testRange->setEnd(range->endContainer(), range->endOffset(), ec);
693     ASSERT(testRange->startContainer() == scope);
694     length = TextIterator::rangeLength(testRange.get()) - location;
695 }
696
697 // Events 
698
699 static const WebEvent* g_currentEvent = 0;
700
701 // FIXME: WebPage::currentEvent is used by the plug-in code to avoid having to convert from DOM events back to
702 // WebEvents. When we get the event handling sorted out, this should go away and the Widgets should get the correct
703 // platform events passed to the event handler code.
704 const WebEvent* WebPage::currentEvent()
705 {
706     return g_currentEvent;
707 }
708
709 class CurrentEvent {
710 public:
711     explicit CurrentEvent(const WebEvent& event)
712         : m_previousCurrentEvent(g_currentEvent)
713     {
714         g_currentEvent = &event;
715     }
716
717     ~CurrentEvent()
718     {
719         g_currentEvent = m_previousCurrentEvent;
720     }
721
722 private:
723     const WebEvent* m_previousCurrentEvent;
724 };
725
726 static bool isContextClick(const PlatformMouseEvent& event)
727 {
728     if (event.button() == WebCore::RightButton)
729         return true;
730
731 #if PLATFORM(MAC)
732     // FIXME: this really should be about OSX-style UI, not about the Mac port
733     if (event.button() == WebCore::LeftButton && event.ctrlKey())
734         return true;
735 #endif
736
737     return false;
738 }
739
740 static bool handleMouseEvent(const WebMouseEvent& mouseEvent, Page* page)
741 {
742     Frame* frame = page->mainFrame();
743     if (!frame->view())
744         return false;
745
746     PlatformMouseEvent platformMouseEvent = platform(mouseEvent);
747
748     switch (platformMouseEvent.eventType()) {
749         case WebCore::MouseEventPressed:
750         {
751             if (isContextClick(platformMouseEvent))
752                 page->contextMenuController()->clearContextMenu();
753             
754             bool handled = frame->eventHandler()->handleMousePressEvent(platformMouseEvent);
755             
756             if (isContextClick(platformMouseEvent)) {
757                 handled = frame->eventHandler()->sendContextMenuEvent(platformMouseEvent);
758                 if (handled)
759                     page->chrome()->showContextMenu();
760             }
761
762             return handled;
763         }
764         case WebCore::MouseEventReleased:
765             return frame->eventHandler()->handleMouseReleaseEvent(platformMouseEvent);
766         case WebCore::MouseEventMoved:
767             return frame->eventHandler()->mouseMoved(platformMouseEvent);
768         default:
769             ASSERT_NOT_REACHED();
770             return false;
771     }
772 }
773
774 void WebPage::mouseEvent(const WebMouseEvent& mouseEvent)
775 {
776     bool handled = false;
777     
778     if (m_pageOverlay) {
779         // Let the page overlay handle the event.
780         handled = m_pageOverlay->mouseEvent(mouseEvent);
781     }
782
783     if (!handled) {
784         CurrentEvent currentEvent(mouseEvent);
785
786         handled = handleMouseEvent(mouseEvent, m_page.get());
787     }
788
789     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(mouseEvent.type()), handled));
790 }
791
792 static bool handleWheelEvent(const WebWheelEvent& wheelEvent, Page* page)
793 {
794     Frame* frame = page->mainFrame();
795     if (!frame->view())
796         return false;
797
798     PlatformWheelEvent platformWheelEvent = platform(wheelEvent);
799     return frame->eventHandler()->handleWheelEvent(platformWheelEvent);
800 }
801
802 void WebPage::wheelEvent(const WebWheelEvent& wheelEvent)
803 {
804     CurrentEvent currentEvent(wheelEvent);
805
806     bool handled = handleWheelEvent(wheelEvent, m_page.get());
807     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(wheelEvent.type()), handled));
808 }
809
810 static bool handleKeyEvent(const WebKeyboardEvent& keyboardEvent, Page* page)
811 {
812     if (!page->mainFrame()->view())
813         return false;
814
815     if (keyboardEvent.type() == WebEvent::Char && keyboardEvent.isSystemKey())
816         return page->focusController()->focusedOrMainFrame()->eventHandler()->handleAccessKey(platform(keyboardEvent));
817     return page->focusController()->focusedOrMainFrame()->eventHandler()->keyEvent(platform(keyboardEvent));
818 }
819
820 void WebPage::keyEvent(const WebKeyboardEvent& keyboardEvent)
821 {
822     CurrentEvent currentEvent(keyboardEvent);
823
824     bool handled = handleKeyEvent(keyboardEvent, m_page.get());
825     if (!handled)
826         handled = performDefaultBehaviorForKeyEvent(keyboardEvent);
827
828     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(keyboardEvent.type()), handled));
829 }
830
831 void WebPage::validateMenuItem(const String& commandName)
832 {
833     bool isEnabled = false;
834     int32_t state = 0;
835     Frame* frame = m_page->focusController()->focusedOrMainFrame();
836     if (frame) {
837         Editor::Command command = frame->editor()->command(commandName);
838         state = command.state();
839         isEnabled = command.isSupported() && command.isEnabled();
840     }
841
842     send(Messages::WebPageProxy::DidValidateMenuItem(commandName, isEnabled, state));
843 }
844
845 void WebPage::executeEditCommand(const String& commandName)
846 {
847     executeEditingCommand(commandName, String());
848 }
849
850 void WebPage::restoreSession(const SessionState&)
851 {
852     // FIXME: Implement
853 }
854
855 #if ENABLE(TOUCH_EVENTS)
856 static bool handleTouchEvent(const WebTouchEvent& touchEvent, Page* page)
857 {
858     Frame* frame = page->mainFrame();
859     if (!frame->view())
860         return false;
861
862     return frame->eventHandler()->handleTouchEvent(platform(touchEvent));
863 }
864
865 void WebPage::touchEvent(const WebTouchEvent& touchEvent)
866 {
867     CurrentEvent currentEvent(touchEvent);
868
869     bool handled = handleTouchEvent(touchEvent, m_page.get());
870
871     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(touchEvent.type()), handled));
872 }
873 #endif
874
875 void WebPage::setActive(bool isActive)
876 {
877     m_page->focusController()->setActive(isActive);
878
879 #if PLATFORM(MAC)    
880     // Tell all our plug-in views that the window focus changed.
881     for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
882         (*it)->setWindowIsFocused(isActive);
883 #endif
884 }
885
886 void WebPage::setDrawsBackground(bool drawsBackground)
887 {
888     if (m_drawsBackground == drawsBackground)
889         return;
890
891     m_drawsBackground = drawsBackground;
892
893     for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
894         if (FrameView* view = coreFrame->view())
895             view->setTransparent(!drawsBackground);
896     }
897
898     m_drawingArea->pageBackgroundTransparencyChanged();
899     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize));
900 }
901
902 void WebPage::setDrawsTransparentBackground(bool drawsTransparentBackground)
903 {
904     if (m_drawsTransparentBackground == drawsTransparentBackground)
905         return;
906
907     m_drawsTransparentBackground = drawsTransparentBackground;
908
909     Color backgroundColor = drawsTransparentBackground ? Color::transparent : Color::white;
910     for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
911         if (FrameView* view = coreFrame->view())
912             view->setBaseBackgroundColor(backgroundColor);
913     }
914
915     m_drawingArea->pageBackgroundTransparencyChanged();
916     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize));
917 }
918
919 void WebPage::setFocused(bool isFocused)
920 {
921     m_page->focusController()->setFocused(isFocused);
922 }
923
924 void WebPage::setInitialFocus(bool forward)
925 {
926     if (!m_page || !m_page->focusController())
927         return;
928
929     Frame* frame = m_page->focusController()->focusedOrMainFrame();
930     frame->document()->setFocusedNode(0);
931     m_page->focusController()->setInitialFocus(forward ? FocusDirectionForward : FocusDirectionBackward, 0);
932 }
933
934 void WebPage::setWindowResizerSize(const IntSize& windowResizerSize)
935 {
936     if (m_windowResizerSize == windowResizerSize)
937         return;
938
939     m_windowResizerSize = windowResizerSize;
940
941     for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
942         FrameView* view = coreFrame->view();
943         if (view)
944             view->windowResizerRectChanged();
945     }
946 }
947
948 void WebPage::setIsInWindow(bool isInWindow)
949 {
950     if (!isInWindow) {
951         m_page->setCanStartMedia(false);
952         m_page->willMoveOffscreen();
953     } else {
954         m_page->setCanStartMedia(true);
955         m_page->didMoveOnscreen();
956     }
957 }
958
959 void WebPage::didReceivePolicyDecision(uint64_t frameID, uint64_t listenerID, uint32_t policyAction, uint64_t downloadID)
960 {
961     WebFrame* frame = WebProcess::shared().webFrame(frameID);
962     if (!frame)
963         return;
964     frame->didReceivePolicyDecision(listenerID, static_cast<PolicyAction>(policyAction), downloadID);
965 }
966
967 void WebPage::show()
968 {
969     send(Messages::WebPageProxy::ShowPage());
970 }
971
972 void WebPage::setUserAgent(const String& userAgent)
973 {
974     m_userAgent = userAgent;
975 }
976
977 IntRect WebPage::windowResizerRect() const
978 {
979     if (m_windowResizerSize.isEmpty())
980         return IntRect();
981
982     IntSize frameViewSize;
983     if (Frame* coreFrame = m_mainFrame->coreFrame()) {
984         if (FrameView* view = coreFrame->view())
985             frameViewSize = view->size();
986     }
987
988     return IntRect(frameViewSize.width() - m_windowResizerSize.width(), frameViewSize.height() - m_windowResizerSize.height(), 
989                    m_windowResizerSize.width(), m_windowResizerSize.height());
990 }
991
992 void WebPage::runJavaScriptInMainFrame(const String& script, uint64_t callbackID)
993 {
994     // NOTE: We need to be careful when running scripts that the objects we depend on don't
995     // disappear during script execution.
996
997     JSLock lock(SilenceAssertionsOnly);
998     JSValue resultValue = m_mainFrame->coreFrame()->script()->executeScript(script, true).jsValue();
999     String resultString;
1000     if (resultValue)
1001         resultString = ustringToString(resultValue.toString(m_mainFrame->coreFrame()->script()->globalObject(mainThreadNormalWorld())->globalExec()));
1002
1003     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1004 }
1005
1006 void WebPage::getContentsAsString(uint64_t callbackID)
1007 {
1008     String resultString = m_mainFrame->contentsAsString();
1009     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1010 }
1011
1012 void WebPage::getRenderTreeExternalRepresentation(uint64_t callbackID)
1013 {
1014     String resultString = renderTreeExternalRepresentation();
1015     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1016 }
1017
1018 void WebPage::getSelectionOrContentsAsString(uint64_t callbackID)
1019 {
1020     String resultString = m_mainFrame->selectionAsString();
1021     if (resultString.isEmpty())
1022         resultString = m_mainFrame->contentsAsString();
1023     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1024 }
1025
1026 void WebPage::getSourceForFrame(uint64_t frameID, uint64_t callbackID)
1027 {
1028     String resultString;
1029     if (WebFrame* frame = WebProcess::shared().webFrame(frameID))
1030        resultString = frame->source();
1031
1032     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1033 }
1034
1035 void WebPage::getMainResourceDataOfFrame(uint64_t frameID, uint64_t callbackID)
1036 {
1037     CoreIPC::DataReference dataReference;
1038
1039     RefPtr<SharedBuffer> buffer;
1040     if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) {
1041         if (DocumentLoader* loader = frame->coreFrame()->loader()->documentLoader()) {
1042             if ((buffer = loader->mainResourceData()))
1043                 dataReference = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size());
1044         }
1045     }
1046
1047     send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
1048 }
1049
1050 void WebPage::getWebArchiveOfFrame(uint64_t frameID, uint64_t callbackID)
1051 {
1052     CoreIPC::DataReference dataReference;
1053
1054 #if PLATFORM(MAC) || PLATFORM(WIN)
1055     RetainPtr<CFDataRef> data;
1056     if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) {
1057         if (RefPtr<LegacyWebArchive> archive = LegacyWebArchive::create(frame->coreFrame())) {
1058             if ((data = archive->rawDataRepresentation()))
1059                 dataReference = CoreIPC::DataReference(CFDataGetBytePtr(data.get()), CFDataGetLength(data.get()));
1060         }
1061     }
1062 #endif
1063
1064     send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
1065 }
1066
1067 void WebPage::preferencesDidChange(const WebPreferencesStore& store)
1068 {
1069     WebPreferencesStore::removeTestRunnerOverrides();
1070     updatePreferences(store);
1071 }
1072
1073 void WebPage::updatePreferences(const WebPreferencesStore& store)
1074 {
1075     Settings* settings = m_page->settings();
1076
1077     m_tabToLinks = store.getBoolValueForKey(WebPreferencesKey::tabsToLinksKey());
1078
1079     // FIXME: This should be generated from macro expansion for all preferences,
1080     // but we currently don't match the naming of WebCore exactly so we are
1081     // handrolling the boolean and integer preferences until that is fixed.
1082
1083 #define INITIALIZE_SETTINGS(KeyUpper, KeyLower, TypeName, Type, DefaultValue) settings->set##KeyUpper(store.get##TypeName##ValueForKey(WebPreferencesKey::KeyLower##Key()));
1084
1085     FOR_EACH_WEBKIT_STRING_PREFERENCE(INITIALIZE_SETTINGS)
1086
1087 #undef INITIALIZE_SETTINGS
1088
1089     settings->setJavaScriptEnabled(store.getBoolValueForKey(WebPreferencesKey::javaScriptEnabledKey()));
1090     settings->setLoadsImagesAutomatically(store.getBoolValueForKey(WebPreferencesKey::loadsImagesAutomaticallyKey()));
1091     settings->setPluginsEnabled(store.getBoolValueForKey(WebPreferencesKey::pluginsEnabledKey()));
1092     settings->setJavaEnabled(store.getBoolValueForKey(WebPreferencesKey::javaEnabledKey()));
1093     settings->setOfflineWebApplicationCacheEnabled(store.getBoolValueForKey(WebPreferencesKey::offlineWebApplicationCacheEnabledKey()));
1094     settings->setLocalStorageEnabled(store.getBoolValueForKey(WebPreferencesKey::localStorageEnabledKey()));
1095     settings->setXSSAuditorEnabled(store.getBoolValueForKey(WebPreferencesKey::xssAuditorEnabledKey()));
1096     settings->setFrameFlatteningEnabled(store.getBoolValueForKey(WebPreferencesKey::frameFlatteningEnabledKey()));
1097     settings->setPrivateBrowsingEnabled(store.getBoolValueForKey(WebPreferencesKey::privateBrowsingEnabledKey()));
1098     settings->setDeveloperExtrasEnabled(store.getBoolValueForKey(WebPreferencesKey::developerExtrasEnabledKey()));
1099     settings->setTextAreasAreResizable(store.getBoolValueForKey(WebPreferencesKey::textAreasAreResizableKey()));
1100     settings->setNeedsSiteSpecificQuirks(store.getBoolValueForKey(WebPreferencesKey::needsSiteSpecificQuirksKey()));
1101     settings->setJavaScriptCanOpenWindowsAutomatically(store.getBoolValueForKey(WebPreferencesKey::javaScriptCanOpenWindowsAutomaticallyKey()));
1102     settings->setForceFTPDirectoryListings(store.getBoolValueForKey(WebPreferencesKey::forceFTPDirectoryListingsKey()));
1103     settings->setDNSPrefetchingEnabled(store.getBoolValueForKey(WebPreferencesKey::dnsPrefetchingEnabledKey()));
1104     settings->setWebArchiveDebugModeEnabled(store.getBoolValueForKey(WebPreferencesKey::webArchiveDebugModeEnabledKey()));
1105     settings->setLocalFileContentSniffingEnabled(store.getBoolValueForKey(WebPreferencesKey::localFileContentSniffingEnabledKey()));
1106     settings->setUsesPageCache(store.getBoolValueForKey(WebPreferencesKey::usesPageCacheKey()));
1107     settings->setAuthorAndUserStylesEnabled(store.getBoolValueForKey(WebPreferencesKey::authorAndUserStylesEnabledKey()));
1108     settings->setPaginateDuringLayoutEnabled(store.getBoolValueForKey(WebPreferencesKey::paginateDuringLayoutEnabledKey()));
1109     settings->setDOMPasteAllowed(store.getBoolValueForKey(WebPreferencesKey::domPasteAllowedKey()));
1110
1111     settings->setMinimumFontSize(store.getUInt32ValueForKey(WebPreferencesKey::minimumFontSizeKey()));
1112     settings->setMinimumLogicalFontSize(store.getUInt32ValueForKey(WebPreferencesKey::minimumLogicalFontSizeKey()));
1113     settings->setDefaultFontSize(store.getUInt32ValueForKey(WebPreferencesKey::defaultFontSizeKey()));
1114     settings->setDefaultFixedFontSize(store.getUInt32ValueForKey(WebPreferencesKey::defaultFixedFontSizeKey()));
1115
1116 #if PLATFORM(WIN)
1117     // Temporarily turn off accelerated compositing until we have a good solution for rendering it.
1118     settings->setAcceleratedCompositingEnabled(false);
1119 #else
1120     settings->setAcceleratedCompositingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedCompositingEnabledKey()));
1121 #endif
1122     settings->setShowDebugBorders(store.getBoolValueForKey(WebPreferencesKey::compositingBordersVisibleKey()));
1123     settings->setShowRepaintCounter(store.getBoolValueForKey(WebPreferencesKey::compositingRepaintCountersVisibleKey()));
1124
1125 #if ENABLE(DATABASE)
1126     AbstractDatabase::setIsAvailable(store.getBoolValueForKey(WebPreferencesKey::databasesEnabledKey()));
1127 #endif
1128
1129     platformPreferencesDidChange(store);
1130 }
1131
1132 #if ENABLE(INSPECTOR)
1133 WebInspector* WebPage::inspector()
1134 {
1135     if (m_isClosed)
1136         return 0;
1137     if (!m_inspector)
1138         m_inspector = adoptPtr(new WebInspector(this));
1139     return m_inspector.get();
1140 }
1141 #endif
1142
1143 #if !PLATFORM(MAC)
1144 bool WebPage::handleEditingKeyboardEvent(KeyboardEvent* evt)
1145 {
1146     Node* node = evt->target()->toNode();
1147     ASSERT(node);
1148     Frame* frame = node->document()->frame();
1149     ASSERT(frame);
1150
1151     const PlatformKeyboardEvent* keyEvent = evt->keyEvent();
1152     if (!keyEvent)
1153         return false;
1154
1155     Editor::Command command = frame->editor()->command(interpretKeyEvent(evt));
1156
1157     if (keyEvent->type() == PlatformKeyboardEvent::RawKeyDown) {
1158         // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated,
1159         // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated
1160         // (e.g. Tab that inserts a Tab character, or Enter).
1161         return !command.isTextInsertion() && command.execute(evt);
1162     }
1163
1164     if (command.execute(evt))
1165         return true;
1166
1167     // Don't insert null or control characters as they can result in unexpected behaviour
1168     if (evt->charCode() < ' ')
1169         return false;
1170
1171     return frame->editor()->insertText(evt->keyEvent()->text(), evt);
1172 }
1173 #endif
1174
1175 WebEditCommand* WebPage::webEditCommand(uint64_t commandID)
1176 {
1177     return m_editCommandMap.get(commandID).get();
1178 }
1179
1180 void WebPage::addWebEditCommand(uint64_t commandID, WebEditCommand* command)
1181 {
1182     m_editCommandMap.set(commandID, command);
1183 }
1184
1185 void WebPage::removeWebEditCommand(uint64_t commandID)
1186 {
1187     m_editCommandMap.remove(commandID);
1188 }
1189
1190 void WebPage::unapplyEditCommand(uint64_t commandID)
1191 {
1192     WebEditCommand* command = webEditCommand(commandID);
1193     if (!command)
1194         return;
1195
1196     command->command()->unapply();
1197 }
1198
1199 void WebPage::reapplyEditCommand(uint64_t commandID)
1200 {
1201     WebEditCommand* command = webEditCommand(commandID);
1202     if (!command)
1203         return;
1204
1205     m_isInRedo = true;
1206     command->command()->reapply();
1207     m_isInRedo = false;
1208 }
1209
1210 void WebPage::didRemoveEditCommand(uint64_t commandID)
1211 {
1212     removeWebEditCommand(commandID);
1213 }
1214
1215 void WebPage::setActivePopupMenu(WebPopupMenu* menu)
1216 {
1217     m_activePopupMenu = menu;
1218 }
1219
1220 void WebPage::setActiveOpenPanelResultListener(PassRefPtr<WebOpenPanelResultListener> openPanelResultListener)
1221 {
1222     m_activeOpenPanelResultListener = openPanelResultListener;
1223 }
1224
1225 bool WebPage::findStringFromInjectedBundle(const String& target, FindOptions options)
1226 {
1227     return m_page->findString(target, options);
1228 }
1229
1230 void WebPage::findString(const String& string, uint32_t options, uint32_t maxMatchCount)
1231 {
1232     m_findController.findString(string, static_cast<FindOptions>(options), maxMatchCount);
1233 }
1234
1235 void WebPage::hideFindUI()
1236 {
1237     m_findController.hideFindUI();
1238 }
1239
1240 void WebPage::countStringMatches(const String& string, uint32_t options, uint32_t maxMatchCount)
1241 {
1242     m_findController.countStringMatches(string, static_cast<FindOptions>(options), maxMatchCount);
1243 }
1244
1245 void WebPage::didChangeSelectedIndexForActivePopupMenu(int32_t newIndex)
1246 {
1247     if (!m_activePopupMenu)
1248         return;
1249
1250     m_activePopupMenu->didChangeSelectedIndex(newIndex);
1251     m_activePopupMenu = 0;
1252 }
1253
1254 void WebPage::didChooseFilesForOpenPanel(const Vector<String>& files)
1255 {
1256     if (!m_activeOpenPanelResultListener)
1257         return;
1258
1259     m_activeOpenPanelResultListener->didChooseFiles(files);
1260     m_activeOpenPanelResultListener = 0;
1261 }
1262
1263 void WebPage::didCancelForOpenPanel()
1264 {
1265     m_activeOpenPanelResultListener = 0;
1266 }
1267
1268 void WebPage::advanceToNextMisspelling(bool startBeforeSelection)
1269 {
1270     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1271     frame->editor()->advanceToNextMisspelling(startBeforeSelection);
1272 }
1273
1274 void WebPage::changeSpellingToWord(const String& word)
1275 {
1276     replaceSelectionWithText(m_page->focusController()->focusedOrMainFrame(), word);
1277 }
1278
1279 void WebPage::unmarkAllMisspellings()
1280 {
1281     for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
1282         if (Document* document = frame->document())
1283             document->markers()->removeMarkers(DocumentMarker::Spelling);
1284     }
1285 }
1286
1287 void WebPage::unmarkAllBadGrammar()
1288 {
1289     for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
1290         if (Document* document = frame->document())
1291             document->markers()->removeMarkers(DocumentMarker::Grammar);
1292     }
1293 }
1294
1295 #if PLATFORM(MAC)
1296 void WebPage::uppercaseWord()
1297 {
1298     m_page->focusController()->focusedOrMainFrame()->editor()->uppercaseWord();
1299 }
1300
1301 void WebPage::lowercaseWord()
1302 {
1303     m_page->focusController()->focusedOrMainFrame()->editor()->lowercaseWord();
1304 }
1305
1306 void WebPage::capitalizeWord()
1307 {
1308     m_page->focusController()->focusedOrMainFrame()->editor()->capitalizeWord();
1309 }
1310 #endif
1311     
1312 void WebPage::setTextForActivePopupMenu(int32_t index)
1313 {
1314     if (!m_activePopupMenu)
1315         return;
1316
1317     m_activePopupMenu->setTextForIndex(index);
1318 }
1319
1320 void WebPage::didSelectItemFromActiveContextMenu(const WebContextMenuItemData& item)
1321 {
1322     ASSERT(m_contextMenu);
1323     m_contextMenu->itemSelected(item);
1324     m_contextMenu = 0;
1325 }
1326
1327 void WebPage::replaceSelectionWithText(Frame* frame, const String& text)
1328 {
1329     if (frame->selection()->isNone())
1330         return;
1331     
1332     RefPtr<DocumentFragment> textFragment = createFragmentFromText(frame->selection()->toNormalizedRange().get(), text);
1333     applyCommand(ReplaceSelectionCommand::create(frame->document(), textFragment.release(), true, false, true));
1334     frame->selection()->revealSelection(ScrollAlignment::alignToEdgeIfNeeded);
1335 }
1336
1337 #if PLATFORM(MAC)
1338
1339 void WebPage::addPluginView(PluginView* pluginView)
1340 {
1341     ASSERT(!m_pluginViews.contains(pluginView));
1342
1343     m_pluginViews.add(pluginView);
1344 }
1345
1346 void WebPage::removePluginView(PluginView* pluginView)
1347 {
1348     ASSERT(m_pluginViews.contains(pluginView));
1349
1350     m_pluginViews.remove(pluginView);
1351 }
1352
1353 void WebPage::setWindowIsVisible(bool windowIsVisible)
1354 {
1355     m_windowIsVisible = windowIsVisible;
1356
1357     // Tell all our plug-in views that the window visibility changed.
1358     for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
1359         (*it)->setWindowIsVisible(windowIsVisible);
1360 }
1361
1362 void WebPage::windowAndViewFramesChanged(const WebCore::IntRect& windowFrameInScreenCoordinates, const WebCore::IntRect& viewFrameInWindowCoordinates, const WebCore::IntPoint& accessibilityViewCoordinates)
1363 {
1364     m_windowFrameInScreenCoordinates = windowFrameInScreenCoordinates;
1365     m_viewFrameInWindowCoordinates = viewFrameInWindowCoordinates;
1366     m_accessibilityPosition = accessibilityViewCoordinates;
1367     
1368     // Tell all our plug-in views that the window and view frames have changed.
1369     for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
1370         (*it)->windowAndViewFramesChanged(windowFrameInScreenCoordinates, viewFrameInWindowCoordinates);
1371 }
1372
1373 bool WebPage::windowIsFocused() const
1374 {
1375     return m_page->focusController()->isActive();
1376 }
1377
1378 #endif
1379
1380 void WebPage::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
1381 {
1382     if (messageID.is<CoreIPC::MessageClassDrawingAreaLegacy>()) {
1383         if (m_drawingArea)
1384             m_drawingArea->didReceiveMessage(connection, messageID, arguments);
1385         return;
1386     }
1387
1388 #if ENABLE(INSPECTOR)
1389     if (messageID.is<CoreIPC::MessageClassWebInspector>()) {
1390         if (WebInspector* inspector = this->inspector())
1391             inspector->didReceiveWebInspectorMessage(connection, messageID, arguments);
1392         return;
1393     }
1394 #endif
1395
1396     didReceiveWebPageMessage(connection, messageID, arguments);
1397 }
1398
1399 CoreIPC::SyncReplyMode WebPage::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments, CoreIPC::ArgumentEncoder* reply)
1400 {   
1401     return didReceiveSyncWebPageMessage(connection, messageID, arguments, reply);
1402 }
1403     
1404 InjectedBundleBackForwardList* WebPage::backForwardList()
1405 {
1406     if (!m_backForwardList)
1407         m_backForwardList = InjectedBundleBackForwardList::create(this);
1408     return m_backForwardList.get();
1409 }
1410
1411 #if PLATFORM(QT)
1412 void WebPage::findZoomableAreaForPoint(const WebCore::IntPoint& point)
1413 {
1414     const int minimumZoomTargetWidth = 100;
1415
1416     Frame* mainframe = m_mainFrame->coreFrame();
1417     HitTestResult result = mainframe->eventHandler()->hitTestResultAtPoint(mainframe->view()->windowToContents(point), /*allowShadowContent*/ false, /*ignoreClipping*/ true);
1418
1419     Node* node = result.innerNode();
1420     while (node && node->getRect().width() < minimumZoomTargetWidth)
1421         node = node->parentNode();
1422
1423     IntRect zoomableArea;
1424     if (node)
1425         zoomableArea = node->getRect();
1426     send(Messages::WebPageProxy::DidFindZoomableArea(zoomableArea));
1427 }
1428 #endif
1429
1430 WebPage::SandboxExtensionTracker::~SandboxExtensionTracker()
1431 {
1432     invalidate();
1433 }
1434
1435 void WebPage::SandboxExtensionTracker::invalidate()
1436 {
1437     if (m_pendingProvisionalSandboxExtension) {
1438         m_pendingProvisionalSandboxExtension->invalidate();
1439         m_pendingProvisionalSandboxExtension = 0;
1440     }
1441
1442     if (m_provisionalSandboxExtension) {
1443         m_provisionalSandboxExtension->invalidate();
1444         m_provisionalSandboxExtension = 0;
1445     }
1446
1447     if (m_committedSandboxExtension) {
1448         m_committedSandboxExtension->invalidate();
1449         m_committedSandboxExtension = 0;
1450     }
1451 }
1452
1453 void WebPage::SandboxExtensionTracker::beginLoad(WebFrame* frame, const SandboxExtension::Handle& handle)
1454 {
1455     ASSERT(frame->isMainFrame());
1456
1457     ASSERT(!m_pendingProvisionalSandboxExtension);
1458     m_pendingProvisionalSandboxExtension = SandboxExtension::create(handle);
1459 }
1460
1461 void WebPage::SandboxExtensionTracker::didStartProvisionalLoad(WebFrame* frame)
1462 {
1463     if (!frame->isMainFrame())
1464         return;
1465
1466     ASSERT(!m_provisionalSandboxExtension);
1467
1468     m_provisionalSandboxExtension = m_pendingProvisionalSandboxExtension.release();
1469     if (!m_provisionalSandboxExtension)
1470         return;
1471
1472     m_provisionalSandboxExtension->consume();
1473 }
1474
1475 void WebPage::SandboxExtensionTracker::didCommitProvisionalLoad(WebFrame* frame)
1476 {
1477     if (!frame->isMainFrame())
1478         return;
1479     
1480     ASSERT(!m_pendingProvisionalSandboxExtension);
1481
1482     // The provisional load has been committed. Invalidate the currently committed sandbox
1483     // extension and make the provisional sandbox extension the committed sandbox extension.
1484     if (m_committedSandboxExtension)
1485         m_committedSandboxExtension->invalidate();
1486
1487     m_committedSandboxExtension = m_provisionalSandboxExtension.release();
1488 }
1489
1490 void WebPage::SandboxExtensionTracker::didFailProvisionalLoad(WebFrame* frame)
1491 {
1492     if (!frame->isMainFrame())
1493         return;
1494
1495     ASSERT(!m_pendingProvisionalSandboxExtension);
1496     if (!m_provisionalSandboxExtension)
1497         return;
1498
1499     m_provisionalSandboxExtension->invalidate();
1500     m_provisionalSandboxExtension = 0;
1501 }
1502
1503 bool WebPage::hasLocalDataForURL(const KURL& url)
1504 {
1505     if (url.isLocalFile())
1506         return true;
1507
1508     FrameLoader* frameLoader = m_page->mainFrame()->loader();
1509     DocumentLoader* documentLoader = frameLoader ? frameLoader->documentLoader() : 0;
1510     if (documentLoader && documentLoader->subresource(url))
1511         return true;
1512
1513     return platformHasLocalDataForURL(url);
1514 }
1515
1516 void WebPage::setCustomTextEncodingName(const String& encoding)
1517 {
1518     m_page->mainFrame()->loader()->reloadWithOverrideEncoding(encoding);
1519 }
1520
1521 void WebPage::didRemoveBackForwardItem(uint64_t itemID)
1522 {
1523     WebBackForwardListProxy::removeItem(itemID);
1524 }
1525
1526 #if PLATFORM(MAC)
1527
1528 bool WebPage::isSpeaking()
1529 {
1530     bool result;
1531     return sendSync(Messages::WebPageProxy::GetIsSpeaking(), Messages::WebPageProxy::GetIsSpeaking::Reply(result)) && result;
1532 }
1533
1534 void WebPage::speak(const String& string)
1535 {
1536     send(Messages::WebPageProxy::Speak(string));
1537 }
1538
1539 void WebPage::stopSpeaking()
1540 {
1541     send(Messages::WebPageProxy::StopSpeaking());
1542 }
1543
1544 #endif
1545
1546 } // namespace WebKit