Crash in WebProcess at com.apple.WebCore: WebCore::Page::goToItem + 46
[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     HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
491     ASSERT(item);
492     if (!item)
493         return;
494
495     m_sandboxExtensionTracker.beginLoad(m_mainFrame.get(), sandboxExtensionHandle);
496     m_page->goToItem(item, FrameLoadTypeForward);
497 }
498
499 void WebPage::goBack(uint64_t backForwardItemID, const SandboxExtension::Handle& sandboxExtensionHandle)
500 {
501     HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
502     ASSERT(item);
503     if (!item)
504         return;
505
506     m_sandboxExtensionTracker.beginLoad(m_mainFrame.get(), sandboxExtensionHandle);
507     m_page->goToItem(item, FrameLoadTypeBack);
508 }
509
510 void WebPage::goToBackForwardItem(uint64_t backForwardItemID, const SandboxExtension::Handle& sandboxExtensionHandle)
511 {
512     HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
513     ASSERT(item);
514     if (!item)
515         return;
516
517     m_sandboxExtensionTracker.beginLoad(m_mainFrame.get(), sandboxExtensionHandle);
518     m_page->goToItem(item, FrameLoadTypeIndexedBackForward);
519 }
520
521 void WebPage::layoutIfNeeded()
522 {
523     if (m_mainFrame->coreFrame()->view())
524         m_mainFrame->coreFrame()->view()->updateLayoutAndStyleIfNeededRecursive();
525 }
526
527 void WebPage::setSize(const WebCore::IntSize& viewSize)
528 {
529 #if ENABLE(TILED_BACKING_STORE)
530     // If we are resizing to content ignore external attempts.
531     if (!m_resizesToContentsLayoutSize.isEmpty())
532         return;
533 #endif
534
535     if (m_viewSize == viewSize)
536         return;
537
538     Frame* frame = m_page->mainFrame();
539     
540     frame->view()->resize(viewSize);
541     frame->view()->setNeedsLayout();
542     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), viewSize));
543     
544     m_viewSize = viewSize;
545 }
546
547 #if ENABLE(TILED_BACKING_STORE)
548 void WebPage::setActualVisibleContentRect(const IntRect& rect)
549 {
550     Frame* frame = m_page->mainFrame();
551
552     frame->view()->setActualVisibleContentRect(rect);
553 }
554
555 void WebPage::setResizesToContentsUsingLayoutSize(const IntSize& targetLayoutSize)
556 {
557     if (m_resizesToContentsLayoutSize == targetLayoutSize)
558         return;
559
560     m_resizesToContentsLayoutSize = targetLayoutSize;
561
562     Frame* frame = m_page->mainFrame();
563     if (m_resizesToContentsLayoutSize.isEmpty()) {
564         frame->view()->setDelegatesScrolling(false);
565         frame->view()->setUseFixedLayout(false);
566         frame->view()->setPaintsEntireContents(false);
567     } else {
568         frame->view()->setDelegatesScrolling(true);
569         frame->view()->setUseFixedLayout(true);
570         frame->view()->setPaintsEntireContents(true);
571         frame->view()->setFixedLayoutSize(m_resizesToContentsLayoutSize);
572     }
573     frame->view()->forceLayout();
574 }
575
576 void WebPage::resizeToContentsIfNeeded()
577 {
578     if (m_resizesToContentsLayoutSize.isEmpty())
579         return;
580
581     Frame* frame = m_page->mainFrame();
582
583     IntSize contentSize = frame->view()->contentsSize();
584     if (contentSize == m_viewSize)
585         return;
586
587     m_viewSize = contentSize;
588     frame->view()->resize(m_viewSize);
589     frame->view()->setNeedsLayout();
590 }
591 #endif
592
593 void WebPage::scrollMainFrameIfNotAtMaxScrollPosition(const IntSize& scrollOffset)
594 {
595     Frame* frame = m_page->mainFrame();
596
597     IntPoint scrollPosition = frame->view()->scrollPosition();
598     IntPoint maximumScrollPosition = frame->view()->maximumScrollPosition();
599
600     // If the current scroll position in a direction is the max scroll position 
601     // we don't want to scroll at all.
602     IntSize newScrollOffset;
603     if (scrollPosition.x() < maximumScrollPosition.x())
604         newScrollOffset.setWidth(scrollOffset.width());
605     if (scrollPosition.y() < maximumScrollPosition.y())
606         newScrollOffset.setHeight(scrollOffset.height());
607
608     if (newScrollOffset.isZero())
609         return;
610
611     frame->view()->setScrollPosition(frame->view()->scrollPosition() + newScrollOffset);
612 }
613
614 void WebPage::drawRect(GraphicsContext& graphicsContext, const IntRect& rect)
615 {
616     graphicsContext.save();
617     graphicsContext.clip(rect);
618     m_mainFrame->coreFrame()->view()->paint(&graphicsContext, rect);
619     graphicsContext.restore();
620
621     // FIXME: Remove this code once we're using the new drawing area on mac and windows.
622     if (m_pageOverlay && m_drawingArea->info().type != DrawingAreaInfo::Impl)
623         drawPageOverlay(graphicsContext, rect);
624 }
625
626 void WebPage::drawPageOverlay(GraphicsContext& graphicsContext, const IntRect& rect)
627 {
628     ASSERT(m_pageOverlay);
629
630     graphicsContext.save();
631     graphicsContext.clip(rect);
632     m_pageOverlay->drawRect(graphicsContext, rect);
633     graphicsContext.restore();
634 }
635
636 double WebPage::textZoomFactor() const
637 {
638     Frame* frame = m_mainFrame->coreFrame();
639     if (!frame)
640         return 1;
641     return frame->textZoomFactor();
642 }
643
644 void WebPage::setTextZoomFactor(double zoomFactor)
645 {
646     Frame* frame = m_mainFrame->coreFrame();
647     if (!frame)
648         return;
649     frame->setTextZoomFactor(static_cast<float>(zoomFactor));
650 }
651
652 double WebPage::pageZoomFactor() const
653 {
654     Frame* frame = m_mainFrame->coreFrame();
655     if (!frame)
656         return 1;
657     return frame->pageZoomFactor();
658 }
659
660 void WebPage::setPageZoomFactor(double zoomFactor)
661 {
662     Frame* frame = m_mainFrame->coreFrame();
663     if (!frame)
664         return;
665     frame->setPageZoomFactor(static_cast<float>(zoomFactor));
666 }
667
668 void WebPage::setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor)
669 {
670     Frame* frame = m_mainFrame->coreFrame();
671     if (!frame)
672         return;
673     return frame->setPageAndTextZoomFactors(static_cast<float>(pageZoomFactor), static_cast<float>(textZoomFactor));
674 }
675
676 void WebPage::scaleWebView(double scale, const IntPoint& origin)
677 {
678     Frame* frame = m_mainFrame->coreFrame();
679     if (!frame)
680         return;
681     frame->scalePage(scale, origin);
682
683     send(Messages::WebPageProxy::ViewScaleFactorDidChange(scale));
684 }
685
686 double WebPage::viewScaleFactor() const
687 {
688     Frame* frame = m_mainFrame->coreFrame();
689     if (!frame)
690         return 1;
691     return frame->pageScaleFactor();
692 }
693
694 void WebPage::setUseFixedLayout(bool fixed)
695 {
696     Frame* frame = m_mainFrame->coreFrame();
697     if (!frame)
698         return;
699
700     FrameView* view = frame->view();
701     if (!view)
702         return;
703
704     view->setUseFixedLayout(fixed);
705     if (!fixed)
706         view->setFixedLayoutSize(IntSize());
707 }
708
709 void WebPage::setFixedLayoutSize(const IntSize& size)
710 {
711     Frame* frame = m_mainFrame->coreFrame();
712     if (!frame)
713         return;
714     
715     FrameView* view = frame->view();
716     if (!view)
717         return;
718
719     view->setFixedLayoutSize(size);
720     view->forceLayout();
721 }
722
723 void WebPage::installPageOverlay(PassRefPtr<PageOverlay> pageOverlay)
724 {
725     if (m_pageOverlay)
726         pageOverlay->setPage(0);
727
728     m_pageOverlay = pageOverlay;
729     m_pageOverlay->setPage(this);
730
731     m_drawingArea->didInstallPageOverlay();
732
733     m_pageOverlay->setNeedsDisplay();
734 }
735
736 void WebPage::uninstallPageOverlay(PageOverlay* pageOverlay)
737 {
738     if (pageOverlay != m_pageOverlay)
739         return;
740
741     m_pageOverlay->setPage(0);
742     m_pageOverlay = nullptr;
743
744     m_drawingArea->didUninstallPageOverlay();
745 }
746
747 PassRefPtr<WebImage> WebPage::snapshotInViewCoordinates(const IntRect& rect, ImageOptions options)
748 {
749     FrameView* frameView = m_mainFrame->coreFrame()->view();
750     if (!frameView)
751         return 0;
752
753     frameView->updateLayoutAndStyleIfNeededRecursive();
754
755     PaintBehavior oldBehavior = frameView->paintBehavior();
756     frameView->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
757
758     RefPtr<WebImage> snapshot = WebImage::create(rect.size(), options);
759     OwnPtr<WebCore::GraphicsContext> graphicsContext = snapshot->bitmap()->createGraphicsContext();
760
761     graphicsContext->save();
762     graphicsContext->translate(-rect.x(), -rect.y());
763     frameView->paint(graphicsContext.get(), rect);
764     graphicsContext->restore();
765
766     frameView->setPaintBehavior(oldBehavior);
767
768     return snapshot.release();
769 }
770
771 PassRefPtr<WebImage> WebPage::scaledSnapshotInDocumentCoordinates(const IntRect& rect, double scaleFactor, ImageOptions options)
772 {
773     FrameView* frameView = m_mainFrame->coreFrame()->view();
774     if (!frameView)
775         return 0;
776
777     frameView->updateLayoutAndStyleIfNeededRecursive();
778
779     PaintBehavior oldBehavior = frameView->paintBehavior();
780     frameView->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
781
782     bool scale = scaleFactor != 1;
783     IntSize size = rect.size();
784     if (scale) 
785         size = IntSize(ceil(rect.width() * scaleFactor), ceil(rect.height() * scaleFactor));
786
787     RefPtr<WebImage> snapshot = WebImage::create(size, options);
788     OwnPtr<WebCore::GraphicsContext> graphicsContext = snapshot->bitmap()->createGraphicsContext();
789     graphicsContext->save();
790     
791     if (scale)
792         graphicsContext->scale(FloatSize(scaleFactor, scaleFactor));
793     
794     graphicsContext->translate(-rect.x(), -rect.y());
795     frameView->paintContents(graphicsContext.get(), rect);
796     graphicsContext->restore();
797
798     frameView->setPaintBehavior(oldBehavior);
799
800     return snapshot.release();
801 }
802
803 PassRefPtr<WebImage> WebPage::snapshotInDocumentCoordinates(const IntRect& rect, ImageOptions options)
804 {
805     return scaledSnapshotInDocumentCoordinates(rect, 1, options);
806 }
807
808 void WebPage::pageDidScroll()
809 {
810     // Hide the find indicator.
811     m_findController.hideFindIndicator();
812
813     m_uiClient.pageDidScroll(this);
814
815     send(Messages::WebPageProxy::PageDidScroll());
816 }
817
818 #if ENABLE(TILED_BACKING_STORE)
819 void WebPage::pageDidRequestScroll(const IntSize& delta)
820 {
821     send(Messages::WebPageProxy::PageDidRequestScroll(delta));
822 }
823 #endif
824
825 WebContextMenu* WebPage::contextMenu()
826 {
827     if (!m_contextMenu)
828         m_contextMenu = WebContextMenu::create(this);
829     return m_contextMenu.get();
830 }
831
832 void WebPage::getLocationAndLengthFromRange(Range* range, uint64_t& location, uint64_t& length)
833 {
834     location = notFound;
835     length = 0;
836
837     if (!range || !range->startContainer())
838         return;
839
840     Element* selectionRoot = range->ownerDocument()->frame()->selection()->rootEditableElement();
841     Element* scope = selectionRoot ? selectionRoot : range->ownerDocument()->documentElement();
842     
843     // Mouse events may cause TSM to attempt to create an NSRange for a portion of the view
844     // that is not inside the current editable region.  These checks ensure we don't produce
845     // potentially invalid data when responding to such requests.
846     if (range->startContainer() != scope && !range->startContainer()->isDescendantOf(scope))
847         return;
848     if (range->endContainer() != scope && !range->endContainer()->isDescendantOf(scope))
849         return;
850
851     RefPtr<Range> testRange = Range::create(scope->document(), scope, 0, range->startContainer(), range->startOffset());
852     ASSERT(testRange->startContainer() == scope);
853     location = TextIterator::rangeLength(testRange.get());
854     
855     ExceptionCode ec;
856     testRange->setEnd(range->endContainer(), range->endOffset(), ec);
857     ASSERT(testRange->startContainer() == scope);
858     length = TextIterator::rangeLength(testRange.get()) - location;
859 }
860
861 // Events 
862
863 static const WebEvent* g_currentEvent = 0;
864
865 // FIXME: WebPage::currentEvent is used by the plug-in code to avoid having to convert from DOM events back to
866 // WebEvents. When we get the event handling sorted out, this should go away and the Widgets should get the correct
867 // platform events passed to the event handler code.
868 const WebEvent* WebPage::currentEvent()
869 {
870     return g_currentEvent;
871 }
872
873 class CurrentEvent {
874 public:
875     explicit CurrentEvent(const WebEvent& event)
876         : m_previousCurrentEvent(g_currentEvent)
877     {
878         g_currentEvent = &event;
879     }
880
881     ~CurrentEvent()
882     {
883         g_currentEvent = m_previousCurrentEvent;
884     }
885
886 private:
887     const WebEvent* m_previousCurrentEvent;
888 };
889
890 static bool isContextClick(const PlatformMouseEvent& event)
891 {
892     if (event.button() == WebCore::RightButton)
893         return true;
894
895 #if PLATFORM(MAC)
896     // FIXME: this really should be about OSX-style UI, not about the Mac port
897     if (event.button() == WebCore::LeftButton && event.ctrlKey())
898         return true;
899 #endif
900
901     return false;
902 }
903
904 static bool handleMouseEvent(const WebMouseEvent& mouseEvent, Page* page)
905 {
906     Frame* frame = page->mainFrame();
907     if (!frame->view())
908         return false;
909
910     PlatformMouseEvent platformMouseEvent = platform(mouseEvent);
911
912     switch (platformMouseEvent.eventType()) {
913         case WebCore::MouseEventPressed:
914         {
915             if (isContextClick(platformMouseEvent))
916                 page->contextMenuController()->clearContextMenu();
917             
918             bool handled = frame->eventHandler()->handleMousePressEvent(platformMouseEvent);
919             
920             if (isContextClick(platformMouseEvent)) {
921                 handled = frame->eventHandler()->sendContextMenuEvent(platformMouseEvent);
922                 if (handled)
923                     page->chrome()->showContextMenu();
924             }
925
926             return handled;
927         }
928         case WebCore::MouseEventReleased:
929             return frame->eventHandler()->handleMouseReleaseEvent(platformMouseEvent);
930         case WebCore::MouseEventMoved:
931             return frame->eventHandler()->mouseMoved(platformMouseEvent);
932
933         default:
934             ASSERT_NOT_REACHED();
935             return false;
936     }
937 }
938
939 void WebPage::mouseEvent(const WebMouseEvent& mouseEvent)
940 {
941     bool handled = false;
942     
943     if (m_pageOverlay) {
944         // Let the page overlay handle the event.
945         handled = m_pageOverlay->mouseEvent(mouseEvent);
946     }
947
948     if (!handled) {
949         CurrentEvent currentEvent(mouseEvent);
950
951         handled = handleMouseEvent(mouseEvent, m_page.get());
952     }
953
954     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(mouseEvent.type()), handled));
955 }
956
957 static bool handleWheelEvent(const WebWheelEvent& wheelEvent, Page* page)
958 {
959     Frame* frame = page->mainFrame();
960     if (!frame->view())
961         return false;
962
963     PlatformWheelEvent platformWheelEvent = platform(wheelEvent);
964     return frame->eventHandler()->handleWheelEvent(platformWheelEvent);
965 }
966
967 void WebPage::wheelEvent(const WebWheelEvent& wheelEvent)
968 {
969     CurrentEvent currentEvent(wheelEvent);
970
971     bool handled = handleWheelEvent(wheelEvent, m_page.get());
972     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(wheelEvent.type()), handled));
973 }
974
975 static bool handleKeyEvent(const WebKeyboardEvent& keyboardEvent, Page* page)
976 {
977     if (!page->mainFrame()->view())
978         return false;
979
980     if (keyboardEvent.type() == WebEvent::Char && keyboardEvent.isSystemKey())
981         return page->focusController()->focusedOrMainFrame()->eventHandler()->handleAccessKey(platform(keyboardEvent));
982     return page->focusController()->focusedOrMainFrame()->eventHandler()->keyEvent(platform(keyboardEvent));
983 }
984
985 void WebPage::keyEvent(const WebKeyboardEvent& keyboardEvent)
986 {
987     CurrentEvent currentEvent(keyboardEvent);
988
989     bool handled = handleKeyEvent(keyboardEvent, m_page.get());
990     if (!handled)
991         handled = performDefaultBehaviorForKeyEvent(keyboardEvent);
992
993     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(keyboardEvent.type()), handled));
994 }
995
996 #if ENABLE(GESTURE_EVENTS)
997 static bool handleGestureEvent(const WebGestureEvent& gestureEvent, Page* page)
998 {
999     Frame* frame = page->mainFrame();
1000     if (!frame->view())
1001         return false;
1002
1003     PlatformGestureEvent platformGestureEvent = platform(gestureEvent);
1004     return frame->eventHandler()->handleGestureEvent(platformGestureEvent);
1005 }
1006
1007 void WebPage::gestureEvent(const WebGestureEvent& gestureEvent)
1008 {
1009     CurrentEvent currentEvent(gestureEvent);
1010
1011     bool handled = handleGestureEvent(gestureEvent, m_page.get());
1012     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(gestureEvent.type()), handled));
1013 }
1014 #endif
1015
1016 void WebPage::validateMenuItem(const String& commandName)
1017 {
1018     bool isEnabled = false;
1019     int32_t state = 0;
1020     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1021     if (frame) {
1022         Editor::Command command = frame->editor()->command(commandName);
1023         state = command.state();
1024         isEnabled = command.isSupported() && command.isEnabled();
1025     }
1026
1027     send(Messages::WebPageProxy::DidValidateMenuItem(commandName, isEnabled, state));
1028 }
1029
1030 void WebPage::executeEditCommand(const String& commandName)
1031 {
1032     executeEditingCommand(commandName, String());
1033 }
1034
1035 uint64_t WebPage::restoreSession(const SessionState& sessionState)
1036 {
1037     const BackForwardListItemVector& list = sessionState.list();
1038     size_t size = list.size();
1039     uint64_t currentItemID = 0;
1040     for (size_t i = 0; i < size; ++i) {
1041         WebBackForwardListItem* webItem = list[i].get();
1042         DecoderAdapter decoder(webItem->backForwardData().data(), webItem->backForwardData().size());
1043         
1044         RefPtr<HistoryItem> item = HistoryItem::decodeBackForwardTree(webItem->url(), webItem->title(), webItem->originalURL(), decoder);
1045         if (!item) {
1046             LOG_ERROR("Failed to decode a HistoryItem from session state data.");
1047             return 0;
1048         }
1049         
1050         if (i == sessionState.currentIndex())
1051             currentItemID = webItem->itemID();
1052         
1053         WebBackForwardListProxy::addItemFromUIProcess(list[i]->itemID(), item.release());
1054     }    
1055     ASSERT(currentItemID);
1056     return currentItemID;
1057 }
1058
1059 void WebPage::restoreSessionAndNavigateToCurrentItem(const SessionState& sessionState, const SandboxExtension::Handle& sandboxExtensionHandle)
1060 {
1061     if (uint64_t currentItemID = restoreSession(sessionState))
1062         goToBackForwardItem(currentItemID, sandboxExtensionHandle);
1063 }
1064
1065 #if ENABLE(TOUCH_EVENTS)
1066 static bool handleTouchEvent(const WebTouchEvent& touchEvent, Page* page)
1067 {
1068     Frame* frame = page->mainFrame();
1069     if (!frame->view())
1070         return false;
1071
1072     return frame->eventHandler()->handleTouchEvent(platform(touchEvent));
1073 }
1074
1075 void WebPage::touchEvent(const WebTouchEvent& touchEvent)
1076 {
1077     CurrentEvent currentEvent(touchEvent);
1078
1079     bool handled = handleTouchEvent(touchEvent, m_page.get());
1080
1081     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(touchEvent.type()), handled));
1082 }
1083 #endif
1084
1085 void WebPage::setActive(bool isActive)
1086 {
1087     m_page->focusController()->setActive(isActive);
1088
1089 #if PLATFORM(MAC)    
1090     // Tell all our plug-in views that the window focus changed.
1091     for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
1092         (*it)->setWindowIsFocused(isActive);
1093 #endif
1094 }
1095
1096 void WebPage::setDrawsBackground(bool drawsBackground)
1097 {
1098     if (m_drawsBackground == drawsBackground)
1099         return;
1100
1101     m_drawsBackground = drawsBackground;
1102
1103     for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
1104         if (FrameView* view = coreFrame->view())
1105             view->setTransparent(!drawsBackground);
1106     }
1107
1108     m_drawingArea->pageBackgroundTransparencyChanged();
1109     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize));
1110 }
1111
1112 void WebPage::setDrawsTransparentBackground(bool drawsTransparentBackground)
1113 {
1114     if (m_drawsTransparentBackground == drawsTransparentBackground)
1115         return;
1116
1117     m_drawsTransparentBackground = drawsTransparentBackground;
1118
1119     Color backgroundColor = drawsTransparentBackground ? Color::transparent : Color::white;
1120     for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
1121         if (FrameView* view = coreFrame->view())
1122             view->setBaseBackgroundColor(backgroundColor);
1123     }
1124
1125     m_drawingArea->pageBackgroundTransparencyChanged();
1126     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize));
1127 }
1128
1129 void WebPage::viewWillStartLiveResize()
1130 {
1131     if (!m_page)
1132         return;
1133
1134     // FIXME: This should propagate to all ScrollableAreas.
1135     if (Frame* frame = m_page->focusController()->focusedOrMainFrame()) {
1136         if (FrameView* view = frame->view())
1137             view->willStartLiveResize();
1138     }
1139 }
1140
1141 void WebPage::viewWillEndLiveResize()
1142 {
1143     if (!m_page)
1144         return;
1145
1146     // FIXME: This should propagate to all ScrollableAreas.
1147     if (Frame* frame = m_page->focusController()->focusedOrMainFrame()) {
1148         if (FrameView* view = frame->view())
1149             view->willEndLiveResize();
1150     }
1151 }
1152
1153 void WebPage::setFocused(bool isFocused)
1154 {
1155     m_page->focusController()->setFocused(isFocused);
1156 }
1157
1158 void WebPage::setInitialFocus(bool forward)
1159 {
1160     if (!m_page || !m_page->focusController())
1161         return;
1162
1163     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1164     frame->document()->setFocusedNode(0);
1165     m_page->focusController()->setInitialFocus(forward ? FocusDirectionForward : FocusDirectionBackward, 0);
1166 }
1167
1168 void WebPage::setWindowResizerSize(const IntSize& windowResizerSize)
1169 {
1170     if (m_windowResizerSize == windowResizerSize)
1171         return;
1172
1173     m_windowResizerSize = windowResizerSize;
1174
1175     for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
1176         FrameView* view = coreFrame->view();
1177         if (view)
1178             view->windowResizerRectChanged();
1179     }
1180 }
1181
1182 void WebPage::setIsInWindow(bool isInWindow)
1183 {
1184     if (!isInWindow) {
1185         m_page->setCanStartMedia(false);
1186         m_page->willMoveOffscreen();
1187     } else {
1188         m_page->setCanStartMedia(true);
1189         m_page->didMoveOnscreen();
1190     }
1191 }
1192
1193 void WebPage::didReceivePolicyDecision(uint64_t frameID, uint64_t listenerID, uint32_t policyAction, uint64_t downloadID)
1194 {
1195     WebFrame* frame = WebProcess::shared().webFrame(frameID);
1196     if (!frame)
1197         return;
1198     frame->didReceivePolicyDecision(listenerID, static_cast<PolicyAction>(policyAction), downloadID);
1199 }
1200
1201 void WebPage::show()
1202 {
1203     send(Messages::WebPageProxy::ShowPage());
1204 }
1205
1206 void WebPage::setUserAgent(const String& userAgent)
1207 {
1208     m_userAgent = userAgent;
1209 }
1210
1211 IntRect WebPage::windowResizerRect() const
1212 {
1213     if (m_windowResizerSize.isEmpty())
1214         return IntRect();
1215
1216     IntSize frameViewSize;
1217     if (Frame* coreFrame = m_mainFrame->coreFrame()) {
1218         if (FrameView* view = coreFrame->view())
1219             frameViewSize = view->size();
1220     }
1221
1222     return IntRect(frameViewSize.width() - m_windowResizerSize.width(), frameViewSize.height() - m_windowResizerSize.height(), 
1223                    m_windowResizerSize.width(), m_windowResizerSize.height());
1224 }
1225
1226 void WebPage::runJavaScriptInMainFrame(const String& script, uint64_t callbackID)
1227 {
1228     // NOTE: We need to be careful when running scripts that the objects we depend on don't
1229     // disappear during script execution.
1230
1231     JSLock lock(SilenceAssertionsOnly);
1232     JSValue resultValue = m_mainFrame->coreFrame()->script()->executeScript(script, true).jsValue();
1233     String resultString;
1234     if (resultValue)
1235         resultString = ustringToString(resultValue.toString(m_mainFrame->coreFrame()->script()->globalObject(mainThreadNormalWorld())->globalExec()));
1236
1237     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1238 }
1239
1240 void WebPage::getContentsAsString(uint64_t callbackID)
1241 {
1242     String resultString = m_mainFrame->contentsAsString();
1243     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1244 }
1245
1246 void WebPage::getRenderTreeExternalRepresentation(uint64_t callbackID)
1247 {
1248     String resultString = renderTreeExternalRepresentation();
1249     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1250 }
1251
1252 void WebPage::getSelectionOrContentsAsString(uint64_t callbackID)
1253 {
1254     String resultString = m_mainFrame->selectionAsString();
1255     if (resultString.isEmpty())
1256         resultString = m_mainFrame->contentsAsString();
1257     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1258 }
1259
1260 void WebPage::getSourceForFrame(uint64_t frameID, uint64_t callbackID)
1261 {
1262     String resultString;
1263     if (WebFrame* frame = WebProcess::shared().webFrame(frameID))
1264        resultString = frame->source();
1265
1266     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1267 }
1268
1269 void WebPage::getMainResourceDataOfFrame(uint64_t frameID, uint64_t callbackID)
1270 {
1271     CoreIPC::DataReference dataReference;
1272
1273     RefPtr<SharedBuffer> buffer;
1274     if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) {
1275         if (DocumentLoader* loader = frame->coreFrame()->loader()->documentLoader()) {
1276             if ((buffer = loader->mainResourceData()))
1277                 dataReference = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size());
1278         }
1279     }
1280
1281     send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
1282 }
1283
1284 void WebPage::getResourceDataFromFrame(uint64_t frameID, const String& resourceURL, uint64_t callbackID)
1285 {
1286     CoreIPC::DataReference dataReference;
1287
1288     RefPtr<SharedBuffer> buffer;
1289     if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) {
1290         if (DocumentLoader* loader = frame->coreFrame()->loader()->documentLoader()) {
1291             if (RefPtr<ArchiveResource> subresource = loader->subresource(KURL(KURL(), resourceURL))) {
1292                 if ((buffer = subresource->data()))
1293                     dataReference = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size());
1294             }
1295         }
1296     }
1297
1298     send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
1299 }
1300
1301 void WebPage::getWebArchiveOfFrame(uint64_t frameID, uint64_t callbackID)
1302 {
1303     CoreIPC::DataReference dataReference;
1304
1305 #if PLATFORM(MAC) || PLATFORM(WIN)
1306     RetainPtr<CFDataRef> data;
1307     if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) {
1308         if (RefPtr<LegacyWebArchive> archive = LegacyWebArchive::create(frame->coreFrame())) {
1309             if ((data = archive->rawDataRepresentation()))
1310                 dataReference = CoreIPC::DataReference(CFDataGetBytePtr(data.get()), CFDataGetLength(data.get()));
1311         }
1312     }
1313 #endif
1314
1315     send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
1316 }
1317
1318 void WebPage::forceRepaint(uint64_t callbackID)
1319 {
1320     m_drawingArea->forceRepaint();
1321     send(Messages::WebPageProxy::VoidCallback(callbackID));
1322 }
1323
1324 void WebPage::preferencesDidChange(const WebPreferencesStore& store)
1325 {
1326     WebPreferencesStore::removeTestRunnerOverrides();
1327     updatePreferences(store);
1328 }
1329
1330 void WebPage::updatePreferences(const WebPreferencesStore& store)
1331 {
1332     Settings* settings = m_page->settings();
1333
1334     m_tabToLinks = store.getBoolValueForKey(WebPreferencesKey::tabsToLinksKey());
1335
1336     // FIXME: This should be generated from macro expansion for all preferences,
1337     // but we currently don't match the naming of WebCore exactly so we are
1338     // handrolling the boolean and integer preferences until that is fixed.
1339
1340 #define INITIALIZE_SETTINGS(KeyUpper, KeyLower, TypeName, Type, DefaultValue) settings->set##KeyUpper(store.get##TypeName##ValueForKey(WebPreferencesKey::KeyLower##Key()));
1341
1342     FOR_EACH_WEBKIT_STRING_PREFERENCE(INITIALIZE_SETTINGS)
1343
1344 #undef INITIALIZE_SETTINGS
1345
1346     settings->setJavaScriptEnabled(store.getBoolValueForKey(WebPreferencesKey::javaScriptEnabledKey()));
1347     settings->setLoadsImagesAutomatically(store.getBoolValueForKey(WebPreferencesKey::loadsImagesAutomaticallyKey()));
1348     settings->setPluginsEnabled(store.getBoolValueForKey(WebPreferencesKey::pluginsEnabledKey()));
1349     settings->setJavaEnabled(store.getBoolValueForKey(WebPreferencesKey::javaEnabledKey()));
1350     settings->setOfflineWebApplicationCacheEnabled(store.getBoolValueForKey(WebPreferencesKey::offlineWebApplicationCacheEnabledKey()));
1351     settings->setLocalStorageEnabled(store.getBoolValueForKey(WebPreferencesKey::localStorageEnabledKey()));
1352     settings->setXSSAuditorEnabled(store.getBoolValueForKey(WebPreferencesKey::xssAuditorEnabledKey()));
1353     settings->setFrameFlatteningEnabled(store.getBoolValueForKey(WebPreferencesKey::frameFlatteningEnabledKey()));
1354     settings->setPrivateBrowsingEnabled(store.getBoolValueForKey(WebPreferencesKey::privateBrowsingEnabledKey()));
1355     settings->setDeveloperExtrasEnabled(store.getBoolValueForKey(WebPreferencesKey::developerExtrasEnabledKey()));
1356     settings->setTextAreasAreResizable(store.getBoolValueForKey(WebPreferencesKey::textAreasAreResizableKey()));
1357     settings->setNeedsSiteSpecificQuirks(store.getBoolValueForKey(WebPreferencesKey::needsSiteSpecificQuirksKey()));
1358     settings->setJavaScriptCanOpenWindowsAutomatically(store.getBoolValueForKey(WebPreferencesKey::javaScriptCanOpenWindowsAutomaticallyKey()));
1359     settings->setForceFTPDirectoryListings(store.getBoolValueForKey(WebPreferencesKey::forceFTPDirectoryListingsKey()));
1360     settings->setDNSPrefetchingEnabled(store.getBoolValueForKey(WebPreferencesKey::dnsPrefetchingEnabledKey()));
1361 #if ENABLE(WEB_ARCHIVE)
1362     settings->setWebArchiveDebugModeEnabled(store.getBoolValueForKey(WebPreferencesKey::webArchiveDebugModeEnabledKey()));
1363 #endif
1364     settings->setLocalFileContentSniffingEnabled(store.getBoolValueForKey(WebPreferencesKey::localFileContentSniffingEnabledKey()));
1365     settings->setUsesPageCache(store.getBoolValueForKey(WebPreferencesKey::usesPageCacheKey()));
1366     settings->setAuthorAndUserStylesEnabled(store.getBoolValueForKey(WebPreferencesKey::authorAndUserStylesEnabledKey()));
1367     settings->setPaginateDuringLayoutEnabled(store.getBoolValueForKey(WebPreferencesKey::paginateDuringLayoutEnabledKey()));
1368     settings->setDOMPasteAllowed(store.getBoolValueForKey(WebPreferencesKey::domPasteAllowedKey()));
1369     settings->setJavaScriptCanAccessClipboard(store.getBoolValueForKey(WebPreferencesKey::javaScriptCanAccessClipboardKey()));
1370     settings->setShouldPrintBackgrounds(store.getBoolValueForKey(WebPreferencesKey::shouldPrintBackgroundsKey()));
1371
1372     settings->setMinimumFontSize(store.getUInt32ValueForKey(WebPreferencesKey::minimumFontSizeKey()));
1373     settings->setMinimumLogicalFontSize(store.getUInt32ValueForKey(WebPreferencesKey::minimumLogicalFontSizeKey()));
1374     settings->setDefaultFontSize(store.getUInt32ValueForKey(WebPreferencesKey::defaultFontSizeKey()));
1375     settings->setDefaultFixedFontSize(store.getUInt32ValueForKey(WebPreferencesKey::defaultFixedFontSizeKey()));
1376
1377 #if PLATFORM(WIN)
1378     // Temporarily turn off accelerated compositing until we have a good solution for rendering it.
1379     settings->setAcceleratedCompositingEnabled(false);
1380     settings->setAcceleratedDrawingEnabled(false);
1381 #else
1382     settings->setAcceleratedCompositingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedCompositingEnabledKey()));
1383     settings->setAcceleratedDrawingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedDrawingEnabledKey()));
1384 #endif
1385     settings->setShowDebugBorders(store.getBoolValueForKey(WebPreferencesKey::compositingBordersVisibleKey()));
1386     settings->setShowRepaintCounter(store.getBoolValueForKey(WebPreferencesKey::compositingRepaintCountersVisibleKey()));
1387     settings->setWebGLEnabled(store.getBoolValueForKey(WebPreferencesKey::webGLEnabledKey()));
1388
1389 #if ENABLE(DATABASE)
1390     AbstractDatabase::setIsAvailable(store.getBoolValueForKey(WebPreferencesKey::databasesEnabledKey()));
1391 #endif
1392
1393     platformPreferencesDidChange(store);
1394 }
1395
1396 #if ENABLE(INSPECTOR)
1397 WebInspector* WebPage::inspector()
1398 {
1399     if (m_isClosed)
1400         return 0;
1401     if (!m_inspector)
1402         m_inspector = WebInspector::create(this);
1403     return m_inspector.get();
1404 }
1405 #endif
1406
1407 #if !PLATFORM(MAC)
1408 bool WebPage::handleEditingKeyboardEvent(KeyboardEvent* evt)
1409 {
1410     Node* node = evt->target()->toNode();
1411     ASSERT(node);
1412     Frame* frame = node->document()->frame();
1413     ASSERT(frame);
1414
1415     const PlatformKeyboardEvent* keyEvent = evt->keyEvent();
1416     if (!keyEvent)
1417         return false;
1418
1419     Editor::Command command = frame->editor()->command(interpretKeyEvent(evt));
1420
1421     if (keyEvent->type() == PlatformKeyboardEvent::RawKeyDown) {
1422         // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated,
1423         // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated
1424         // (e.g. Tab that inserts a Tab character, or Enter).
1425         return !command.isTextInsertion() && command.execute(evt);
1426     }
1427
1428     if (command.execute(evt))
1429         return true;
1430
1431     // Don't insert null or control characters as they can result in unexpected behaviour
1432     if (evt->charCode() < ' ')
1433         return false;
1434
1435     return frame->editor()->insertText(evt->keyEvent()->text(), evt);
1436 }
1437 #endif
1438
1439 #if PLATFORM(WIN)
1440 void WebPage::performDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, const WebCore::DragDataMap& dataMap, uint32_t flags)
1441 {
1442     if (!m_page) {
1443         send(Messages::WebPageProxy::DidPerformDragControllerAction(DragOperationNone));
1444         return;
1445     }
1446
1447     DragData dragData(dataMap, clientPosition, globalPosition, static_cast<DragOperation>(draggingSourceOperationMask), static_cast<DragApplicationFlags>(flags));
1448     switch (action) {
1449     case DragControllerActionEntered:
1450         send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragEntered(&dragData)));
1451         break;
1452
1453     case DragControllerActionUpdated:
1454         send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragUpdated(&dragData)));
1455         break;
1456         
1457     case DragControllerActionExited:
1458         m_page->dragController()->dragExited(&dragData);
1459         break;
1460         
1461     case DragControllerActionPerformDrag:
1462         m_page->dragController()->performDrag(&dragData);
1463         break;
1464         
1465     default:
1466         ASSERT_NOT_REACHED();
1467     }
1468 }
1469 #else
1470 void WebPage::performDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, const String& dragStorageName, uint32_t flags)
1471 {
1472     if (!m_page) {
1473         send(Messages::WebPageProxy::DidPerformDragControllerAction(DragOperationNone));
1474         return;
1475     }
1476
1477     DragData dragData(dragStorageName, clientPosition, globalPosition, static_cast<DragOperation>(draggingSourceOperationMask), static_cast<DragApplicationFlags>(flags));
1478     switch (action) {
1479     case DragControllerActionEntered:
1480         send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragEntered(&dragData)));
1481         break;
1482
1483     case DragControllerActionUpdated:
1484         send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragUpdated(&dragData)));
1485         break;
1486         
1487     case DragControllerActionExited:
1488         m_page->dragController()->dragExited(&dragData);
1489         break;
1490         
1491     case DragControllerActionPerformDrag:
1492         m_page->dragController()->performDrag(&dragData);
1493         break;
1494         
1495     default:
1496         ASSERT_NOT_REACHED();
1497     }
1498 }
1499 #endif
1500
1501 void WebPage::dragEnded(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t operation)
1502 {
1503     IntPoint adjustedClientPosition(clientPosition.x() + m_page->dragController()->dragOffset().x(), clientPosition.y() + m_page->dragController()->dragOffset().y());
1504     IntPoint adjustedGlobalPosition(globalPosition.x() + m_page->dragController()->dragOffset().x(), globalPosition.y() + m_page->dragController()->dragOffset().y());
1505     
1506     m_page->dragController()->dragEnded();
1507     FrameView* view = m_page->mainFrame()->view();
1508     if (!view)
1509         return;
1510     // FIXME: These are fake modifier keys here, but they should be real ones instead.
1511     PlatformMouseEvent event(adjustedClientPosition, adjustedGlobalPosition, LeftButton, MouseEventMoved, 0, false, false, false, false, currentTime());
1512     m_page->mainFrame()->eventHandler()->dragSourceEndedAt(event, (DragOperation)operation);
1513 }
1514
1515 WebEditCommand* WebPage::webEditCommand(uint64_t commandID)
1516 {
1517     return m_editCommandMap.get(commandID).get();
1518 }
1519
1520 void WebPage::addWebEditCommand(uint64_t commandID, WebEditCommand* command)
1521 {
1522     m_editCommandMap.set(commandID, command);
1523 }
1524
1525 void WebPage::removeWebEditCommand(uint64_t commandID)
1526 {
1527     m_editCommandMap.remove(commandID);
1528 }
1529
1530 void WebPage::unapplyEditCommand(uint64_t commandID)
1531 {
1532     WebEditCommand* command = webEditCommand(commandID);
1533     if (!command)
1534         return;
1535
1536     command->command()->unapply();
1537 }
1538
1539 void WebPage::reapplyEditCommand(uint64_t commandID)
1540 {
1541     WebEditCommand* command = webEditCommand(commandID);
1542     if (!command)
1543         return;
1544
1545     m_isInRedo = true;
1546     command->command()->reapply();
1547     m_isInRedo = false;
1548 }
1549
1550 void WebPage::didRemoveEditCommand(uint64_t commandID)
1551 {
1552     removeWebEditCommand(commandID);
1553 }
1554
1555 void WebPage::setActivePopupMenu(WebPopupMenu* menu)
1556 {
1557     m_activePopupMenu = menu;
1558 }
1559
1560 void WebPage::setActiveOpenPanelResultListener(PassRefPtr<WebOpenPanelResultListener> openPanelResultListener)
1561 {
1562     m_activeOpenPanelResultListener = openPanelResultListener;
1563 }
1564
1565 bool WebPage::findStringFromInjectedBundle(const String& target, FindOptions options)
1566 {
1567     return m_page->findString(target, options);
1568 }
1569
1570 void WebPage::findString(const String& string, uint32_t options, uint32_t maxMatchCount)
1571 {
1572     m_findController.findString(string, static_cast<FindOptions>(options), maxMatchCount);
1573 }
1574
1575 void WebPage::hideFindUI()
1576 {
1577     m_findController.hideFindUI();
1578 }
1579
1580 void WebPage::countStringMatches(const String& string, uint32_t options, uint32_t maxMatchCount)
1581 {
1582     m_findController.countStringMatches(string, static_cast<FindOptions>(options), maxMatchCount);
1583 }
1584
1585 void WebPage::didChangeSelectedIndexForActivePopupMenu(int32_t newIndex)
1586 {
1587     if (!m_activePopupMenu)
1588         return;
1589
1590     m_activePopupMenu->didChangeSelectedIndex(newIndex);
1591     m_activePopupMenu = 0;
1592 }
1593
1594 void WebPage::didChooseFilesForOpenPanel(const Vector<String>& files)
1595 {
1596     if (!m_activeOpenPanelResultListener)
1597         return;
1598
1599     m_activeOpenPanelResultListener->didChooseFiles(files);
1600     m_activeOpenPanelResultListener = 0;
1601 }
1602
1603 void WebPage::didCancelForOpenPanel()
1604 {
1605     m_activeOpenPanelResultListener = 0;
1606 }
1607
1608 #if ENABLE(WEB_PROCESS_SANDBOX)
1609 void WebPage::extendSandboxForFileFromOpenPanel(const SandboxExtension::Handle& handle)
1610 {
1611     SandboxExtension::create(handle)->consumePermanently();
1612 }
1613 #endif
1614
1615 void WebPage::didReceiveGeolocationPermissionDecision(uint64_t geolocationID, bool allowed)
1616 {
1617     m_geolocationPermissionRequestManager.didReceiveGeolocationPermissionDecision(geolocationID, allowed);
1618 }
1619
1620 void WebPage::advanceToNextMisspelling(bool startBeforeSelection)
1621 {
1622     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1623     frame->editor()->advanceToNextMisspelling(startBeforeSelection);
1624 }
1625
1626 void WebPage::changeSpellingToWord(const String& word)
1627 {
1628     replaceSelectionWithText(m_page->focusController()->focusedOrMainFrame(), word);
1629 }
1630
1631 void WebPage::unmarkAllMisspellings()
1632 {
1633     for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
1634         if (Document* document = frame->document())
1635             document->markers()->removeMarkers(DocumentMarker::Spelling);
1636     }
1637 }
1638
1639 void WebPage::unmarkAllBadGrammar()
1640 {
1641     for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
1642         if (Document* document = frame->document())
1643             document->markers()->removeMarkers(DocumentMarker::Grammar);
1644     }
1645 }
1646
1647 #if PLATFORM(MAC)
1648 void WebPage::uppercaseWord()
1649 {
1650     m_page->focusController()->focusedOrMainFrame()->editor()->uppercaseWord();
1651 }
1652
1653 void WebPage::lowercaseWord()
1654 {
1655     m_page->focusController()->focusedOrMainFrame()->editor()->lowercaseWord();
1656 }
1657
1658 void WebPage::capitalizeWord()
1659 {
1660     m_page->focusController()->focusedOrMainFrame()->editor()->capitalizeWord();
1661 }
1662 #endif
1663     
1664 void WebPage::setTextForActivePopupMenu(int32_t index)
1665 {
1666     if (!m_activePopupMenu)
1667         return;
1668
1669     m_activePopupMenu->setTextForIndex(index);
1670 }
1671
1672 void WebPage::didSelectItemFromActiveContextMenu(const WebContextMenuItemData& item)
1673 {
1674     ASSERT(m_contextMenu);
1675     m_contextMenu->itemSelected(item);
1676     m_contextMenu = 0;
1677 }
1678
1679 void WebPage::replaceSelectionWithText(Frame* frame, const String& text)
1680 {
1681     if (frame->selection()->isNone())
1682         return;
1683
1684     RefPtr<DocumentFragment> textFragment = createFragmentFromText(frame->selection()->toNormalizedRange().get(), text);
1685     applyCommand(ReplaceSelectionCommand::create(frame->document(), textFragment.release(), ReplaceSelectionCommand::SelectReplacement | ReplaceSelectionCommand::MatchStyle | ReplaceSelectionCommand::PreventNesting));
1686     frame->selection()->revealSelection(ScrollAlignment::alignToEdgeIfNeeded);
1687 }
1688
1689 bool WebPage::mainFrameHasCustomRepresentation() const
1690 {
1691     return static_cast<WebFrameLoaderClient*>(mainFrame()->coreFrame()->loader()->client())->frameHasCustomRepresentation();
1692 }
1693
1694 void WebPage::didChangeScrollOffsetForMainFrame()
1695 {
1696     Frame* frame = m_page->mainFrame();
1697     IntPoint scrollPosition = frame->view()->scrollPosition();
1698     IntPoint maximumScrollPosition = frame->view()->maximumScrollPosition();
1699
1700     bool isPinnedToLeftSide = (scrollPosition.x() <= 0);
1701     bool isPinnedToRightSide = (scrollPosition.x() >= maximumScrollPosition.x());
1702
1703     if (isPinnedToLeftSide != m_cachedMainFrameIsPinnedToLeftSide || isPinnedToRightSide != m_cachedMainFrameIsPinnedToRightSide) {
1704         send(Messages::WebPageProxy::DidChangeScrollOffsetPinningForMainFrame(isPinnedToLeftSide, isPinnedToRightSide));
1705         
1706         m_cachedMainFrameIsPinnedToLeftSide = isPinnedToLeftSide;
1707         m_cachedMainFrameIsPinnedToRightSide = isPinnedToRightSide;
1708     }
1709 }
1710
1711 #if PLATFORM(MAC)
1712
1713 void WebPage::addPluginView(PluginView* pluginView)
1714 {
1715     ASSERT(!m_pluginViews.contains(pluginView));
1716
1717     m_pluginViews.add(pluginView);
1718 }
1719
1720 void WebPage::removePluginView(PluginView* pluginView)
1721 {
1722     ASSERT(m_pluginViews.contains(pluginView));
1723
1724     m_pluginViews.remove(pluginView);
1725 }
1726
1727 void WebPage::setWindowIsVisible(bool windowIsVisible)
1728 {
1729     m_windowIsVisible = windowIsVisible;
1730
1731     // Tell all our plug-in views that the window visibility changed.
1732     for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
1733         (*it)->setWindowIsVisible(windowIsVisible);
1734 }
1735
1736 void WebPage::windowAndViewFramesChanged(const WebCore::IntRect& windowFrameInScreenCoordinates, const WebCore::IntRect& viewFrameInWindowCoordinates, const WebCore::IntPoint& accessibilityViewCoordinates)
1737 {
1738     m_windowFrameInScreenCoordinates = windowFrameInScreenCoordinates;
1739     m_viewFrameInWindowCoordinates = viewFrameInWindowCoordinates;
1740     m_accessibilityPosition = accessibilityViewCoordinates;
1741     
1742     // Tell all our plug-in views that the window and view frames have changed.
1743     for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
1744         (*it)->windowAndViewFramesChanged(windowFrameInScreenCoordinates, viewFrameInWindowCoordinates);
1745 }
1746
1747 bool WebPage::windowIsFocused() const
1748 {
1749     return m_page->focusController()->isActive();
1750 }
1751
1752 #endif
1753
1754 void WebPage::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
1755 {
1756     if (messageID.is<CoreIPC::MessageClassDrawingAreaLegacy>()) {
1757         if (m_drawingArea)
1758             m_drawingArea->didReceiveMessage(connection, messageID, arguments);
1759         return;
1760     }
1761
1762 #if PLATFORM(MAC) || PLATFORM(WIN)
1763     if (messageID.is<CoreIPC::MessageClassDrawingArea>()) {
1764         if (m_drawingArea)
1765             m_drawingArea->didReceiveDrawingAreaMessage(connection, messageID, arguments);
1766         return;
1767     }
1768 #endif
1769     
1770 #if ENABLE(INSPECTOR)
1771     if (messageID.is<CoreIPC::MessageClassWebInspector>()) {
1772         if (WebInspector* inspector = this->inspector())
1773             inspector->didReceiveWebInspectorMessage(connection, messageID, arguments);
1774         return;
1775     }
1776 #endif
1777
1778     didReceiveWebPageMessage(connection, messageID, arguments);
1779 }
1780
1781 CoreIPC::SyncReplyMode WebPage::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments, CoreIPC::ArgumentEncoder* reply)
1782 {   
1783     return didReceiveSyncWebPageMessage(connection, messageID, arguments, reply);
1784 }
1785     
1786 InjectedBundleBackForwardList* WebPage::backForwardList()
1787 {
1788     if (!m_backForwardList)
1789         m_backForwardList = InjectedBundleBackForwardList::create(this);
1790     return m_backForwardList.get();
1791 }
1792
1793 #if PLATFORM(QT)
1794 void WebPage::findZoomableAreaForPoint(const WebCore::IntPoint& point)
1795 {
1796     const int minimumZoomTargetWidth = 100;
1797
1798     Frame* mainframe = m_mainFrame->coreFrame();
1799     HitTestResult result = mainframe->eventHandler()->hitTestResultAtPoint(mainframe->view()->windowToContents(point), /*allowShadowContent*/ false, /*ignoreClipping*/ true);
1800
1801     Node* node = result.innerNode();
1802     while (node && node->getRect().width() < minimumZoomTargetWidth)
1803         node = node->parentNode();
1804
1805     IntRect zoomableArea;
1806     if (node)
1807         zoomableArea = node->getRect();
1808     send(Messages::WebPageProxy::DidFindZoomableArea(zoomableArea));
1809 }
1810 #endif
1811
1812 WebPage::SandboxExtensionTracker::~SandboxExtensionTracker()
1813 {
1814     invalidate();
1815 }
1816
1817 void WebPage::SandboxExtensionTracker::invalidate()
1818 {
1819     if (m_pendingProvisionalSandboxExtension) {
1820         m_pendingProvisionalSandboxExtension->invalidate();
1821         m_pendingProvisionalSandboxExtension = 0;
1822     }
1823
1824     if (m_provisionalSandboxExtension) {
1825         m_provisionalSandboxExtension->invalidate();
1826         m_provisionalSandboxExtension = 0;
1827     }
1828
1829     if (m_committedSandboxExtension) {
1830         m_committedSandboxExtension->invalidate();
1831         m_committedSandboxExtension = 0;
1832     }
1833 }
1834
1835 void WebPage::SandboxExtensionTracker::beginLoad(WebFrame* frame, const SandboxExtension::Handle& handle)
1836 {
1837     ASSERT(frame->isMainFrame());
1838
1839     // If we get two beginLoad calls in succession, without a provisional load starting, then
1840     // m_pendingProvisionalSandboxExtension will be non-null. Invalidate and null out the extension if that is the case.
1841     if (m_pendingProvisionalSandboxExtension) {
1842         m_pendingProvisionalSandboxExtension->invalidate();
1843         m_pendingProvisionalSandboxExtension = nullptr;
1844     }
1845         
1846     m_pendingProvisionalSandboxExtension = SandboxExtension::create(handle);
1847 }
1848
1849 static bool shouldReuseCommittedSandboxExtension(WebFrame* frame)
1850 {
1851     ASSERT(frame->isMainFrame());
1852
1853     FrameLoader* frameLoader = frame->coreFrame()->loader();
1854     FrameLoadType frameLoadType = frameLoader->loadType();
1855
1856     // If the page is being reloaded, it should reuse whatever extension is committed.
1857     if (frameLoadType == FrameLoadTypeReload || frameLoadType == FrameLoadTypeReloadFromOrigin)
1858         return true;
1859
1860     DocumentLoader* documentLoader = frameLoader->documentLoader();
1861     DocumentLoader* provisionalDocumentLoader = frameLoader->provisionalDocumentLoader();
1862     if (!documentLoader || !provisionalDocumentLoader)
1863         return false;
1864
1865     if (documentLoader->url().isLocalFile() && provisionalDocumentLoader->url().isLocalFile() 
1866         && provisionalDocumentLoader->triggeringAction().type() == NavigationTypeLinkClicked)
1867         return true;
1868
1869     return false;
1870 }
1871
1872 void WebPage::SandboxExtensionTracker::didStartProvisionalLoad(WebFrame* frame)
1873 {
1874     if (!frame->isMainFrame())
1875         return;
1876
1877     if (shouldReuseCommittedSandboxExtension(frame)) {
1878         m_pendingProvisionalSandboxExtension = m_committedSandboxExtension.release();
1879         ASSERT(!m_committedSandboxExtension);
1880     }
1881
1882     ASSERT(!m_provisionalSandboxExtension);
1883
1884     m_provisionalSandboxExtension = m_pendingProvisionalSandboxExtension.release();
1885     if (!m_provisionalSandboxExtension)
1886         return;
1887
1888     m_provisionalSandboxExtension->consume();
1889 }
1890
1891 void WebPage::SandboxExtensionTracker::didCommitProvisionalLoad(WebFrame* frame)
1892 {
1893     if (!frame->isMainFrame())
1894         return;
1895     
1896     ASSERT(!m_pendingProvisionalSandboxExtension);
1897
1898     // The provisional load has been committed. Invalidate the currently committed sandbox
1899     // extension and make the provisional sandbox extension the committed sandbox extension.
1900     if (m_committedSandboxExtension)
1901         m_committedSandboxExtension->invalidate();
1902
1903     m_committedSandboxExtension = m_provisionalSandboxExtension.release();
1904 }
1905
1906 void WebPage::SandboxExtensionTracker::didFailProvisionalLoad(WebFrame* frame)
1907 {
1908     if (!frame->isMainFrame())
1909         return;
1910
1911     ASSERT(!m_pendingProvisionalSandboxExtension);
1912     if (!m_provisionalSandboxExtension)
1913         return;
1914
1915     m_provisionalSandboxExtension->invalidate();
1916     m_provisionalSandboxExtension = nullptr;
1917 }
1918
1919 bool WebPage::hasLocalDataForURL(const KURL& url)
1920 {
1921     if (url.isLocalFile())
1922         return true;
1923
1924     FrameLoader* frameLoader = m_page->mainFrame()->loader();
1925     DocumentLoader* documentLoader = frameLoader ? frameLoader->documentLoader() : 0;
1926     if (documentLoader && documentLoader->subresource(url))
1927         return true;
1928
1929     return platformHasLocalDataForURL(url);
1930 }
1931
1932 void WebPage::setCustomTextEncodingName(const String& encoding)
1933 {
1934     m_page->mainFrame()->loader()->reloadWithOverrideEncoding(encoding);
1935 }
1936
1937 void WebPage::didRemoveBackForwardItem(uint64_t itemID)
1938 {
1939     WebBackForwardListProxy::removeItem(itemID);
1940 }
1941
1942 #if PLATFORM(MAC)
1943
1944 bool WebPage::isSpeaking()
1945 {
1946     bool result;
1947     return sendSync(Messages::WebPageProxy::GetIsSpeaking(), Messages::WebPageProxy::GetIsSpeaking::Reply(result)) && result;
1948 }
1949
1950 void WebPage::speak(const String& string)
1951 {
1952     send(Messages::WebPageProxy::Speak(string));
1953 }
1954
1955 void WebPage::stopSpeaking()
1956 {
1957     send(Messages::WebPageProxy::StopSpeaking());
1958 }
1959
1960 #endif
1961
1962 void WebPage::beginPrinting(uint64_t frameID, const PrintInfo& printInfo)
1963 {
1964     WebFrame* frame = WebProcess::shared().webFrame(frameID);
1965     if (!frame)
1966         return;
1967
1968     Frame* coreFrame = frame->coreFrame();
1969     if (!coreFrame)
1970         return;
1971
1972     if (!m_printContext)
1973         m_printContext = adoptPtr(new PrintContext(coreFrame));
1974
1975     m_printContext->begin(printInfo.availablePaperWidth, printInfo.availablePaperHeight);
1976
1977     float fullPageHeight;
1978     m_printContext->computePageRects(FloatRect(0, 0, printInfo.availablePaperWidth, printInfo.availablePaperHeight), 0, 0, printInfo.pageSetupScaleFactor, fullPageHeight, true);
1979 }
1980
1981 void WebPage::endPrinting()
1982 {
1983     m_printContext = nullptr;
1984 }
1985
1986 void WebPage::computePagesForPrinting(uint64_t frameID, const PrintInfo& printInfo, uint64_t callbackID)
1987 {
1988     Vector<IntRect> resultPageRects;
1989     double resultTotalScaleFactorForPrinting = 1;
1990
1991     beginPrinting(frameID, printInfo);
1992
1993     if (m_printContext) {
1994         resultPageRects = m_printContext->pageRects();
1995         resultTotalScaleFactorForPrinting = m_printContext->computeAutomaticScaleFactor(FloatSize(printInfo.availablePaperWidth, printInfo.availablePaperHeight)) * printInfo.pageSetupScaleFactor;
1996     }
1997
1998     // If we're asked to print, we should actually print at least a blank page.
1999     if (resultPageRects.isEmpty())
2000         resultPageRects.append(IntRect(0, 0, 1, 1));
2001
2002     send(Messages::WebPageProxy::ComputedPagesCallback(resultPageRects, resultTotalScaleFactorForPrinting, callbackID));
2003 }
2004
2005 #if PLATFORM(MAC)
2006 // FIXME: Find a better place for Mac specific code.
2007 void WebPage::drawRectToPDF(uint64_t frameID, const WebCore::IntRect& rect, uint64_t callbackID)
2008 {
2009     WebFrame* frame = WebProcess::shared().webFrame(frameID);
2010     Frame* coreFrame = frame ? frame->coreFrame() : 0;
2011
2012     RetainPtr<CFMutableDataRef> pdfPageData(AdoptCF, CFDataCreateMutable(0, 0));
2013
2014     if (coreFrame) {
2015         ASSERT(coreFrame->document()->printing());
2016
2017         // FIXME: Use CGDataConsumerCreate with callbacks to avoid copying the data.
2018         RetainPtr<CGDataConsumerRef> pdfDataConsumer(AdoptCF, CGDataConsumerCreateWithCFData(pdfPageData.get()));
2019
2020         CGRect mediaBox = CGRectMake(0, 0, rect.width(), rect.height());
2021         RetainPtr<CGContextRef> context(AdoptCF, CGPDFContextCreate(pdfDataConsumer.get(), &mediaBox, 0));
2022         RetainPtr<CFDictionaryRef> pageInfo(AdoptCF, CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
2023         CGPDFContextBeginPage(context.get(), pageInfo.get());
2024
2025         GraphicsContext ctx(context.get());
2026         ctx.scale(FloatSize(1, -1));
2027         ctx.translate(0, -rect.height());
2028         m_printContext->spoolRect(ctx, rect);
2029
2030         CGPDFContextEndPage(context.get());
2031         CGPDFContextClose(context.get());
2032     }
2033
2034     send(Messages::WebPageProxy::DataCallback(CoreIPC::DataReference(CFDataGetBytePtr(pdfPageData.get()), CFDataGetLength(pdfPageData.get())), callbackID));
2035 }
2036
2037 void WebPage::drawPagesToPDF(uint64_t frameID, uint32_t first, uint32_t count, uint64_t callbackID)
2038 {
2039     WebFrame* frame = WebProcess::shared().webFrame(frameID);
2040     Frame* coreFrame = frame ? frame->coreFrame() : 0;
2041
2042     RetainPtr<CFMutableDataRef> pdfPageData(AdoptCF, CFDataCreateMutable(0, 0));
2043
2044     if (coreFrame) {
2045         ASSERT(coreFrame->document()->printing());
2046
2047         // FIXME: Use CGDataConsumerCreate with callbacks to avoid copying the data.
2048         RetainPtr<CGDataConsumerRef> pdfDataConsumer(AdoptCF, CGDataConsumerCreateWithCFData(pdfPageData.get()));
2049
2050         CGRect mediaBox = m_printContext->pageCount() ? m_printContext->pageRect(0) : CGRectMake(0, 0, 1, 1);
2051         RetainPtr<CGContextRef> context(AdoptCF, CGPDFContextCreate(pdfDataConsumer.get(), &mediaBox, 0));
2052         for (uint32_t page = first; page < first + count; ++page) {
2053             if (page >= m_printContext->pageCount())
2054                 break;
2055
2056             RetainPtr<CFDictionaryRef> pageInfo(AdoptCF, CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
2057             CGPDFContextBeginPage(context.get(), pageInfo.get());
2058
2059             GraphicsContext ctx(context.get());
2060             ctx.scale(FloatSize(1, -1));
2061             ctx.translate(0, -m_printContext->pageRect(page).height());
2062             m_printContext->spoolPage(ctx, page, m_printContext->pageRect(page).width());
2063
2064             CGPDFContextEndPage(context.get());
2065         }
2066         CGPDFContextClose(context.get());
2067     }
2068
2069     send(Messages::WebPageProxy::DataCallback(CoreIPC::DataReference(CFDataGetBytePtr(pdfPageData.get()), CFDataGetLength(pdfPageData.get())), callbackID));
2070 }
2071 #endif
2072
2073 void WebPage::runModal()
2074 {
2075     if (m_isClosed)
2076         return;
2077     if (m_isRunningModal)
2078         return;
2079
2080     m_isRunningModal = true;
2081     send(Messages::WebPageProxy::RunModal());
2082     RunLoop::run();
2083     ASSERT(!m_isRunningModal);
2084 }
2085
2086 void WebPage::setMemoryCacheMessagesEnabled(bool memoryCacheMessagesEnabled)
2087 {
2088     m_page->setMemoryCacheClientCallsEnabled(memoryCacheMessagesEnabled);
2089 }
2090
2091 } // namespace WebKit