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