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