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