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