Removing line in computeViewportAttributes that enforces a minimum scale factor to...
[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 "LayerTreeHost.h"
36 #include "MessageID.h"
37 #include "NetscapePlugin.h"
38 #include "NotificationPermissionRequestManager.h"
39 #include "PageOverlay.h"
40 #include "PluginProxy.h"
41 #include "PluginView.h"
42 #include "PrintInfo.h"
43 #include "SessionState.h"
44 #include "ShareableBitmap.h"
45 #include "WebAlternativeTextClient.h"
46 #include "WebBackForwardList.h"
47 #include "WebBackForwardListItem.h"
48 #include "WebBackForwardListProxy.h"
49 #include "WebChromeClient.h"
50 #include "WebContextMenu.h"
51 #include "WebContextMenuClient.h"
52 #include "WebContextMessages.h"
53 #include "WebCoreArgumentCoders.h"
54 #include "WebDragClient.h"
55 #include "WebEditorClient.h"
56 #include "WebEvent.h"
57 #include "WebEventConversion.h"
58 #include "WebFrame.h"
59 #include "WebFullScreenManager.h"
60 #include "WebGeolocationClient.h"
61 #include "WebGeometry.h"
62 #include "WebImage.h"
63 #include "WebInspector.h"
64 #include "WebInspectorClient.h"
65 #include "WebNotificationClient.h"
66 #include "WebOpenPanelResultListener.h"
67 #include "WebPageCreationParameters.h"
68 #include "WebPageGroupProxy.h"
69 #include "WebPageProxyMessages.h"
70 #include "WebPopupMenu.h"
71 #include "WebPreferencesStore.h"
72 #include "WebProcess.h"
73 #include "WebProcessProxyMessages.h"
74 #include <JavaScriptCore/APICast.h>
75 #include <WebCore/AbstractDatabase.h>
76 #include <WebCore/ArchiveResource.h>
77 #include <WebCore/Chrome.h>
78 #include <WebCore/ContextMenuController.h>
79 #include <WebCore/DocumentFragment.h>
80 #include <WebCore/DocumentLoader.h>
81 #include <WebCore/DocumentMarkerController.h>
82 #include <WebCore/DragController.h>
83 #include <WebCore/DragData.h>
84 #include <WebCore/DragSession.h>
85 #include <WebCore/EventHandler.h>
86 #include <WebCore/FocusController.h>
87 #include <WebCore/FormState.h>
88 #include <WebCore/Frame.h>
89 #include <WebCore/FrameLoadRequest.h>
90 #include <WebCore/FrameLoaderTypes.h>
91 #include <WebCore/FrameView.h>
92 #include <WebCore/HTMLFormElement.h>
93 #include <WebCore/HTMLInputElement.h>
94 #include <WebCore/HistoryItem.h>
95 #include <WebCore/KeyboardEvent.h>
96 #include <WebCore/MouseEvent.h>
97 #include <WebCore/Page.h>
98 #include <WebCore/PlatformKeyboardEvent.h>
99 #include <WebCore/PluginDocument.h>
100 #include <WebCore/PrintContext.h>
101 #include <WebCore/RenderArena.h>
102 #include <WebCore/RenderLayer.h>
103 #include <WebCore/RenderTreeAsText.h>
104 #include <WebCore/RenderView.h>
105 #include <WebCore/ResourceRequest.h>
106 #include <WebCore/RunLoop.h>
107 #include <WebCore/SchemeRegistry.h>
108 #include <WebCore/ScriptValue.h>
109 #include <WebCore/SerializedScriptValue.h>
110 #include <WebCore/Settings.h>
111 #include <WebCore/SharedBuffer.h>
112 #include <WebCore/SubstituteData.h>
113 #include <WebCore/TextIterator.h>
114 #include <WebCore/markup.h>
115 #include <runtime/JSLock.h>
116 #include <runtime/JSValue.h>
117
118 #include <WebCore/Range.h>
119 #include <WebCore/VisiblePosition.h>
120
121 #if ENABLE(PLUGIN_PROCESS)
122 #if PLATFORM(MAC)
123 #include "MachPort.h"
124 #endif
125 #endif
126
127 #if PLATFORM(MAC)
128 #include "BuiltInPDFView.h"
129 #endif
130
131 #if PLATFORM(QT)
132 #if ENABLE(DEVICE_ORIENTATION)
133 #include "DeviceMotionClientQt.h"
134 #include "DeviceOrientationClientQt.h"
135 #endif
136 #include "HitTestResult.h"
137 #include <QMimeData>
138 #endif
139
140 #if PLATFORM(GTK)
141 #include <gtk/gtk.h>
142 #include "DataObjectGtk.h"
143 #include "WebPrintOperationGtk.h"
144 #endif
145
146 #ifndef NDEBUG
147 #include <wtf/RefCountedLeakCounter.h>
148 #endif
149
150 using namespace JSC;
151 using namespace WebCore;
152 using namespace std;
153
154 namespace WebKit {
155
156 class SendStopResponsivenessTimer {
157 public:
158     SendStopResponsivenessTimer(WebPage* page)
159         : m_page(page)
160     {
161     }
162     
163     ~SendStopResponsivenessTimer()
164     {
165         m_page->send(Messages::WebPageProxy::StopResponsivenessTimer());
166     }
167
168 private:
169     WebPage* m_page;
170 };
171
172 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, webPageCounter, ("WebPage"));
173
174 PassRefPtr<WebPage> WebPage::create(uint64_t pageID, const WebPageCreationParameters& parameters)
175 {
176     RefPtr<WebPage> page = adoptRef(new WebPage(pageID, parameters));
177
178     if (page->pageGroup()->isVisibleToInjectedBundle() && WebProcess::shared().injectedBundle())
179         WebProcess::shared().injectedBundle()->didCreatePage(page.get());
180
181     return page.release();
182 }
183
184 WebPage::WebPage(uint64_t pageID, const WebPageCreationParameters& parameters)
185     : m_viewSize(parameters.viewSize)
186     , m_useFixedLayout(false)
187     , m_drawsBackground(true)
188     , m_drawsTransparentBackground(false)
189     , m_isInRedo(false)
190     , m_isClosed(false)
191     , m_tabToLinks(false)
192 #if PLATFORM(MAC)
193     , m_windowIsVisible(false)
194     , m_isSmartInsertDeleteEnabled(parameters.isSmartInsertDeleteEnabled)
195     , m_layerHostingMode(LayerHostingModeDefault)
196     , m_keyboardEventBeingInterpreted(0)
197 #elif PLATFORM(WIN)
198     , m_nativeWindow(parameters.nativeWindow)
199 #elif PLATFORM(GTK)
200     , m_accessibilityObject(0)
201 #endif
202     , m_setCanStartMediaTimer(WebProcess::shared().runLoop(), this, &WebPage::setCanStartMediaTimerFired)
203     , m_findController(this)
204 #if ENABLE(TOUCH_EVENTS)
205 #if PLATFORM(QT)
206     , m_tapHighlightController(this)
207 #endif
208 #endif
209 #if ENABLE(GEOLOCATION)
210     , m_geolocationPermissionRequestManager(this)
211 #endif
212     , m_pageID(pageID)
213     , m_canRunBeforeUnloadConfirmPanel(parameters.canRunBeforeUnloadConfirmPanel)
214     , m_canRunModal(parameters.canRunModal)
215     , m_isRunningModal(false)
216     , m_cachedMainFrameIsPinnedToLeftSide(false)
217     , m_cachedMainFrameIsPinnedToRightSide(false)
218     , m_canShortCircuitHorizontalWheelEvents(false)
219     , m_numWheelEventHandlers(0)
220     , m_cachedPageCount(0)
221 #if ENABLE(CONTEXT_MENUS)
222     , m_isShowingContextMenu(false)
223 #endif
224     , m_willGoToBackForwardItemCallbackEnabled(true)
225 #if PLATFORM(WIN)
226     , m_gestureReachedScrollingLimit(false)
227 #endif
228 {
229     ASSERT(m_pageID);
230     // FIXME: This is a non-ideal location for this Setting and
231     // 4ms should be adopted project-wide now, https://bugs.webkit.org/show_bug.cgi?id=61214
232     Settings::setDefaultMinDOMTimerInterval(0.004);
233
234     Page::PageClients pageClients;
235     pageClients.chromeClient = new WebChromeClient(this);
236 #if ENABLE(CONTEXT_MENUS)
237     pageClients.contextMenuClient = new WebContextMenuClient(this);
238 #endif
239     pageClients.editorClient = new WebEditorClient(this);
240     pageClients.dragClient = new WebDragClient(this);
241     pageClients.backForwardClient = WebBackForwardListProxy::create(this);
242 #if ENABLE(INSPECTOR)
243     pageClients.inspectorClient = new WebInspectorClient(this);
244 #endif
245 #if USE(AUTOCORRECTION_PANEL)
246     pageClients.alternativeTextClient = new WebAlternativeTextClient(this);
247 #endif
248     
249     m_page = adoptPtr(new Page(pageClients));
250
251 #if ENABLE(GEOLOCATION)
252     WebCore::provideGeolocationTo(m_page.get(), new WebGeolocationClient(this));
253 #endif
254 #if ENABLE(DEVICE_ORIENTATION) && PLATFORM(QT)
255     WebCore::provideDeviceMotionTo(m_page.get(), new DeviceMotionClientQt);
256     WebCore::provideDeviceOrientationTo(m_page.get(), new DeviceOrientationClientQt);
257 #endif
258 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
259     WebCore::provideNotification(m_page.get(), new WebNotificationClient(this));
260 #endif
261
262     // Qt does not yet call setIsInWindow. Until it does, just leave
263     // this line out so plug-ins and video will work. Eventually all platforms
264     // should call setIsInWindow and this comment and #if should be removed,
265     // leaving behind the setCanStartMedia call.
266 #if !PLATFORM(QT)
267     m_page->setCanStartMedia(false);
268 #endif
269
270     updatePreferences(parameters.store);
271
272     m_pageGroup = WebProcess::shared().webPageGroup(parameters.pageGroupData);
273     m_page->setGroupName(m_pageGroup->identifier());
274
275     platformInitialize();
276
277     m_drawingArea = DrawingArea::create(this, parameters);
278     m_drawingArea->setPaintingEnabled(false);
279
280     m_mainFrame = WebFrame::createMainFrame(this);
281
282     setUseFixedLayout(parameters.useFixedLayout);
283
284     setDrawsBackground(parameters.drawsBackground);
285     setDrawsTransparentBackground(parameters.drawsTransparentBackground);
286
287     setPaginationMode(parameters.paginationMode);
288     setPaginationBehavesLikeColumns(parameters.paginationBehavesLikeColumns);
289     setPageLength(parameters.pageLength);
290     setGapBetweenPages(parameters.gapBetweenPages);
291
292     setMemoryCacheMessagesEnabled(parameters.areMemoryCacheClientCallsEnabled);
293
294     setActive(parameters.isActive);
295     setFocused(parameters.isFocused);
296     setIsInWindow(parameters.isInWindow);
297
298     m_userAgent = parameters.userAgent;
299
300     WebBackForwardListProxy::setHighestItemIDFromUIProcess(parameters.highestUsedBackForwardItemID);
301     
302     if (!parameters.sessionState.isEmpty())
303         restoreSession(parameters.sessionState);
304
305     m_drawingArea->setPaintingEnabled(true);
306     
307     setMediaVolume(parameters.mediaVolume);
308
309 #ifndef NDEBUG
310     webPageCounter.increment();
311 #endif
312 }
313
314 WebPage::~WebPage()
315 {
316     if (m_backForwardList)
317         m_backForwardList->detach();
318
319     ASSERT(!m_page);
320
321     m_sandboxExtensionTracker.invalidate();
322
323 #if PLATFORM(MAC)
324     ASSERT(m_pluginViews.isEmpty());
325 #endif
326
327 #ifndef NDEBUG
328     webPageCounter.decrement();
329 #endif
330 }
331
332 void WebPage::dummy(bool&)
333 {
334 }
335
336 CoreIPC::Connection* WebPage::connection() const
337 {
338     return WebProcess::shared().connection();
339 }
340
341 #if ENABLE(CONTEXT_MENUS)
342 void WebPage::initializeInjectedBundleContextMenuClient(WKBundlePageContextMenuClient* client)
343 {
344     m_contextMenuClient.initialize(client);
345 }
346 #endif
347
348 void WebPage::initializeInjectedBundleEditorClient(WKBundlePageEditorClient* client)
349 {
350     m_editorClient.initialize(client);
351 }
352
353 void WebPage::initializeInjectedBundleFormClient(WKBundlePageFormClient* client)
354 {
355     m_formClient.initialize(client);
356 }
357
358 void WebPage::initializeInjectedBundleLoaderClient(WKBundlePageLoaderClient* client)
359 {
360     m_loaderClient.initialize(client);
361 }
362
363 void WebPage::initializeInjectedBundlePolicyClient(WKBundlePagePolicyClient* client)
364 {
365     m_policyClient.initialize(client);
366 }
367
368 void WebPage::initializeInjectedBundleResourceLoadClient(WKBundlePageResourceLoadClient* client)
369 {
370     m_resourceLoadClient.initialize(client);
371 }
372
373 void WebPage::initializeInjectedBundleUIClient(WKBundlePageUIClient* client)
374 {
375     m_uiClient.initialize(client);
376 }
377
378 #if ENABLE(FULLSCREEN_API)
379 void WebPage::initializeInjectedBundleFullScreenClient(WKBundlePageFullScreenClient* client)
380 {
381     m_fullScreenClient.initialize(client);
382 }
383 #endif
384
385 PassRefPtr<Plugin> WebPage::createPlugin(WebFrame* frame, const Plugin::Parameters& parameters)
386 {
387     String pluginPath;
388
389     if (!WebProcess::shared().connection()->sendSync(
390             Messages::WebContext::GetPluginPath(parameters.mimeType, parameters.url.string()), 
391             Messages::WebContext::GetPluginPath::Reply(pluginPath), 0)) {
392         return 0;
393     }
394
395     if (pluginPath.isNull()) {
396 #if PLATFORM(MAC)
397         if (parameters.mimeType == "application/pdf"
398             || (parameters.mimeType.isEmpty() && parameters.url.path().lower().endsWith(".pdf")))
399             return BuiltInPDFView::create(frame);
400 #else
401         UNUSED_PARAM(frame);
402 #endif
403         return 0;
404     }
405
406 #if ENABLE(PLUGIN_PROCESS)
407     return PluginProxy::create(pluginPath);
408 #else
409     NetscapePlugin::setSetExceptionFunction(NPRuntimeObjectMap::setGlobalException);
410     return NetscapePlugin::create(NetscapePluginModule::getOrCreate(pluginPath));
411 #endif
412 }
413
414 EditorState WebPage::editorState() const
415 {
416     Frame* frame = m_page->focusController()->focusedOrMainFrame();
417     ASSERT(frame);
418
419     EditorState result;
420     result.selectionIsNone = frame->selection()->isNone();
421     result.selectionIsRange = frame->selection()->isRange();
422     result.isContentEditable = frame->selection()->isContentEditable();
423     result.isContentRichlyEditable = frame->selection()->isContentRichlyEditable();
424     result.isInPasswordField = frame->selection()->isInPasswordField();
425     result.hasComposition = frame->editor()->hasComposition();
426     result.shouldIgnoreCompositionSelectionChange = frame->editor()->ignoreCompositionSelectionChange();
427
428 #if PLATFORM(QT)
429     size_t location = 0;
430     size_t length = 0;
431
432     Element* selectionRoot = frame->selection()->rootEditableElement();
433     Element* scope = selectionRoot ? selectionRoot : frame->document()->documentElement();
434
435     if (!scope)
436         return result;
437
438     if (scope->hasTagName(HTMLNames::inputTag)) {
439         HTMLInputElement* input = static_cast<HTMLInputElement*>(scope);
440         if (input->isTelephoneField())
441             result.inputMethodHints |= Qt::ImhDialableCharactersOnly;
442         else if (input->isNumberField())
443             result.inputMethodHints |= Qt::ImhDigitsOnly;
444         else if (input->isEmailField()) {
445             result.inputMethodHints |= Qt::ImhEmailCharactersOnly;
446             result.inputMethodHints |= Qt::ImhNoAutoUppercase;
447         } else if (input->isURLField()) {
448             result.inputMethodHints |= Qt::ImhUrlCharactersOnly;
449             result.inputMethodHints |= Qt::ImhNoAutoUppercase;
450         } else if (input->isPasswordField()) {
451             // Set ImhHiddenText flag for password fields. The Qt platform
452             // is responsible for determining which widget will receive input
453             // method events for password fields.
454             result.inputMethodHints |= Qt::ImhHiddenText;
455             result.inputMethodHints |= Qt::ImhNoAutoUppercase;
456             result.inputMethodHints |= Qt::ImhNoPredictiveText;
457             result.inputMethodHints |= Qt::ImhSensitiveData;
458         }
459     }
460
461     if (selectionRoot)
462         result.editorRect = frame->view()->contentsToWindow(selectionRoot->getPixelSnappedRect());
463
464     RefPtr<Range> range;
465     if (result.hasComposition && (range = frame->editor()->compositionRange())) {
466         frame->editor()->getCompositionSelection(result.anchorPosition, result.cursorPosition);
467
468         result.compositionRect = frame->view()->contentsToWindow(range->boundingBox());
469     }
470
471     if (!result.hasComposition && !result.selectionIsNone && (range = frame->selection()->selection().firstRange())) {
472         TextIterator::getLocationAndLengthFromRange(scope, range.get(), location, length);
473         bool baseIsFirst = frame->selection()->selection().isBaseFirst();
474
475         result.cursorPosition = (baseIsFirst) ? location + length : location;
476         result.anchorPosition = (baseIsFirst) ? location : location + length;
477         result.selectedText = range->text();
478     }
479
480     if (range)
481         result.cursorRect = frame->view()->contentsToWindow(frame->editor()->firstRectForRange(range.get()));
482
483     // FIXME: We should only transfer innerText when it changes and do this on the UI side.
484     if (result.isContentEditable && !result.isInPasswordField) {
485         result.surroundingText = scope->innerText();
486         if (result.hasComposition) {
487             // The anchor is always the left position when they represent a composition.
488             result.surroundingText.remove(result.anchorPosition, result.cursorPosition - result.anchorPosition);
489         }
490     }
491 #endif
492
493     return result;
494 }
495
496 String WebPage::renderTreeExternalRepresentation() const
497 {
498     return externalRepresentation(m_mainFrame->coreFrame(), RenderAsTextBehaviorNormal);
499 }
500
501 uint64_t WebPage::renderTreeSize() const
502 {
503     if (!m_page)
504         return 0;
505
506     Frame* mainFrame = m_page->mainFrame();
507     if (!mainFrame)
508         return 0;
509
510     uint64_t size = 0;
511     for (Frame* coreFrame = mainFrame; coreFrame; coreFrame = coreFrame->tree()->traverseNext())
512         size += coreFrame->document()->renderArena()->totalRenderArenaSize();
513
514     return size;
515 }
516
517 void WebPage::setPaintedObjectsCounterThreshold(uint64_t threshold)
518 {
519     if (!m_page)
520         return;
521     m_page->setRelevantRepaintedObjectsCounterThreshold(threshold);
522 }
523
524 void WebPage::setTracksRepaints(bool trackRepaints)
525 {
526     if (FrameView* view = mainFrameView())
527         view->setTracksRepaints(trackRepaints);
528 }
529
530 bool WebPage::isTrackingRepaints() const
531 {
532     if (FrameView* view = mainFrameView())
533         return view->isTrackingRepaints();
534
535     return false;
536 }
537
538 void WebPage::resetTrackedRepaints()
539 {
540     if (FrameView* view = mainFrameView())
541         view->resetTrackedRepaints();
542 }
543
544 PassRefPtr<ImmutableArray> WebPage::trackedRepaintRects()
545 {
546     FrameView* view = mainFrameView();
547     if (!view)
548         return ImmutableArray::create();
549
550     const Vector<IntRect>& rects = view->trackedRepaintRects();
551     size_t size = rects.size();
552     if (!size)
553         return ImmutableArray::create();
554
555     Vector<RefPtr<APIObject> > vector;
556     vector.reserveInitialCapacity(size);
557
558     for (size_t i = 0; i < size; ++i)
559         vector.uncheckedAppend(WebRect::create(toAPI(rects[i])));
560
561     return ImmutableArray::adopt(vector);
562 }
563
564 void WebPage::executeEditingCommand(const String& commandName, const String& argument)
565 {
566     Frame* frame = m_page->focusController()->focusedOrMainFrame();
567     if (!frame)
568         return;
569     frame->editor()->command(commandName).execute(argument);
570 }
571
572 bool WebPage::isEditingCommandEnabled(const String& commandName)
573 {
574     Frame* frame = m_page->focusController()->focusedOrMainFrame();
575     if (!frame)
576         return false;
577     
578     Editor::Command command = frame->editor()->command(commandName);
579     return command.isSupported() && command.isEnabled();
580 }
581     
582 void WebPage::clearMainFrameName()
583 {
584     if (Frame* frame = mainFrame())
585         frame->tree()->clearName();
586 }
587
588 #if USE(ACCELERATED_COMPOSITING)
589 void WebPage::enterAcceleratedCompositingMode(GraphicsLayer* layer)
590 {
591     m_drawingArea->setRootCompositingLayer(layer);
592 }
593
594 void WebPage::exitAcceleratedCompositingMode()
595 {
596     m_drawingArea->setRootCompositingLayer(0);
597 }
598 #endif
599
600 void WebPage::close()
601 {
602     if (m_isClosed)
603         return;
604
605     m_isClosed = true;
606
607     if (pageGroup()->isVisibleToInjectedBundle() && WebProcess::shared().injectedBundle())
608         WebProcess::shared().injectedBundle()->willDestroyPage(this);
609
610 #if ENABLE(INSPECTOR)
611     m_inspector = 0;
612 #endif
613 #if ENABLE(FULLSCREEN_API)
614     m_fullScreenManager = 0;
615 #endif
616
617     if (m_activePopupMenu) {
618         m_activePopupMenu->disconnectFromPage();
619         m_activePopupMenu = 0;
620     }
621
622     if (m_activeOpenPanelResultListener) {
623         m_activeOpenPanelResultListener->disconnectFromPage();
624         m_activeOpenPanelResultListener = 0;
625     }
626
627     m_sandboxExtensionTracker.invalidate();
628
629     m_underlayPage = nullptr;
630     m_printContext = nullptr;
631     m_mainFrame->coreFrame()->loader()->detachFromParent();
632     m_page = nullptr;
633     m_drawingArea = nullptr;
634
635     bool isRunningModal = m_isRunningModal;
636     m_isRunningModal = false;
637
638     // The WebPage can be destroyed by this call.
639     WebProcess::shared().removeWebPage(m_pageID);
640
641     if (isRunningModal)
642         WebProcess::shared().runLoop()->stop();
643 }
644
645 void WebPage::tryClose()
646 {
647     SendStopResponsivenessTimer stopper(this);
648
649     if (!m_mainFrame->coreFrame()->loader()->shouldClose()) {
650         send(Messages::WebPageProxy::StopResponsivenessTimer());
651         return;
652     }
653
654     send(Messages::WebPageProxy::ClosePage(true));
655 }
656
657 void WebPage::sendClose()
658 {
659     send(Messages::WebPageProxy::ClosePage(false));
660 }
661
662 void WebPage::loadURL(const String& url, const SandboxExtension::Handle& sandboxExtensionHandle)
663 {
664     loadURLRequest(ResourceRequest(KURL(KURL(), url)), sandboxExtensionHandle);
665 }
666
667 void WebPage::loadURLRequest(const ResourceRequest& request, const SandboxExtension::Handle& sandboxExtensionHandle)
668 {
669     SendStopResponsivenessTimer stopper(this);
670
671     m_sandboxExtensionTracker.beginLoad(m_mainFrame.get(), sandboxExtensionHandle);
672     m_mainFrame->coreFrame()->loader()->load(request, false);
673 }
674
675 void WebPage::loadData(PassRefPtr<SharedBuffer> sharedBuffer, const String& MIMEType, const String& encodingName, const KURL& baseURL, const KURL& unreachableURL)
676 {
677     SendStopResponsivenessTimer stopper(this);
678
679     ResourceRequest request(baseURL);
680     SubstituteData substituteData(sharedBuffer, MIMEType, encodingName, unreachableURL);
681     m_mainFrame->coreFrame()->loader()->load(request, substituteData, false);
682 }
683
684 void WebPage::loadHTMLString(const String& htmlString, const String& baseURLString)
685 {
686     RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(htmlString.characters()), htmlString.length() * sizeof(UChar));
687     KURL baseURL = baseURLString.isEmpty() ? blankURL() : KURL(KURL(), baseURLString);
688     loadData(sharedBuffer, "text/html", "utf-16", baseURL, KURL());
689 }
690
691 void WebPage::loadAlternateHTMLString(const String& htmlString, const String& baseURLString, const String& unreachableURLString)
692 {
693     RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(htmlString.characters()), htmlString.length() * sizeof(UChar));
694     KURL baseURL = baseURLString.isEmpty() ? blankURL() : KURL(KURL(), baseURLString);
695     KURL unreachableURL = unreachableURLString.isEmpty() ? KURL() : KURL(KURL(), unreachableURLString);
696     loadData(sharedBuffer, "text/html", "utf-16", baseURL, unreachableURL);
697 }
698
699 void WebPage::loadPlainTextString(const String& string)
700 {
701     RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(string.characters()), string.length() * sizeof(UChar));
702     loadData(sharedBuffer, "text/plain", "utf-16", blankURL(), KURL());
703 }
704
705 void WebPage::loadWebArchiveData(const CoreIPC::DataReference& webArchiveData)
706 {
707     RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(webArchiveData.data()), webArchiveData.size() * sizeof(uint8_t));
708     loadData(sharedBuffer, "application/x-webarchive", "utf-16", blankURL(), KURL());
709 }
710
711 void WebPage::linkClicked(const String& url, const WebMouseEvent& event)
712 {
713     Frame* frame = m_page->mainFrame();
714     if (!frame)
715         return;
716
717     RefPtr<Event> coreEvent;
718     if (event.type() != WebEvent::NoType)
719         coreEvent = MouseEvent::create(eventNames().clickEvent, frame->document()->defaultView(), platform(event), 0, 0);
720
721     frame->loader()->loadFrameRequest(FrameLoadRequest(frame->document()->securityOrigin(), ResourceRequest(url)), 
722         false, false, coreEvent.get(), 0, MaybeSendReferrer);
723 }
724
725 void WebPage::stopLoadingFrame(uint64_t frameID)
726 {
727     WebFrame* frame = WebProcess::shared().webFrame(frameID);
728     if (!frame)
729         return;
730
731     frame->coreFrame()->loader()->stopForUserCancel();
732 }
733
734 void WebPage::stopLoading()
735 {
736     SendStopResponsivenessTimer stopper(this);
737
738     m_mainFrame->coreFrame()->loader()->stopForUserCancel();
739 }
740
741 void WebPage::setDefersLoading(bool defersLoading)
742 {
743     m_page->setDefersLoading(defersLoading);
744 }
745
746 void WebPage::reload(bool reloadFromOrigin, const SandboxExtension::Handle& sandboxExtensionHandle)
747 {
748     SendStopResponsivenessTimer stopper(this);
749
750     m_sandboxExtensionTracker.beginLoad(m_mainFrame.get(), sandboxExtensionHandle);
751     m_mainFrame->coreFrame()->loader()->reload(reloadFromOrigin);
752 }
753
754 void WebPage::goForward(uint64_t backForwardItemID)
755 {
756     SendStopResponsivenessTimer stopper(this);
757
758     HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
759     ASSERT(item);
760     if (!item)
761         return;
762
763     m_page->goToItem(item, FrameLoadTypeForward);
764 }
765
766 void WebPage::goBack(uint64_t backForwardItemID)
767 {
768     SendStopResponsivenessTimer stopper(this);
769
770     HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
771     ASSERT(item);
772     if (!item)
773         return;
774
775     m_page->goToItem(item, FrameLoadTypeBack);
776 }
777
778 void WebPage::goToBackForwardItem(uint64_t backForwardItemID)
779 {
780     SendStopResponsivenessTimer stopper(this);
781
782     HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
783     ASSERT(item);
784     if (!item)
785         return;
786
787     m_page->goToItem(item, FrameLoadTypeIndexedBackForward);
788 }
789
790 void WebPage::tryRestoreScrollPosition()
791 {
792     m_page->mainFrame()->loader()->history()->restoreScrollPositionAndViewState();
793 }
794
795 void WebPage::layoutIfNeeded()
796 {
797     if (m_mainFrame->coreFrame()->view())
798         m_mainFrame->coreFrame()->view()->updateLayoutAndStyleIfNeededRecursive();
799
800     if (m_underlayPage) {
801         if (FrameView *frameView = m_underlayPage->mainFrameView())
802             frameView->updateLayoutAndStyleIfNeededRecursive();
803     }
804 }
805
806 void WebPage::setSize(const WebCore::IntSize& viewSize)
807 {
808     FrameView* view = m_page->mainFrame()->view();
809
810 #if USE(TILED_BACKING_STORE)
811     // If we are resizing to content ignore external attempts.
812     if (view->useFixedLayout())
813         return;
814 #endif
815
816     if (m_viewSize == viewSize)
817         return;
818
819     view->resize(viewSize);
820     view->setNeedsLayout();
821     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), viewSize));
822     
823     m_viewSize = viewSize;
824 }
825
826 #if USE(TILED_BACKING_STORE)
827 void WebPage::setFixedVisibleContentRect(const IntRect& rect)
828 {
829     ASSERT(m_useFixedLayout);
830
831     m_page->mainFrame()->view()->setFixedVisibleContentRect(rect);
832 }
833
834 void WebPage::setResizesToContentsUsingLayoutSize(const IntSize& targetLayoutSize)
835 {
836     ASSERT(m_useFixedLayout);
837     ASSERT(!targetLayoutSize.isEmpty());
838
839     FrameView* view = m_page->mainFrame()->view();
840
841     view->setDelegatesScrolling(true);
842     view->setUseFixedLayout(true);
843     view->setPaintsEntireContents(true);
844
845     if (view->fixedLayoutSize() == targetLayoutSize)
846         return;
847
848     // Always reset even when empty.
849     view->setFixedLayoutSize(targetLayoutSize);
850
851     m_page->settings()->setAcceleratedCompositingForFixedPositionEnabled(true);
852     m_page->settings()->setFixedElementsLayoutRelativeToFrame(true);
853
854     // Schedule a layout to use the new target size.
855     if (!view->layoutPending()) {
856         view->setNeedsLayout();
857         view->scheduleRelayout();
858     }
859 }
860
861 void WebPage::resizeToContentsIfNeeded()
862 {
863     ASSERT(m_useFixedLayout);
864
865     FrameView* view = m_page->mainFrame()->view();
866
867     if (!view->useFixedLayout())
868         return;
869
870     IntSize newSize = view->contentsSize().expandedTo(view->fixedLayoutSize());
871
872     if (newSize == m_viewSize)
873         return;
874
875     m_viewSize = newSize;
876     view->resize(newSize);
877     view->setNeedsLayout();
878 }
879
880 void WebPage::sendViewportAttributesChanged()
881 {
882     ASSERT(m_useFixedLayout);
883
884     // Viewport properties have no impact on zero sized fixed viewports.
885     if (m_viewportSize.isEmpty())
886         return;
887
888     // Recalculate the recommended layout size, when the available size (device pixel) changes.
889     Settings* settings = m_page->settings();
890
891     int minimumLayoutFallbackWidth = std::max(settings->layoutFallbackWidth(), m_viewportSize.width());
892
893     ViewportAttributes attr = computeViewportAttributes(m_page->viewportArguments(), minimumLayoutFallbackWidth, settings->deviceWidth(), settings->deviceHeight(), settings->deviceDPI(), m_viewportSize);
894
895     setResizesToContentsUsingLayoutSize(IntSize(static_cast<int>(attr.layoutSize.width()), static_cast<int>(attr.layoutSize.height())));
896     send(Messages::WebPageProxy::DidChangeViewportProperties(attr));
897 }
898
899 void WebPage::setViewportSize(const IntSize& size)
900 {
901     ASSERT(m_useFixedLayout);
902
903     if (m_viewportSize == size)
904         return;
905
906      m_viewportSize = size;
907
908     sendViewportAttributesChanged();
909 }
910
911 #endif
912
913 void WebPage::scrollMainFrameIfNotAtMaxScrollPosition(const IntSize& scrollOffset)
914 {
915     Frame* frame = m_page->mainFrame();
916
917     IntPoint scrollPosition = frame->view()->scrollPosition();
918     IntPoint maximumScrollPosition = frame->view()->maximumScrollPosition();
919
920     // If the current scroll position in a direction is the max scroll position 
921     // we don't want to scroll at all.
922     IntSize newScrollOffset;
923     if (scrollPosition.x() < maximumScrollPosition.x())
924         newScrollOffset.setWidth(scrollOffset.width());
925     if (scrollPosition.y() < maximumScrollPosition.y())
926         newScrollOffset.setHeight(scrollOffset.height());
927
928     if (newScrollOffset.isZero())
929         return;
930
931     frame->view()->setScrollPosition(frame->view()->scrollPosition() + newScrollOffset);
932 }
933
934 void WebPage::drawRect(GraphicsContext& graphicsContext, const IntRect& rect)
935 {
936     GraphicsContextStateSaver stateSaver(graphicsContext);
937     graphicsContext.clip(rect);
938
939     if (m_underlayPage) {
940         m_underlayPage->drawRect(graphicsContext, rect);
941
942         graphicsContext.beginTransparencyLayer(1);
943         m_mainFrame->coreFrame()->view()->paint(&graphicsContext, rect);
944         graphicsContext.endTransparencyLayer();
945         return;
946     }
947
948     m_mainFrame->coreFrame()->view()->paint(&graphicsContext, rect);
949 }
950
951 void WebPage::drawPageOverlay(GraphicsContext& graphicsContext, const IntRect& rect)
952 {
953     ASSERT(m_pageOverlay);
954
955     GraphicsContextStateSaver stateSaver(graphicsContext);
956     graphicsContext.clip(rect);
957     m_pageOverlay->drawRect(graphicsContext, rect);
958 }
959
960 double WebPage::textZoomFactor() const
961 {
962     Frame* frame = m_mainFrame->coreFrame();
963     if (!frame)
964         return 1;
965     return frame->textZoomFactor();
966 }
967
968 void WebPage::setTextZoomFactor(double zoomFactor)
969 {
970     Frame* frame = m_mainFrame->coreFrame();
971     if (!frame)
972         return;
973     frame->setTextZoomFactor(static_cast<float>(zoomFactor));
974 }
975
976 double WebPage::pageZoomFactor() const
977 {
978     Frame* frame = m_mainFrame->coreFrame();
979     if (!frame)
980         return 1;
981     return frame->pageZoomFactor();
982 }
983
984 void WebPage::setPageZoomFactor(double zoomFactor)
985 {
986     Frame* frame = m_mainFrame->coreFrame();
987     if (!frame)
988         return;
989     frame->setPageZoomFactor(static_cast<float>(zoomFactor));
990 }
991
992 void WebPage::setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor)
993 {
994     Frame* frame = m_mainFrame->coreFrame();
995     if (!frame)
996         return;
997     return frame->setPageAndTextZoomFactors(static_cast<float>(pageZoomFactor), static_cast<float>(textZoomFactor));
998 }
999
1000 void WebPage::windowScreenDidChange(uint64_t displayID)
1001 {
1002     m_page->windowScreenDidChange(static_cast<PlatformDisplayID>(displayID));
1003 }
1004
1005 void WebPage::scalePage(double scale, const IntPoint& origin)
1006 {
1007     m_page->setPageScaleFactor(scale, origin);
1008
1009     send(Messages::WebPageProxy::PageScaleFactorDidChange(scale));
1010 }
1011
1012 double WebPage::pageScaleFactor() const
1013 {
1014     return m_page->pageScaleFactor();
1015 }
1016
1017 void WebPage::setDeviceScaleFactor(float scaleFactor)
1018 {
1019     if (scaleFactor == m_page->deviceScaleFactor())
1020         return;
1021
1022     m_page->setDeviceScaleFactor(scaleFactor);
1023
1024     // Tell all our plug-in views that the device scale factor changed.
1025 #if PLATFORM(MAC)
1026     for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
1027         (*it)->setDeviceScaleFactor(scaleFactor);
1028 #endif
1029
1030     if (m_findController.isShowingOverlay()) {
1031         // We must have updated layout to get the selection rects right.
1032         layoutIfNeeded();
1033         m_findController.deviceScaleFactorDidChange();
1034     }
1035 }
1036
1037 float WebPage::deviceScaleFactor() const
1038 {
1039     return m_page->deviceScaleFactor();
1040 }
1041
1042 void WebPage::setUseFixedLayout(bool fixed)
1043 {
1044     m_useFixedLayout = fixed;
1045
1046     FrameView* view = mainFrameView();
1047     if (!view)
1048         return;
1049
1050     view->setUseFixedLayout(fixed);
1051     if (!fixed)
1052         view->setFixedLayoutSize(IntSize());
1053 }
1054
1055 void WebPage::setFixedLayoutSize(const IntSize& size)
1056 {
1057     FrameView* view = mainFrameView();
1058     if (!view)
1059         return;
1060
1061     view->setFixedLayoutSize(size);
1062     view->forceLayout();
1063 }
1064
1065 void WebPage::setPaginationMode(uint32_t mode)
1066 {
1067     Page::Pagination pagination = m_page->pagination();
1068     pagination.mode = static_cast<Page::Pagination::Mode>(mode);
1069     m_page->setPagination(pagination);
1070 }
1071
1072 void WebPage::setPaginationBehavesLikeColumns(bool behavesLikeColumns)
1073 {
1074     Page::Pagination pagination = m_page->pagination();
1075     pagination.behavesLikeColumns = behavesLikeColumns;
1076     m_page->setPagination(pagination);
1077 }
1078
1079 void WebPage::setPageLength(double pageLength)
1080 {
1081     Page::Pagination pagination = m_page->pagination();
1082     pagination.pageLength = pageLength;
1083     m_page->setPagination(pagination);
1084 }
1085
1086 void WebPage::setGapBetweenPages(double gap)
1087 {
1088     Page::Pagination pagination = m_page->pagination();
1089     pagination.gap = gap;
1090     m_page->setPagination(pagination);
1091 }
1092
1093 void WebPage::installPageOverlay(PassRefPtr<PageOverlay> pageOverlay)
1094 {
1095     bool shouldFadeIn = true;
1096     
1097     if (m_pageOverlay) {
1098         m_pageOverlay->setPage(0);
1099
1100         if (pageOverlay) {
1101             // We're installing a page overlay when a page overlay is already active.
1102             // In this case we don't want to fade in the new overlay.
1103             shouldFadeIn = false;
1104         }
1105     }
1106
1107     m_pageOverlay = pageOverlay;
1108     m_pageOverlay->setPage(this);
1109
1110     if (shouldFadeIn)
1111         m_pageOverlay->startFadeInAnimation();
1112
1113     m_drawingArea->didInstallPageOverlay();
1114 #if PLATFORM(WIN)
1115     send(Messages::WebPageProxy::DidInstallOrUninstallPageOverlay(true));
1116 #endif
1117
1118     m_pageOverlay->setNeedsDisplay();
1119 }
1120
1121 void WebPage::uninstallPageOverlay(PageOverlay* pageOverlay, bool fadeOut)
1122 {
1123     if (pageOverlay != m_pageOverlay)
1124         return;
1125
1126     if (fadeOut) {
1127         m_pageOverlay->startFadeOutAnimation();
1128         return;
1129     }
1130
1131     m_pageOverlay->setPage(0);
1132     m_pageOverlay = nullptr;
1133
1134     m_drawingArea->didUninstallPageOverlay();
1135 #if PLATFORM(WIN)
1136     send(Messages::WebPageProxy::DidInstallOrUninstallPageOverlay(false));
1137 #endif
1138 }
1139
1140 PassRefPtr<WebImage> WebPage::snapshotInViewCoordinates(const IntRect& rect, ImageOptions options)
1141 {
1142     FrameView* frameView = m_mainFrame->coreFrame()->view();
1143     if (!frameView)
1144         return 0;
1145
1146     IntSize bitmapSize = rect.size();
1147     float deviceScaleFactor = corePage()->deviceScaleFactor();
1148     bitmapSize.scale(deviceScaleFactor);
1149
1150     RefPtr<WebImage> snapshot = WebImage::create(bitmapSize, options);
1151     if (!snapshot->bitmap())
1152         return 0;
1153     
1154     OwnPtr<WebCore::GraphicsContext> graphicsContext = snapshot->bitmap()->createGraphicsContext();
1155     graphicsContext->applyDeviceScaleFactor(deviceScaleFactor);
1156     graphicsContext->translate(-rect.x(), -rect.y());
1157
1158     frameView->updateLayoutAndStyleIfNeededRecursive();
1159
1160     PaintBehavior oldBehavior = frameView->paintBehavior();
1161     frameView->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
1162     frameView->paint(graphicsContext.get(), rect);
1163     frameView->setPaintBehavior(oldBehavior);
1164
1165     return snapshot.release();
1166 }
1167
1168 PassRefPtr<WebImage> WebPage::scaledSnapshotInDocumentCoordinates(const IntRect& rect, double scaleFactor, ImageOptions options)
1169 {
1170     FrameView* frameView = m_mainFrame->coreFrame()->view();
1171     if (!frameView)
1172         return 0;
1173
1174     float combinedScaleFactor = scaleFactor * corePage()->deviceScaleFactor();
1175     IntSize size(ceil(rect.width() * combinedScaleFactor), ceil(rect.height() * combinedScaleFactor));
1176     RefPtr<WebImage> snapshot = WebImage::create(size, options);
1177     if (!snapshot->bitmap())
1178         return 0;
1179
1180     OwnPtr<WebCore::GraphicsContext> graphicsContext = snapshot->bitmap()->createGraphicsContext();
1181     graphicsContext->applyDeviceScaleFactor(combinedScaleFactor);
1182     graphicsContext->translate(-rect.x(), -rect.y());
1183
1184     frameView->updateLayoutAndStyleIfNeededRecursive();
1185
1186     PaintBehavior oldBehavior = frameView->paintBehavior();
1187     frameView->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
1188     frameView->paintContents(graphicsContext.get(), rect);
1189     frameView->setPaintBehavior(oldBehavior);
1190
1191     return snapshot.release();
1192 }
1193
1194 PassRefPtr<WebImage> WebPage::snapshotInDocumentCoordinates(const IntRect& rect, ImageOptions options)
1195 {
1196     return scaledSnapshotInDocumentCoordinates(rect, 1, options);
1197 }
1198
1199 void WebPage::pageDidScroll()
1200 {
1201     m_uiClient.pageDidScroll(this);
1202
1203     send(Messages::WebPageProxy::PageDidScroll());
1204 }
1205
1206 #if USE(TILED_BACKING_STORE)
1207 void WebPage::pageDidRequestScroll(const IntPoint& point)
1208 {
1209     send(Messages::WebPageProxy::PageDidRequestScroll(point));
1210 }
1211 #endif
1212
1213 #if ENABLE(CONTEXT_MENUS)
1214 WebContextMenu* WebPage::contextMenu()
1215 {
1216     if (!m_contextMenu)
1217         m_contextMenu = WebContextMenu::create(this);
1218     return m_contextMenu.get();
1219 }
1220 #endif
1221
1222 // Events 
1223
1224 static const WebEvent* g_currentEvent = 0;
1225
1226 // FIXME: WebPage::currentEvent is used by the plug-in code to avoid having to convert from DOM events back to
1227 // WebEvents. When we get the event handling sorted out, this should go away and the Widgets should get the correct
1228 // platform events passed to the event handler code.
1229 const WebEvent* WebPage::currentEvent()
1230 {
1231     return g_currentEvent;
1232 }
1233
1234 class CurrentEvent {
1235 public:
1236     explicit CurrentEvent(const WebEvent& event)
1237         : m_previousCurrentEvent(g_currentEvent)
1238     {
1239         g_currentEvent = &event;
1240     }
1241
1242     ~CurrentEvent()
1243     {
1244         g_currentEvent = m_previousCurrentEvent;
1245     }
1246
1247 private:
1248     const WebEvent* m_previousCurrentEvent;
1249 };
1250
1251 #if ENABLE(CONTEXT_MENUS)
1252 static bool isContextClick(const PlatformMouseEvent& event)
1253 {
1254     if (event.button() == WebCore::RightButton)
1255         return true;
1256
1257 #if PLATFORM(MAC)
1258     // FIXME: this really should be about OSX-style UI, not about the Mac port
1259     if (event.button() == WebCore::LeftButton && event.ctrlKey())
1260         return true;
1261 #endif
1262
1263     return false;
1264 }
1265
1266 static bool handleContextMenuEvent(const PlatformMouseEvent& platformMouseEvent, WebPage* page)
1267 {
1268     IntPoint point = page->corePage()->mainFrame()->view()->windowToContents(platformMouseEvent.position());
1269     HitTestResult result = page->corePage()->mainFrame()->eventHandler()->hitTestResultAtPoint(point, false);
1270
1271     Frame* frame = page->corePage()->mainFrame();
1272     if (result.innerNonSharedNode())
1273         frame = result.innerNonSharedNode()->document()->frame();
1274     
1275     bool handled = frame->eventHandler()->sendContextMenuEvent(platformMouseEvent);
1276     if (handled)
1277         page->contextMenu()->show();
1278
1279     return handled;
1280 }
1281 #endif
1282
1283 static bool handleMouseEvent(const WebMouseEvent& mouseEvent, WebPage* page, bool onlyUpdateScrollbars)
1284 {
1285     Frame* frame = page->corePage()->mainFrame();
1286     if (!frame->view())
1287         return false;
1288
1289     PlatformMouseEvent platformMouseEvent = platform(mouseEvent);
1290
1291     switch (platformMouseEvent.type()) {
1292         case PlatformEvent::MousePressed: {
1293 #if ENABLE(CONTEXT_MENUS)
1294             if (isContextClick(platformMouseEvent))
1295                 page->corePage()->contextMenuController()->clearContextMenu();
1296 #endif
1297
1298             bool handled = frame->eventHandler()->handleMousePressEvent(platformMouseEvent);
1299 #if ENABLE(CONTEXT_MENUS)
1300             if (isContextClick(platformMouseEvent))
1301                 handled = handleContextMenuEvent(platformMouseEvent, page);
1302 #endif
1303
1304             return handled;
1305         }
1306         case PlatformEvent::MouseReleased:
1307             return frame->eventHandler()->handleMouseReleaseEvent(platformMouseEvent);
1308         case PlatformEvent::MouseMoved:
1309             if (onlyUpdateScrollbars)
1310                 return frame->eventHandler()->passMouseMovedEventToScrollbars(platformMouseEvent);
1311             return frame->eventHandler()->mouseMoved(platformMouseEvent);
1312         default:
1313             ASSERT_NOT_REACHED();
1314             return false;
1315     }
1316 }
1317
1318 void WebPage::mouseEvent(const WebMouseEvent& mouseEvent)
1319 {
1320 #if ENABLE(CONTEXT_MENUS)
1321     // Don't try to handle any pending mouse events if a context menu is showing.
1322     if (m_isShowingContextMenu) {
1323         send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(mouseEvent.type()), false));
1324         return;
1325     }
1326 #endif
1327     
1328     bool handled = false;
1329     
1330     if (m_pageOverlay) {
1331         // Let the page overlay handle the event.
1332         handled = m_pageOverlay->mouseEvent(mouseEvent);
1333     }
1334
1335     if (!handled) {
1336         CurrentEvent currentEvent(mouseEvent);
1337
1338         // We need to do a full, normal hit test during this mouse event if the page is active or if a mouse
1339         // button is currently pressed. It is possible that neither of those things will be true since on 
1340         // Lion when legacy scrollbars are enabled, WebKit receives mouse events all the time. If it is one 
1341         // of those cases where the page is not active and the mouse is not pressed, then we can fire a more
1342         // efficient scrollbars-only version of the event.
1343         bool onlyUpdateScrollbars = !(m_page->focusController()->isActive() || (mouseEvent.button() != WebMouseEvent::NoButton));
1344         handled = handleMouseEvent(mouseEvent, this, onlyUpdateScrollbars);
1345     }
1346
1347     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(mouseEvent.type()), handled));
1348 }
1349
1350 void WebPage::mouseEventSyncForTesting(const WebMouseEvent& mouseEvent, bool& handled)
1351 {
1352     handled = m_pageOverlay && m_pageOverlay->mouseEvent(mouseEvent);
1353
1354     if (!handled) {
1355         CurrentEvent currentEvent(mouseEvent);
1356
1357         // We need to do a full, normal hit test during this mouse event if the page is active or if a mouse
1358         // button is currently pressed. It is possible that neither of those things will be true since on 
1359         // Lion when legacy scrollbars are enabled, WebKit receives mouse events all the time. If it is one 
1360         // of those cases where the page is not active and the mouse is not pressed, then we can fire a more
1361         // efficient scrollbars-only version of the event.
1362         bool onlyUpdateScrollbars = !(m_page->focusController()->isActive() || (mouseEvent.button() != WebMouseEvent::NoButton));
1363         handled = handleMouseEvent(mouseEvent, this, onlyUpdateScrollbars);
1364     }
1365 }
1366
1367 static bool handleWheelEvent(const WebWheelEvent& wheelEvent, Page* page)
1368 {
1369     Frame* frame = page->mainFrame();
1370     if (!frame->view())
1371         return false;
1372
1373     PlatformWheelEvent platformWheelEvent = platform(wheelEvent);
1374     return frame->eventHandler()->handleWheelEvent(platformWheelEvent);
1375 }
1376
1377 void WebPage::wheelEvent(const WebWheelEvent& wheelEvent)
1378 {
1379     CurrentEvent currentEvent(wheelEvent);
1380
1381     bool handled = handleWheelEvent(wheelEvent, m_page.get());
1382     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(wheelEvent.type()), handled));
1383 }
1384
1385 void WebPage::wheelEventSyncForTesting(const WebWheelEvent& wheelEvent, bool& handled)
1386 {
1387     CurrentEvent currentEvent(wheelEvent);
1388
1389     handled = handleWheelEvent(wheelEvent, m_page.get());
1390 }
1391
1392 static bool handleKeyEvent(const WebKeyboardEvent& keyboardEvent, Page* page)
1393 {
1394     if (!page->mainFrame()->view())
1395         return false;
1396
1397     if (keyboardEvent.type() == WebEvent::Char && keyboardEvent.isSystemKey())
1398         return page->focusController()->focusedOrMainFrame()->eventHandler()->handleAccessKey(platform(keyboardEvent));
1399     return page->focusController()->focusedOrMainFrame()->eventHandler()->keyEvent(platform(keyboardEvent));
1400 }
1401
1402 void WebPage::keyEvent(const WebKeyboardEvent& keyboardEvent)
1403 {
1404     CurrentEvent currentEvent(keyboardEvent);
1405
1406     bool handled = handleKeyEvent(keyboardEvent, m_page.get());
1407     // FIXME: Platform default behaviors should be performed during normal DOM event dispatch (in most cases, in default keydown event handler).
1408     if (!handled)
1409         handled = performDefaultBehaviorForKeyEvent(keyboardEvent);
1410
1411     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(keyboardEvent.type()), handled));
1412 }
1413
1414 void WebPage::keyEventSyncForTesting(const WebKeyboardEvent& keyboardEvent, bool& handled)
1415 {
1416     CurrentEvent currentEvent(keyboardEvent);
1417
1418     handled = handleKeyEvent(keyboardEvent, m_page.get());
1419     if (!handled)
1420         handled = performDefaultBehaviorForKeyEvent(keyboardEvent);
1421 }
1422
1423 #if ENABLE(GESTURE_EVENTS)
1424 static bool handleGestureEvent(const WebGestureEvent& gestureEvent, Page* page)
1425 {
1426     Frame* frame = page->mainFrame();
1427     if (!frame->view())
1428         return false;
1429
1430     PlatformGestureEvent platformGestureEvent = platform(gestureEvent);
1431     return frame->eventHandler()->handleGestureEvent(platformGestureEvent);
1432 }
1433
1434 void WebPage::gestureEvent(const WebGestureEvent& gestureEvent)
1435 {
1436     CurrentEvent currentEvent(gestureEvent);
1437
1438     bool handled = handleGestureEvent(gestureEvent, m_page.get());
1439     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(gestureEvent.type()), handled));
1440 }
1441 #endif
1442
1443 void WebPage::validateCommand(const String& commandName, uint64_t callbackID)
1444 {
1445     bool isEnabled = false;
1446     int32_t state = 0;
1447     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1448     if (frame) {
1449         Editor::Command command = frame->editor()->command(commandName);
1450         state = command.state();
1451         isEnabled = command.isSupported() && command.isEnabled();
1452     }
1453
1454     send(Messages::WebPageProxy::ValidateCommandCallback(commandName, isEnabled, state, callbackID));
1455 }
1456
1457 void WebPage::executeEditCommand(const String& commandName)
1458 {
1459     executeEditingCommand(commandName, String());
1460 }
1461
1462 uint64_t WebPage::restoreSession(const SessionState& sessionState)
1463 {
1464     const BackForwardListItemVector& list = sessionState.list();
1465     size_t size = list.size();
1466     uint64_t currentItemID = 0;
1467     for (size_t i = 0; i < size; ++i) {
1468         WebBackForwardListItem* webItem = list[i].get();
1469         DecoderAdapter decoder(webItem->backForwardData().data(), webItem->backForwardData().size());
1470         
1471         RefPtr<HistoryItem> item = HistoryItem::decodeBackForwardTree(webItem->url(), webItem->title(), webItem->originalURL(), decoder);
1472         if (!item) {
1473             LOG_ERROR("Failed to decode a HistoryItem from session state data.");
1474             return 0;
1475         }
1476         
1477         if (i == sessionState.currentIndex())
1478             currentItemID = webItem->itemID();
1479         
1480         WebBackForwardListProxy::addItemFromUIProcess(list[i]->itemID(), item.release());
1481     }    
1482     ASSERT(currentItemID);
1483     return currentItemID;
1484 }
1485
1486 void WebPage::restoreSessionAndNavigateToCurrentItem(const SessionState& sessionState)
1487 {
1488     if (uint64_t currentItemID = restoreSession(sessionState))
1489         goToBackForwardItem(currentItemID);
1490 }
1491
1492 #if ENABLE(TOUCH_EVENTS)
1493 #if PLATFORM(QT)
1494 void WebPage::highlightPotentialActivation(const IntPoint& point, const IntSize& area)
1495 {
1496     if (point == IntPoint::zero()) {
1497         // An empty point deactivates the highlighting.
1498         tapHighlightController().hideHighlight();
1499     } else {
1500         Frame* mainframe = m_page->mainFrame();
1501         Node* activationNode = 0;
1502         Node* adjustedNode = 0;
1503         IntPoint adjustedPoint;
1504
1505 #if ENABLE(TOUCH_ADJUSTMENT)
1506         if (!mainframe->eventHandler()->bestClickableNodeForTouchPoint(point, IntSize(area.width() / 2, area.height() / 2), adjustedPoint, adjustedNode))
1507             return;
1508
1509 #else
1510         HitTestResult result = mainframe->eventHandler()->hitTestResultAtPoint(mainframe->view()->windowToContents(point), /*allowShadowContent*/ false, /*ignoreClipping*/ true);
1511         adjustedNode = result.innerNode();
1512 #endif
1513         // Find the node to highlight. This is not the same as the node responding the tap gesture, because many
1514         // pages has a global click handler and we do not want to highlight the body.
1515         // Instead find the enclosing link or focusable element, or the last enclosing inline element.
1516         for (Node* node = adjustedNode; node; node = node->parentOrHostNode()) {
1517             if (node->isMouseFocusable() || node->isLink()) {
1518                 activationNode = node;
1519                 break;
1520             }
1521             if (node->renderer() && node->renderer()->isInline())
1522                 activationNode = node;
1523             else if (activationNode)
1524                 break;
1525         }
1526
1527         if (activationNode)
1528             tapHighlightController().highlight(activationNode);
1529     }
1530 }
1531 #endif
1532
1533 static bool handleTouchEvent(const WebTouchEvent& touchEvent, Page* page)
1534 {
1535     Frame* frame = page->mainFrame();
1536     if (!frame->view())
1537         return false;
1538
1539     return frame->eventHandler()->handleTouchEvent(platform(touchEvent));
1540 }
1541
1542 void WebPage::touchEvent(const WebTouchEvent& touchEvent)
1543 {
1544     CurrentEvent currentEvent(touchEvent);
1545
1546     bool handled = handleTouchEvent(touchEvent, m_page.get());
1547
1548     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(touchEvent.type()), handled));
1549 }
1550
1551 void WebPage::touchEventSyncForTesting(const WebTouchEvent& touchEvent, bool& handled)
1552 {
1553     CurrentEvent currentEvent(touchEvent);
1554     handled = handleTouchEvent(touchEvent, m_page.get());
1555 }
1556 #endif
1557
1558 void WebPage::scroll(Page* page, ScrollDirection direction, ScrollGranularity granularity)
1559 {
1560     page->focusController()->focusedOrMainFrame()->eventHandler()->scrollRecursively(direction, granularity);
1561 }
1562
1563 void WebPage::logicalScroll(Page* page, ScrollLogicalDirection direction, ScrollGranularity granularity)
1564 {
1565     page->focusController()->focusedOrMainFrame()->eventHandler()->logicalScrollRecursively(direction, granularity);
1566 }
1567
1568 void WebPage::scrollBy(uint32_t scrollDirection, uint32_t scrollGranularity)
1569 {
1570     scroll(m_page.get(), static_cast<ScrollDirection>(scrollDirection), static_cast<ScrollGranularity>(scrollGranularity));
1571 }
1572
1573 void WebPage::centerSelectionInVisibleArea()
1574 {
1575     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1576     if (!frame)
1577         return;
1578     
1579     frame->selection()->revealSelection(ScrollAlignment::alignCenterAlways);
1580     m_findController.showFindIndicatorInSelection();
1581 }
1582
1583 void WebPage::setActive(bool isActive)
1584 {
1585     m_page->focusController()->setActive(isActive);
1586
1587 #if PLATFORM(MAC)    
1588     // Tell all our plug-in views that the window focus changed.
1589     for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
1590         (*it)->setWindowIsFocused(isActive);
1591 #endif
1592 }
1593
1594 void WebPage::setDrawsBackground(bool drawsBackground)
1595 {
1596     if (m_drawsBackground == drawsBackground)
1597         return;
1598
1599     m_drawsBackground = drawsBackground;
1600
1601     for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
1602         if (FrameView* view = coreFrame->view())
1603             view->setTransparent(!drawsBackground);
1604     }
1605
1606     m_drawingArea->pageBackgroundTransparencyChanged();
1607     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize));
1608 }
1609
1610 void WebPage::setDrawsTransparentBackground(bool drawsTransparentBackground)
1611 {
1612     if (m_drawsTransparentBackground == drawsTransparentBackground)
1613         return;
1614
1615     m_drawsTransparentBackground = drawsTransparentBackground;
1616
1617     Color backgroundColor = drawsTransparentBackground ? Color::transparent : Color::white;
1618     for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
1619         if (FrameView* view = coreFrame->view())
1620             view->setBaseBackgroundColor(backgroundColor);
1621     }
1622
1623     m_drawingArea->pageBackgroundTransparencyChanged();
1624     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize));
1625 }
1626
1627 void WebPage::viewWillStartLiveResize()
1628 {
1629     if (!m_page)
1630         return;
1631
1632     // FIXME: This should propagate to all ScrollableAreas.
1633     if (Frame* frame = m_page->focusController()->focusedOrMainFrame()) {
1634         if (FrameView* view = frame->view())
1635             view->willStartLiveResize();
1636     }
1637 }
1638
1639 void WebPage::viewWillEndLiveResize()
1640 {
1641     if (!m_page)
1642         return;
1643
1644     // FIXME: This should propagate to all ScrollableAreas.
1645     if (Frame* frame = m_page->focusController()->focusedOrMainFrame()) {
1646         if (FrameView* view = frame->view())
1647             view->willEndLiveResize();
1648     }
1649 }
1650
1651 void WebPage::setFocused(bool isFocused)
1652 {
1653     m_page->focusController()->setFocused(isFocused);
1654 }
1655
1656 void WebPage::setInitialFocus(bool forward, bool isKeyboardEventValid, const WebKeyboardEvent& event)
1657 {
1658     if (!m_page || !m_page->focusController())
1659         return;
1660
1661     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1662     frame->document()->setFocusedNode(0);
1663
1664     if (isKeyboardEventValid && event.type() == WebEvent::KeyDown) {
1665         PlatformKeyboardEvent platformEvent(platform(event));
1666         platformEvent.disambiguateKeyDownEvent(PlatformEvent::RawKeyDown);
1667         m_page->focusController()->setInitialFocus(forward ? FocusDirectionForward : FocusDirectionBackward, KeyboardEvent::create(platformEvent, frame->document()->defaultView()).get());
1668         return;
1669     }
1670
1671     m_page->focusController()->setInitialFocus(forward ? FocusDirectionForward : FocusDirectionBackward, 0);
1672 }
1673
1674 void WebPage::setWindowResizerSize(const IntSize& windowResizerSize)
1675 {
1676     if (m_windowResizerSize == windowResizerSize)
1677         return;
1678
1679     m_windowResizerSize = windowResizerSize;
1680
1681     for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
1682         FrameView* view = coreFrame->view();
1683         if (view)
1684             view->windowResizerRectChanged();
1685     }
1686 }
1687
1688 void WebPage::setCanStartMediaTimerFired()
1689 {
1690     if (m_page)
1691         m_page->setCanStartMedia(true);
1692 }
1693
1694 void WebPage::setIsInWindow(bool isInWindow)
1695 {
1696     if (!isInWindow) {
1697         m_setCanStartMediaTimer.stop();
1698         m_page->setCanStartMedia(false);
1699         m_page->willMoveOffscreen();
1700     } else {
1701         // Defer the call to Page::setCanStartMedia() since it ends up sending a syncrhonous messages to the UI process
1702         // in order to get plug-in connections, and the UI process will be waiting for the Web process to update the backing
1703         // store after moving the view into a window, until it times out and paints white. See <rdar://problem/9242771>.
1704         m_setCanStartMediaTimer.startOneShot(0);
1705         m_page->didMoveOnscreen();
1706     }
1707 }
1708
1709 void WebPage::didReceivePolicyDecision(uint64_t frameID, uint64_t listenerID, uint32_t policyAction, uint64_t downloadID)
1710 {
1711     WebFrame* frame = WebProcess::shared().webFrame(frameID);
1712     if (!frame)
1713         return;
1714     frame->didReceivePolicyDecision(listenerID, static_cast<PolicyAction>(policyAction), downloadID);
1715 }
1716
1717 void WebPage::show()
1718 {
1719     send(Messages::WebPageProxy::ShowPage());
1720 }
1721
1722 void WebPage::setUserAgent(const String& userAgent)
1723 {
1724     m_userAgent = userAgent;
1725 }
1726
1727 void WebPage::suspendActiveDOMObjectsAndAnimations()
1728 {
1729     m_page->suspendActiveDOMObjectsAndAnimations();
1730 }
1731
1732 void WebPage::resumeActiveDOMObjectsAndAnimations()
1733 {
1734     m_page->resumeActiveDOMObjectsAndAnimations();
1735
1736     // We need to repaint on resume to kickstart animated painting again.
1737     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize));
1738 }
1739
1740 IntPoint WebPage::screenToWindow(const IntPoint& point)
1741 {
1742     IntPoint windowPoint;
1743     sendSync(Messages::WebPageProxy::ScreenToWindow(point), Messages::WebPageProxy::ScreenToWindow::Reply(windowPoint));
1744     return windowPoint;
1745 }
1746     
1747 IntRect WebPage::windowToScreen(const IntRect& rect)
1748 {
1749     IntRect screenRect;
1750     sendSync(Messages::WebPageProxy::WindowToScreen(rect), Messages::WebPageProxy::WindowToScreen::Reply(screenRect));
1751     return screenRect;
1752 }
1753
1754 IntRect WebPage::windowResizerRect() const
1755 {
1756     if (m_windowResizerSize.isEmpty())
1757         return IntRect();
1758
1759     IntSize frameViewSize;
1760     if (Frame* coreFrame = m_mainFrame->coreFrame()) {
1761         if (FrameView* view = coreFrame->view())
1762             frameViewSize = view->size();
1763     }
1764
1765     return IntRect(frameViewSize.width() - m_windowResizerSize.width(), frameViewSize.height() - m_windowResizerSize.height(), 
1766                    m_windowResizerSize.width(), m_windowResizerSize.height());
1767 }
1768
1769 KeyboardUIMode WebPage::keyboardUIMode()
1770 {
1771     bool fullKeyboardAccessEnabled = WebProcess::shared().fullKeyboardAccessEnabled();
1772     return static_cast<KeyboardUIMode>((fullKeyboardAccessEnabled ? KeyboardAccessFull : KeyboardAccessDefault) | (m_tabToLinks ? KeyboardAccessTabsToLinks : 0));
1773 }
1774
1775 void WebPage::runJavaScriptInMainFrame(const String& script, uint64_t callbackID)
1776 {
1777     // NOTE: We need to be careful when running scripts that the objects we depend on don't
1778     // disappear during script execution.
1779
1780     // Retain the SerializedScriptValue at this level so it (and the internal data) lives
1781     // long enough for the DataReference to be encoded by the sent message.
1782     RefPtr<SerializedScriptValue> serializedResultValue;
1783     CoreIPC::DataReference dataReference;
1784
1785     JSLock lock(SilenceAssertionsOnly);
1786     if (JSValue resultValue = m_mainFrame->coreFrame()->script()->executeScript(script, true).jsValue()) {
1787         if ((serializedResultValue = SerializedScriptValue::create(m_mainFrame->jsContext(), toRef(m_mainFrame->coreFrame()->script()->globalObject(mainThreadNormalWorld())->globalExec(), resultValue), 0)))
1788             dataReference = serializedResultValue->data();
1789     }
1790
1791     send(Messages::WebPageProxy::ScriptValueCallback(dataReference, callbackID));
1792 }
1793
1794 void WebPage::getContentsAsString(uint64_t callbackID)
1795 {
1796     String resultString = m_mainFrame->contentsAsString();
1797     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1798 }
1799
1800 void WebPage::getRenderTreeExternalRepresentation(uint64_t callbackID)
1801 {
1802     String resultString = renderTreeExternalRepresentation();
1803     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1804 }
1805
1806 void WebPage::getSelectionOrContentsAsString(uint64_t callbackID)
1807 {
1808     String resultString = m_mainFrame->selectionAsString();
1809     if (resultString.isEmpty())
1810         resultString = m_mainFrame->contentsAsString();
1811     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1812 }
1813
1814 void WebPage::getSourceForFrame(uint64_t frameID, uint64_t callbackID)
1815 {
1816     String resultString;
1817     if (WebFrame* frame = WebProcess::shared().webFrame(frameID))
1818        resultString = frame->source();
1819
1820     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1821 }
1822
1823 void WebPage::getMainResourceDataOfFrame(uint64_t frameID, uint64_t callbackID)
1824 {
1825     CoreIPC::DataReference dataReference;
1826
1827     RefPtr<SharedBuffer> buffer;
1828     if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) {
1829         if (DocumentLoader* loader = frame->coreFrame()->loader()->documentLoader()) {
1830             if ((buffer = loader->mainResourceData()))
1831                 dataReference = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size());
1832         }
1833     }
1834
1835     send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
1836 }
1837
1838 static PassRefPtr<SharedBuffer> resourceDataForFrame(Frame* frame, const KURL& resourceURL)
1839 {
1840     DocumentLoader* loader = frame->loader()->documentLoader();
1841     if (!loader)
1842         return 0;
1843
1844     RefPtr<ArchiveResource> subresource = loader->subresource(resourceURL);
1845     if (!subresource)
1846         return 0;
1847
1848     return subresource->data();
1849 }
1850
1851 void WebPage::getResourceDataFromFrame(uint64_t frameID, const String& resourceURLString, uint64_t callbackID)
1852 {
1853     CoreIPC::DataReference dataReference;
1854     KURL resourceURL(KURL(), resourceURLString);
1855
1856     RefPtr<SharedBuffer> buffer;
1857     if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) {
1858         buffer = resourceDataForFrame(frame->coreFrame(), resourceURL);
1859         if (!buffer) {
1860             // Try to get the resource data from the cache.
1861             buffer = cachedResponseDataForURL(resourceURL);
1862         }
1863
1864         if (buffer)
1865             dataReference = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size());
1866     }
1867
1868     send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
1869 }
1870
1871 void WebPage::getWebArchiveOfFrame(uint64_t frameID, uint64_t callbackID)
1872 {
1873     CoreIPC::DataReference dataReference;
1874
1875 #if PLATFORM(MAC) || PLATFORM(WIN)
1876     RetainPtr<CFDataRef> data;
1877     if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) {
1878         if ((data = frame->webArchiveData(0, 0)))
1879             dataReference = CoreIPC::DataReference(CFDataGetBytePtr(data.get()), CFDataGetLength(data.get()));
1880     }
1881 #endif
1882
1883     send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
1884 }
1885
1886 void WebPage::forceRepaintWithoutCallback()
1887 {
1888     m_drawingArea->forceRepaint();
1889 }
1890
1891 void WebPage::forceRepaint(uint64_t callbackID)
1892 {
1893     if (m_drawingArea->forceRepaintAsync(callbackID))
1894         return;
1895
1896     forceRepaintWithoutCallback();
1897     send(Messages::WebPageProxy::VoidCallback(callbackID));
1898 }
1899
1900 void WebPage::preferencesDidChange(const WebPreferencesStore& store)
1901 {
1902     WebPreferencesStore::removeTestRunnerOverrides();
1903     updatePreferences(store);
1904 }
1905
1906 void WebPage::updatePreferences(const WebPreferencesStore& store)
1907 {
1908     Settings* settings = m_page->settings();
1909
1910     m_tabToLinks = store.getBoolValueForKey(WebPreferencesKey::tabsToLinksKey());
1911
1912     // FIXME: This should be generated from macro expansion for all preferences,
1913     // but we currently don't match the naming of WebCore exactly so we are
1914     // handrolling the boolean and integer preferences until that is fixed.
1915
1916 #define INITIALIZE_SETTINGS(KeyUpper, KeyLower, TypeName, Type, DefaultValue) settings->set##KeyUpper(store.get##TypeName##ValueForKey(WebPreferencesKey::KeyLower##Key()));
1917
1918     FOR_EACH_WEBKIT_STRING_PREFERENCE(INITIALIZE_SETTINGS)
1919
1920 #undef INITIALIZE_SETTINGS
1921
1922     settings->setScriptEnabled(store.getBoolValueForKey(WebPreferencesKey::javaScriptEnabledKey()));
1923     settings->setLoadsImagesAutomatically(store.getBoolValueForKey(WebPreferencesKey::loadsImagesAutomaticallyKey()));
1924     settings->setLoadsSiteIconsIgnoringImageLoadingSetting(store.getBoolValueForKey(WebPreferencesKey::loadsSiteIconsIgnoringImageLoadingPreferenceKey()));
1925     settings->setPluginsEnabled(store.getBoolValueForKey(WebPreferencesKey::pluginsEnabledKey()));
1926     settings->setJavaEnabled(store.getBoolValueForKey(WebPreferencesKey::javaEnabledKey()));
1927     settings->setJavaEnabledForLocalFiles(store.getBoolValueForKey(WebPreferencesKey::javaEnabledForLocalFilesKey()));    
1928     settings->setOfflineWebApplicationCacheEnabled(store.getBoolValueForKey(WebPreferencesKey::offlineWebApplicationCacheEnabledKey()));
1929     settings->setLocalStorageEnabled(store.getBoolValueForKey(WebPreferencesKey::localStorageEnabledKey()));
1930     settings->setXSSAuditorEnabled(store.getBoolValueForKey(WebPreferencesKey::xssAuditorEnabledKey()));
1931     settings->setFrameFlatteningEnabled(store.getBoolValueForKey(WebPreferencesKey::frameFlatteningEnabledKey()));
1932     settings->setPrivateBrowsingEnabled(store.getBoolValueForKey(WebPreferencesKey::privateBrowsingEnabledKey()));
1933     settings->setDeveloperExtrasEnabled(store.getBoolValueForKey(WebPreferencesKey::developerExtrasEnabledKey()));
1934     settings->setTextAreasAreResizable(store.getBoolValueForKey(WebPreferencesKey::textAreasAreResizableKey()));
1935     settings->setNeedsSiteSpecificQuirks(store.getBoolValueForKey(WebPreferencesKey::needsSiteSpecificQuirksKey()));
1936     settings->setJavaScriptCanOpenWindowsAutomatically(store.getBoolValueForKey(WebPreferencesKey::javaScriptCanOpenWindowsAutomaticallyKey()));
1937     settings->setForceFTPDirectoryListings(store.getBoolValueForKey(WebPreferencesKey::forceFTPDirectoryListingsKey()));
1938     settings->setDNSPrefetchingEnabled(store.getBoolValueForKey(WebPreferencesKey::dnsPrefetchingEnabledKey()));
1939 #if ENABLE(WEB_ARCHIVE)
1940     settings->setWebArchiveDebugModeEnabled(store.getBoolValueForKey(WebPreferencesKey::webArchiveDebugModeEnabledKey()));
1941 #endif
1942     settings->setLocalFileContentSniffingEnabled(store.getBoolValueForKey(WebPreferencesKey::localFileContentSniffingEnabledKey()));
1943     settings->setUsesPageCache(store.getBoolValueForKey(WebPreferencesKey::usesPageCacheKey()));
1944     settings->setPageCacheSupportsPlugins(store.getBoolValueForKey(WebPreferencesKey::pageCacheSupportsPluginsKey()));
1945     settings->setAuthorAndUserStylesEnabled(store.getBoolValueForKey(WebPreferencesKey::authorAndUserStylesEnabledKey()));
1946     settings->setPaginateDuringLayoutEnabled(store.getBoolValueForKey(WebPreferencesKey::paginateDuringLayoutEnabledKey()));
1947     settings->setDOMPasteAllowed(store.getBoolValueForKey(WebPreferencesKey::domPasteAllowedKey()));
1948     settings->setJavaScriptCanAccessClipboard(store.getBoolValueForKey(WebPreferencesKey::javaScriptCanAccessClipboardKey()));
1949     settings->setShouldPrintBackgrounds(store.getBoolValueForKey(WebPreferencesKey::shouldPrintBackgroundsKey()));
1950     settings->setWebSecurityEnabled(store.getBoolValueForKey(WebPreferencesKey::webSecurityEnabledKey()));
1951     settings->setAllowUniversalAccessFromFileURLs(store.getBoolValueForKey(WebPreferencesKey::allowUniversalAccessFromFileURLsKey()));
1952     settings->setAllowFileAccessFromFileURLs(store.getBoolValueForKey(WebPreferencesKey::allowFileAccessFromFileURLsKey()));
1953
1954     settings->setMinimumFontSize(store.getUInt32ValueForKey(WebPreferencesKey::minimumFontSizeKey()));
1955     settings->setMinimumLogicalFontSize(store.getUInt32ValueForKey(WebPreferencesKey::minimumLogicalFontSizeKey()));
1956     settings->setDefaultFontSize(store.getUInt32ValueForKey(WebPreferencesKey::defaultFontSizeKey()));
1957     settings->setDefaultFixedFontSize(store.getUInt32ValueForKey(WebPreferencesKey::defaultFixedFontSizeKey()));
1958     settings->setLayoutFallbackWidth(store.getUInt32ValueForKey(WebPreferencesKey::layoutFallbackWidthKey()));
1959     settings->setDeviceDPI(store.getUInt32ValueForKey(WebPreferencesKey::deviceDPIKey()));
1960     settings->setDeviceWidth(store.getUInt32ValueForKey(WebPreferencesKey::deviceWidthKey()));
1961     settings->setDeviceHeight(store.getUInt32ValueForKey(WebPreferencesKey::deviceHeightKey()));
1962     settings->setEditableLinkBehavior(static_cast<WebCore::EditableLinkBehavior>(store.getUInt32ValueForKey(WebPreferencesKey::editableLinkBehaviorKey())));
1963     settings->setShowsToolTipOverTruncatedText(store.getBoolValueForKey(WebPreferencesKey::showsToolTipOverTruncatedTextKey()));
1964
1965     settings->setAcceleratedCompositingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedCompositingEnabledKey()) && LayerTreeHost::supportsAcceleratedCompositing());
1966     settings->setAcceleratedDrawingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedDrawingEnabledKey()) && LayerTreeHost::supportsAcceleratedCompositing());
1967     settings->setCanvasUsesAcceleratedDrawing(store.getBoolValueForKey(WebPreferencesKey::canvasUsesAcceleratedDrawingKey()) && LayerTreeHost::supportsAcceleratedCompositing());
1968     settings->setShowDebugBorders(store.getBoolValueForKey(WebPreferencesKey::compositingBordersVisibleKey()));
1969     settings->setShowRepaintCounter(store.getBoolValueForKey(WebPreferencesKey::compositingRepaintCountersVisibleKey()));
1970     settings->setCSSCustomFilterEnabled(store.getBoolValueForKey(WebPreferencesKey::cssCustomFilterEnabledKey()));
1971     settings->setCSSRegionsEnabled(store.getBoolValueForKey(WebPreferencesKey::cssRegionsEnabledKey()));
1972     settings->setRegionBasedColumnsEnabled(store.getBoolValueForKey(WebPreferencesKey::regionBasedColumnsEnabledKey()));
1973     settings->setWebGLEnabled(store.getBoolValueForKey(WebPreferencesKey::webGLEnabledKey()));
1974     settings->setMediaPlaybackRequiresUserGesture(store.getBoolValueForKey(WebPreferencesKey::mediaPlaybackRequiresUserGestureKey()));
1975     settings->setMediaPlaybackAllowsInline(store.getBoolValueForKey(WebPreferencesKey::mediaPlaybackAllowsInlineKey()));
1976     settings->setMockScrollbarsEnabled(store.getBoolValueForKey(WebPreferencesKey::mockScrollbarsEnabledKey()));
1977     settings->setHyperlinkAuditingEnabled(store.getBoolValueForKey(WebPreferencesKey::hyperlinkAuditingEnabledKey()));
1978
1979     // <rdar://problem/10697417>: It is necessary to force compositing when accelerate drawing
1980     // is enabled on Mac so that scrollbars are always in their own layers.
1981 #if PLATFORM(MAC)
1982     if (settings->acceleratedDrawingEnabled())
1983         settings->setForceCompositingMode(LayerTreeHost::supportsAcceleratedCompositing());
1984     else
1985 #endif
1986         settings->setForceCompositingMode(store.getBoolValueForKey(WebPreferencesKey::forceCompositingModeKey()) && LayerTreeHost::supportsAcceleratedCompositing());
1987
1988 #if ENABLE(SQL_DATABASE)
1989     AbstractDatabase::setIsAvailable(store.getBoolValueForKey(WebPreferencesKey::databasesEnabledKey()));
1990 #endif
1991
1992 #if ENABLE(FULLSCREEN_API)
1993     settings->setFullScreenEnabled(store.getBoolValueForKey(WebPreferencesKey::fullScreenEnabledKey()));
1994 #endif
1995
1996     settings->setLocalStorageDatabasePath(WebProcess::shared().localStorageDirectory());
1997
1998 #if USE(AVFOUNDATION)
1999     settings->setAVFoundationEnabled(store.getBoolValueForKey(WebPreferencesKey::isAVFoundationEnabledKey()));
2000 #endif
2001
2002 #if ENABLE(WEB_SOCKETS)
2003     settings->setUseHixie76WebSocketProtocol(store.getBoolValueForKey(WebPreferencesKey::hixie76WebSocketProtocolEnabledKey()));
2004 #endif
2005
2006 #if ENABLE(WEB_AUDIO)
2007     settings->setWebAudioEnabled(store.getBoolValueForKey(WebPreferencesKey::webAudioEnabledKey()));
2008 #endif
2009
2010     settings->setApplicationChromeMode(store.getBoolValueForKey(WebPreferencesKey::applicationChromeModeKey()));    
2011     settings->setSuppressesIncrementalRendering(store.getBoolValueForKey(WebPreferencesKey::suppressesIncrementalRenderingKey()));
2012     settings->setBackspaceKeyNavigationEnabled(store.getBoolValueForKey(WebPreferencesKey::backspaceKeyNavigationEnabledKey()));
2013     settings->setCaretBrowsingEnabled(store.getBoolValueForKey(WebPreferencesKey::caretBrowsingEnabledKey()));
2014
2015 #if ENABLE(VIDEO_TRACK)
2016     settings->setShouldDisplaySubtitles(store.getBoolValueForKey(WebPreferencesKey::shouldDisplaySubtitlesKey()));
2017     settings->setShouldDisplayCaptions(store.getBoolValueForKey(WebPreferencesKey::shouldDisplayCaptionsKey()));
2018     settings->setShouldDisplayTextDescriptions(store.getBoolValueForKey(WebPreferencesKey::shouldDisplayTextDescriptionsKey()));
2019 #endif
2020
2021 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
2022     settings->setNotificationsEnabled(store.getBoolValueForKey(WebPreferencesKey::notificationsEnabledKey()));
2023 #endif
2024
2025     settings->setShouldRespectImageOrientation(store.getBoolValueForKey(WebPreferencesKey::shouldRespectImageOrientationKey()));
2026
2027     platformPreferencesDidChange(store);
2028
2029     if (m_drawingArea)
2030         m_drawingArea->updatePreferences();
2031 }
2032
2033 #if ENABLE(INSPECTOR)
2034 WebInspector* WebPage::inspector()
2035 {
2036     if (m_isClosed)
2037         return 0;
2038     if (!m_inspector)
2039         m_inspector = WebInspector::create(this);
2040     return m_inspector.get();
2041 }
2042 #endif
2043
2044 #if ENABLE(FULLSCREEN_API)
2045 WebFullScreenManager* WebPage::fullScreenManager()
2046 {
2047     if (!m_fullScreenManager)
2048         m_fullScreenManager = WebFullScreenManager::create(this);
2049     return m_fullScreenManager.get();
2050 }
2051 #endif
2052
2053 NotificationPermissionRequestManager* WebPage::notificationPermissionRequestManager()
2054 {
2055     if (m_notificationPermissionRequestManager)
2056         return m_notificationPermissionRequestManager.get();
2057
2058     m_notificationPermissionRequestManager = NotificationPermissionRequestManager::create(this);
2059     return m_notificationPermissionRequestManager.get();
2060 }
2061
2062 #if !PLATFORM(GTK) && !PLATFORM(MAC)
2063 bool WebPage::handleEditingKeyboardEvent(KeyboardEvent* evt)
2064 {
2065     Node* node = evt->target()->toNode();
2066     ASSERT(node);
2067     Frame* frame = node->document()->frame();
2068     ASSERT(frame);
2069
2070     const PlatformKeyboardEvent* keyEvent = evt->keyEvent();
2071     if (!keyEvent)
2072         return false;
2073
2074     Editor::Command command = frame->editor()->command(interpretKeyEvent(evt));
2075
2076     if (keyEvent->type() == PlatformEvent::RawKeyDown) {
2077         // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated,
2078         // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated
2079         // (e.g. Tab that inserts a Tab character, or Enter).
2080         return !command.isTextInsertion() && command.execute(evt);
2081     }
2082
2083     if (command.execute(evt))
2084         return true;
2085
2086     // Don't insert null or control characters as they can result in unexpected behaviour
2087     if (evt->charCode() < ' ')
2088         return false;
2089
2090     return frame->editor()->insertText(evt->keyEvent()->text(), evt);
2091 }
2092 #endif
2093
2094 #if PLATFORM(WIN)
2095 void WebPage::performDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, const WebCore::DragDataMap& dataMap, uint32_t flags)
2096 {
2097     if (!m_page) {
2098         send(Messages::WebPageProxy::DidPerformDragControllerAction(WebCore::DragSession()));
2099         return;
2100     }
2101
2102     DragData dragData(dataMap, clientPosition, globalPosition, static_cast<DragOperation>(draggingSourceOperationMask), static_cast<DragApplicationFlags>(flags));
2103     switch (action) {
2104     case DragControllerActionEntered:
2105         send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragEntered(&dragData)));
2106         break;
2107
2108     case DragControllerActionUpdated:
2109         send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragUpdated(&dragData)));
2110         break;
2111         
2112     case DragControllerActionExited:
2113         m_page->dragController()->dragExited(&dragData);
2114         break;
2115         
2116     case DragControllerActionPerformDrag:
2117         m_page->dragController()->performDrag(&dragData);
2118         break;
2119         
2120     default:
2121         ASSERT_NOT_REACHED();
2122     }
2123 }
2124
2125 #elif PLATFORM(QT) || PLATFORM(GTK)
2126 void WebPage::performDragControllerAction(uint64_t action, WebCore::DragData dragData)
2127 {
2128     if (!m_page) {
2129         send(Messages::WebPageProxy::DidPerformDragControllerAction(WebCore::DragSession()));
2130 #if PLATFORM(QT)
2131         QMimeData* data = const_cast<QMimeData*>(dragData.platformData());
2132 #elif PLATFORM(GTK)
2133         DataObjectGtk* data = const_cast<DataObjectGtk*>(dragData.platformData());
2134 #endif
2135         delete data;
2136         return;
2137     }
2138
2139     switch (action) {
2140     case DragControllerActionEntered:
2141         send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragEntered(&dragData)));
2142         break;
2143
2144     case DragControllerActionUpdated:
2145         send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragUpdated(&dragData)));
2146         break;
2147
2148     case DragControllerActionExited:
2149         m_page->dragController()->dragExited(&dragData);
2150         break;
2151
2152     case DragControllerActionPerformDrag: {
2153         m_page->dragController()->performDrag(&dragData);
2154         break;
2155     }
2156
2157     default:
2158         ASSERT_NOT_REACHED();
2159     }
2160     // DragData does not delete its platformData so we need to do that here.
2161 #if PLATFORM(QT)
2162     QMimeData* data = const_cast<QMimeData*>(dragData.platformData());
2163 #elif PLATFORM(GTK)
2164     DataObjectGtk* data = const_cast<DataObjectGtk*>(dragData.platformData());
2165 #endif
2166     delete data;
2167 }
2168
2169 #else
2170 void WebPage::performDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, const String& dragStorageName, uint32_t flags, const SandboxExtension::Handle& sandboxExtensionHandle, const SandboxExtension::HandleArray& sandboxExtensionsHandleArray)
2171 {
2172     if (!m_page) {
2173         send(Messages::WebPageProxy::DidPerformDragControllerAction(WebCore::DragSession()));
2174         return;
2175     }
2176
2177     DragData dragData(dragStorageName, clientPosition, globalPosition, static_cast<DragOperation>(draggingSourceOperationMask), static_cast<DragApplicationFlags>(flags));
2178     switch (action) {
2179     case DragControllerActionEntered:
2180         send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragEntered(&dragData)));
2181         break;
2182
2183     case DragControllerActionUpdated:
2184         send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragUpdated(&dragData)));
2185         break;
2186         
2187     case DragControllerActionExited:
2188         m_page->dragController()->dragExited(&dragData);
2189         break;
2190         
2191     case DragControllerActionPerformDrag: {
2192         ASSERT(!m_pendingDropSandboxExtension);
2193
2194         m_pendingDropSandboxExtension = SandboxExtension::create(sandboxExtensionHandle);
2195         for (size_t i = 0; i < sandboxExtensionsHandleArray.size(); i++)
2196             m_pendingDropExtensionsForFileUpload.append(SandboxExtension::create(sandboxExtensionsHandleArray[i]));
2197
2198         m_page->dragController()->performDrag(&dragData);
2199
2200         // If we started loading a local file, the sandbox extension tracker would have adopted this
2201         // pending drop sandbox extension. If not, we'll play it safe and invalidate it.
2202         if (m_pendingDropSandboxExtension) {
2203             m_pendingDropSandboxExtension->invalidate();
2204             m_pendingDropSandboxExtension = nullptr;
2205         }
2206         for (size_t i = 0; i < m_pendingDropExtensionsForFileUpload.size(); i++)
2207             m_pendingDropExtensionsForFileUpload[i]->invalidate();
2208
2209         m_pendingDropExtensionsForFileUpload.clear();
2210         break;
2211     }
2212
2213     default:
2214         ASSERT_NOT_REACHED();
2215     }
2216 }
2217 #endif
2218
2219 void WebPage::dragEnded(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t operation)
2220 {
2221     IntPoint adjustedClientPosition(clientPosition.x() + m_page->dragController()->dragOffset().x(), clientPosition.y() + m_page->dragController()->dragOffset().y());
2222     IntPoint adjustedGlobalPosition(globalPosition.x() + m_page->dragController()->dragOffset().x(), globalPosition.y() + m_page->dragController()->dragOffset().y());
2223
2224     m_page->dragController()->dragEnded();
2225     FrameView* view = m_page->mainFrame()->view();
2226     if (!view)
2227         return;
2228     // FIXME: These are fake modifier keys here, but they should be real ones instead.
2229     PlatformMouseEvent event(adjustedClientPosition, adjustedGlobalPosition, LeftButton, PlatformEvent::MouseMoved, 0, false, false, false, false, currentTime());
2230     m_page->mainFrame()->eventHandler()->dragSourceEndedAt(event, (DragOperation)operation);
2231 }
2232
2233 void WebPage::willPerformLoadDragDestinationAction()
2234 {
2235     m_sandboxExtensionTracker.willPerformLoadDragDestinationAction(m_pendingDropSandboxExtension.release());
2236 }
2237
2238 void WebPage::mayPerformUploadDragDestinationAction()
2239 {
2240     for (size_t i = 0; i < m_pendingDropExtensionsForFileUpload.size(); i++)
2241         m_pendingDropExtensionsForFileUpload[i]->consumePermanently();
2242     m_pendingDropExtensionsForFileUpload.clear();
2243 }
2244
2245 WebUndoStep* WebPage::webUndoStep(uint64_t stepID)
2246 {
2247     return m_undoStepMap.get(stepID).get();
2248 }
2249
2250 void WebPage::addWebUndoStep(uint64_t stepID, WebUndoStep* entry)
2251 {
2252     m_undoStepMap.set(stepID, entry);
2253 }
2254
2255 void WebPage::removeWebEditCommand(uint64_t stepID)
2256 {
2257     m_undoStepMap.remove(stepID);
2258 }
2259
2260 void WebPage::unapplyEditCommand(uint64_t stepID)
2261 {
2262     WebUndoStep* step = webUndoStep(stepID);
2263     if (!step)
2264         return;
2265
2266     step->step()->unapply();
2267 }
2268
2269 void WebPage::reapplyEditCommand(uint64_t stepID)
2270 {
2271     WebUndoStep* step = webUndoStep(stepID);
2272     if (!step)
2273         return;
2274
2275     m_isInRedo = true;
2276     step->step()->reapply();
2277     m_isInRedo = false;
2278 }
2279
2280 void WebPage::didRemoveEditCommand(uint64_t commandID)
2281 {
2282     removeWebEditCommand(commandID);
2283 }
2284
2285 void WebPage::setActivePopupMenu(WebPopupMenu* menu)
2286 {
2287     m_activePopupMenu = menu;
2288 }
2289
2290 void WebPage::setActiveOpenPanelResultListener(PassRefPtr<WebOpenPanelResultListener> openPanelResultListener)
2291 {
2292     m_activeOpenPanelResultListener = openPanelResultListener;
2293 }
2294
2295 bool WebPage::findStringFromInjectedBundle(const String& target, FindOptions options)
2296 {
2297     return m_page->findString(target, options);
2298 }
2299
2300 void WebPage::findString(const String& string, uint32_t options, uint32_t maxMatchCount)
2301 {
2302     m_findController.findString(string, static_cast<FindOptions>(options), maxMatchCount);
2303 }
2304
2305 void WebPage::hideFindUI()
2306 {
2307     m_findController.hideFindUI();
2308 }
2309
2310 void WebPage::countStringMatches(const String& string, uint32_t options, uint32_t maxMatchCount)
2311 {
2312     m_findController.countStringMatches(string, static_cast<FindOptions>(options), maxMatchCount);
2313 }
2314
2315 void WebPage::didChangeSelectedIndexForActivePopupMenu(int32_t newIndex)
2316 {
2317     if (!m_activePopupMenu)
2318         return;
2319
2320     m_activePopupMenu->didChangeSelectedIndex(newIndex);
2321     m_activePopupMenu = 0;
2322 }
2323
2324 void WebPage::didChooseFilesForOpenPanel(const Vector<String>& files)
2325 {
2326     if (!m_activeOpenPanelResultListener)
2327         return;
2328
2329     m_activeOpenPanelResultListener->didChooseFiles(files);
2330     m_activeOpenPanelResultListener = 0;
2331 }
2332
2333 void WebPage::didCancelForOpenPanel()
2334 {
2335     m_activeOpenPanelResultListener = 0;
2336 }
2337
2338 #if ENABLE(WEB_PROCESS_SANDBOX)
2339 void WebPage::extendSandboxForFileFromOpenPanel(const SandboxExtension::Handle& handle)
2340 {
2341     SandboxExtension::create(handle)->consumePermanently();
2342 }
2343 #endif
2344
2345 #if ENABLE(GEOLOCATION)
2346 void WebPage::didReceiveGeolocationPermissionDecision(uint64_t geolocationID, bool allowed)
2347 {
2348     m_geolocationPermissionRequestManager.didReceiveGeolocationPermissionDecision(geolocationID, allowed);
2349 }
2350 #endif
2351
2352 void WebPage::didReceiveNotificationPermissionDecision(uint64_t notificationID, bool allowed)
2353 {
2354     notificationPermissionRequestManager()->didReceiveNotificationPermissionDecision(notificationID, allowed);
2355 }
2356
2357 void WebPage::advanceToNextMisspelling(bool startBeforeSelection)
2358 {
2359     Frame* frame = m_page->focusController()->focusedOrMainFrame();
2360     frame->editor()->advanceToNextMisspelling(startBeforeSelection);
2361 }
2362
2363 void WebPage::changeSpellingToWord(const String& word)
2364 {
2365     replaceSelectionWithText(m_page->focusController()->focusedOrMainFrame(), word);
2366 }
2367
2368 void WebPage::unmarkAllMisspellings()
2369 {
2370     for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
2371         if (Document* document = frame->document())
2372             document->markers()->removeMarkers(DocumentMarker::Spelling);
2373     }
2374 }
2375
2376 void WebPage::unmarkAllBadGrammar()
2377 {
2378     for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
2379         if (Document* document = frame->document())
2380             document->markers()->removeMarkers(DocumentMarker::Grammar);
2381     }
2382 }
2383
2384 #if PLATFORM(MAC)
2385 void WebPage::uppercaseWord()
2386 {
2387     m_page->focusController()->focusedOrMainFrame()->editor()->uppercaseWord();
2388 }
2389
2390 void WebPage::lowercaseWord()
2391 {
2392     m_page->focusController()->focusedOrMainFrame()->editor()->lowercaseWord();
2393 }
2394
2395 void WebPage::capitalizeWord()
2396 {
2397     m_page->focusController()->focusedOrMainFrame()->editor()->capitalizeWord();
2398 }
2399 #endif
2400     
2401 void WebPage::setTextForActivePopupMenu(int32_t index)
2402 {
2403     if (!m_activePopupMenu)
2404         return;
2405
2406     m_activePopupMenu->setTextForIndex(index);
2407 }
2408
2409 #if PLATFORM(GTK)
2410 void WebPage::failedToShowPopupMenu()
2411 {
2412     if (!m_activePopupMenu)
2413         return;
2414
2415     m_activePopupMenu->client()->popupDidHide();
2416 }
2417 #endif
2418
2419 #if ENABLE(CONTEXT_MENUS)
2420 void WebPage::didSelectItemFromActiveContextMenu(const WebContextMenuItemData& item)
2421 {
2422     if (!m_contextMenu)
2423         return;
2424
2425     m_contextMenu->itemSelected(item);
2426     m_contextMenu = 0;
2427 }
2428 #endif
2429
2430 void WebPage::replaceSelectionWithText(Frame* frame, const String& text)
2431 {
2432     bool selectReplacement = true;
2433     bool smartReplace = false;
2434     return frame->editor()->replaceSelectionWithText(text, selectReplacement, smartReplace);
2435 }
2436
2437 void WebPage::clearSelection()
2438 {
2439     m_page->focusController()->focusedOrMainFrame()->selection()->clear();
2440 }
2441
2442 bool WebPage::mainFrameHasCustomRepresentation() const
2443 {
2444     if (Frame* frame = mainFrame())
2445         return static_cast<WebFrameLoaderClient*>(frame->loader()->client())->frameHasCustomRepresentation();
2446
2447     return false;
2448 }
2449
2450 void WebPage::didChangeScrollOffsetForMainFrame()
2451 {
2452     Frame* frame = m_page->mainFrame();
2453     IntPoint scrollPosition = frame->view()->scrollPosition();
2454     IntPoint maximumScrollPosition = frame->view()->maximumScrollPosition();
2455     IntPoint minimumScrollPosition = frame->view()->minimumScrollPosition();
2456
2457     bool isPinnedToLeftSide = (scrollPosition.x() <= minimumScrollPosition.x());
2458     bool isPinnedToRightSide = (scrollPosition.x() >= maximumScrollPosition.x());
2459
2460     if (isPinnedToLeftSide != m_cachedMainFrameIsPinnedToLeftSide || isPinnedToRightSide != m_cachedMainFrameIsPinnedToRightSide) {
2461         send(Messages::WebPageProxy::DidChangeScrollOffsetPinningForMainFrame(isPinnedToLeftSide, isPinnedToRightSide));
2462         
2463         m_cachedMainFrameIsPinnedToLeftSide = isPinnedToLeftSide;
2464         m_cachedMainFrameIsPinnedToRightSide = isPinnedToRightSide;
2465     }
2466 }
2467
2468 void WebPage::mainFrameDidLayout()
2469 {
2470     unsigned pageCount = m_page->pageCount();
2471     if (pageCount != m_cachedPageCount) {
2472         send(Messages::WebPageProxy::DidChangePageCount(pageCount));
2473         m_cachedPageCount = pageCount;
2474     }
2475 }
2476
2477 #if PLATFORM(MAC)
2478
2479 void WebPage::addPluginView(PluginView* pluginView)
2480 {
2481     ASSERT(!m_pluginViews.contains(pluginView));
2482
2483     m_pluginViews.add(pluginView);
2484 }
2485
2486 void WebPage::removePluginView(PluginView* pluginView)
2487 {
2488     ASSERT(m_pluginViews.contains(pluginView));
2489
2490     m_pluginViews.remove(pluginView);
2491 }
2492
2493 void WebPage::setWindowIsVisible(bool windowIsVisible)
2494 {
2495     m_windowIsVisible = windowIsVisible;
2496
2497     corePage()->focusController()->setContainingWindowIsVisible(windowIsVisible);
2498
2499     // Tell all our plug-in views that the window visibility changed.
2500     for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
2501         (*it)->setWindowIsVisible(windowIsVisible);
2502 }
2503
2504 void WebPage::windowAndViewFramesChanged(const WebCore::IntRect& windowFrameInScreenCoordinates, const WebCore::IntRect& viewFrameInWindowCoordinates, const WebCore::IntPoint& accessibilityViewCoordinates)
2505 {
2506     m_windowFrameInScreenCoordinates = windowFrameInScreenCoordinates;
2507     m_viewFrameInWindowCoordinates = viewFrameInWindowCoordinates;
2508     m_accessibilityPosition = accessibilityViewCoordinates;
2509     
2510     // Tell all our plug-in views that the window and view frames have changed.
2511     for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
2512         (*it)->windowAndViewFramesChanged(windowFrameInScreenCoordinates, viewFrameInWindowCoordinates);
2513 }
2514 #endif
2515
2516 bool WebPage::windowIsFocused() const
2517 {
2518     return m_page->focusController()->isActive();
2519 }
2520
2521 bool WebPage::windowAndWebPageAreFocused() const
2522 {
2523 #if PLATFORM(MAC)
2524     if (!m_windowIsVisible)
2525         return false;
2526 #endif
2527     return m_page->focusController()->isFocused() && m_page->focusController()->isActive();
2528 }
2529
2530 void WebPage::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
2531 {
2532     if (messageID.is<CoreIPC::MessageClassDrawingArea>()) {
2533         if (m_drawingArea)
2534             m_drawingArea->didReceiveDrawingAreaMessage(connection, messageID, arguments);
2535         return;
2536     }
2537
2538 #if USE(TILED_BACKING_STORE) && USE(ACCELERATED_COMPOSITING)
2539     if (messageID.is<CoreIPC::MessageClassLayerTreeHost>()) {
2540         if (m_drawingArea)
2541             m_drawingArea->didReceiveLayerTreeHostMessage(connection, messageID, arguments);
2542         return;
2543     }
2544 #endif
2545     
2546 #if ENABLE(INSPECTOR)
2547     if (messageID.is<CoreIPC::MessageClassWebInspector>()) {
2548         if (WebInspector* inspector = this->inspector())
2549             inspector->didReceiveWebInspectorMessage(connection, messageID, arguments);
2550         return;
2551     }
2552 #endif
2553
2554 #if ENABLE(FULLSCREEN_API)
2555     if (messageID.is<CoreIPC::MessageClassWebFullScreenManager>()) {
2556         fullScreenManager()->didReceiveMessage(connection, messageID, arguments);
2557         return;
2558     }
2559 #endif
2560
2561     didReceiveWebPageMessage(connection, messageID, arguments);
2562 }
2563
2564 void WebPage::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments, OwnPtr<CoreIPC::ArgumentEncoder>& reply)
2565 {   
2566     didReceiveSyncWebPageMessage(connection, messageID, arguments, reply);
2567 }
2568     
2569 InjectedBundleBackForwardList* WebPage::backForwardList()
2570 {
2571     if (!m_backForwardList)
2572         m_backForwardList = InjectedBundleBackForwardList::create(this);
2573     return m_backForwardList.get();
2574 }
2575
2576 #if PLATFORM(QT)
2577 #if ENABLE(TOUCH_ADJUSTMENT)
2578 void WebPage::findZoomableAreaForPoint(const WebCore::IntPoint& point, const WebCore::IntSize& area)
2579 {
2580     Node* node = 0;
2581     IntRect zoomableArea;
2582     bool foundAreaForTouchPoint = m_mainFrame->coreFrame()->eventHandler()->bestZoomableAreaForTouchPoint(point, IntSize(area.width() / 2, area.height() / 2), zoomableArea, node);
2583     ASSERT(node);
2584
2585     if (!foundAreaForTouchPoint)
2586         return;
2587
2588     if (node->document() && node->document()->view())
2589         zoomableArea = node->document()->view()->contentsToWindow(zoomableArea);
2590
2591     send(Messages::WebPageProxy::DidFindZoomableArea(point, zoomableArea));
2592 }
2593
2594 #else
2595 void WebPage::findZoomableAreaForPoint(const WebCore::IntPoint& point, const WebCore::IntSize& area)
2596 {
2597     UNUSED_PARAM(area);
2598     Frame* mainframe = m_mainFrame->coreFrame();
2599     HitTestResult result = mainframe->eventHandler()->hitTestResultAtPoint(mainframe->view()->windowToContents(point), /*allowShadowContent*/ false, /*ignoreClipping*/ true);
2600
2601     Node* node = result.innerNode();
2602
2603     if (!node)
2604         return;
2605
2606     IntRect zoomableArea = node->getRect();
2607
2608     while (true) {
2609         bool found = !node->isTextNode() && !node->isShadowRoot();
2610
2611         // No candidate found, bail out.
2612         if (!found && !node->parentNode())
2613             return;
2614
2615         // Candidate found, and it is a better candidate than its parent.
2616         // NB: A parent is considered a better candidate iff the node is
2617         // contained by it and it is the only child.
2618         if (found && (!node->parentNode() || node->parentNode()->childNodeCount() != 1))
2619             break;
2620
2621         node = node->parentNode();
2622         zoomableArea.unite(node->getRect());
2623     }
2624
2625     if (node->document() && node->document()->frame() && node->document()->frame()->view()) {
2626         const ScrollView* view = node->document()->frame()->view();
2627         zoomableArea = view->contentsToWindow(zoomableArea);
2628     }
2629
2630     send(Messages::WebPageProxy::DidFindZoomableArea(point, zoomableArea));
2631 }
2632 #endif
2633 #endif
2634
2635 WebPage::SandboxExtensionTracker::~SandboxExtensionTracker()
2636 {
2637     invalidate();
2638 }
2639
2640 void WebPage::SandboxExtensionTracker::invalidate()
2641 {
2642     if (m_pendingProvisionalSandboxExtension) {
2643         m_pendingProvisionalSandboxExtension->invalidate();
2644         m_pendingProvisionalSandboxExtension = 0;
2645     }
2646
2647     if (m_provisionalSandboxExtension) {
2648         m_provisionalSandboxExtension->invalidate();
2649         m_provisionalSandboxExtension = 0;
2650     }
2651
2652     if (m_committedSandboxExtension) {
2653         m_committedSandboxExtension->invalidate();
2654         m_committedSandboxExtension = 0;
2655     }
2656 }
2657
2658 void WebPage::SandboxExtensionTracker::willPerformLoadDragDestinationAction(PassRefPtr<SandboxExtension> pendingDropSandboxExtension)
2659 {
2660     setPendingProvisionalSandboxExtension(pendingDropSandboxExtension);
2661 }
2662
2663 void WebPage::SandboxExtensionTracker::beginLoad(WebFrame* frame, const SandboxExtension::Handle& handle)
2664 {
2665     ASSERT(frame->isMainFrame());
2666
2667     setPendingProvisionalSandboxExtension(SandboxExtension::create(handle));
2668 }
2669
2670 void WebPage::SandboxExtensionTracker::setPendingProvisionalSandboxExtension(PassRefPtr<SandboxExtension> pendingProvisionalSandboxExtension)
2671 {
2672     // If we get two beginLoad calls in succession, without a provisional load starting, then
2673     // m_pendingProvisionalSandboxExtension will be non-null. Invalidate and null out the extension if that is the case.
2674     if (m_pendingProvisionalSandboxExtension) {
2675         m_pendingProvisionalSandboxExtension->invalidate();
2676         m_pendingProvisionalSandboxExtension = nullptr;
2677     }
2678     
2679     m_pendingProvisionalSandboxExtension = pendingProvisionalSandboxExtension;    
2680 }
2681
2682 static bool shouldReuseCommittedSandboxExtension(WebFrame* frame)
2683 {
2684     ASSERT(frame->isMainFrame());
2685
2686     FrameLoader* frameLoader = frame->coreFrame()->loader();
2687     FrameLoadType frameLoadType = frameLoader->loadType();
2688
2689     // If the page is being reloaded, it should reuse whatever extension is committed.
2690     if (frameLoadType == FrameLoadTypeReload || frameLoadType == FrameLoadTypeReloadFromOrigin)
2691         return true;
2692
2693     DocumentLoader* documentLoader = frameLoader->documentLoader();
2694     DocumentLoader* provisionalDocumentLoader = frameLoader->provisionalDocumentLoader();
2695     if (!documentLoader || !provisionalDocumentLoader)
2696         return false;
2697
2698     if (documentLoader->url().isLocalFile() && provisionalDocumentLoader->url().isLocalFile())
2699         return true;
2700
2701     return false;
2702 }
2703
2704 void WebPage::SandboxExtensionTracker::didStartProvisionalLoad(WebFrame* frame)
2705 {
2706     if (!frame->isMainFrame())
2707         return;
2708
2709     // We should only reuse the commited sandbox extension if it is not null. It can be
2710     // null if the last load was for an error page.
2711     if (m_committedSandboxExtension && shouldReuseCommittedSandboxExtension(frame)) {
2712         m_pendingProvisionalSandboxExtension = m_committedSandboxExtension.release();
2713         ASSERT(!m_committedSandboxExtension);
2714     }
2715
2716     ASSERT(!m_provisionalSandboxExtension);
2717
2718     m_provisionalSandboxExtension = m_pendingProvisionalSandboxExtension.release();
2719     if (!m_provisionalSandboxExtension)
2720         return;
2721
2722     m_provisionalSandboxExtension->consume();
2723 }
2724
2725 void WebPage::SandboxExtensionTracker::didCommitProvisionalLoad(WebFrame* frame)
2726 {
2727     if (!frame->isMainFrame())
2728         return;
2729
2730     // Generally, there should be no pending extension at this stage, but we can have one if UI process
2731     // has an out of date idea of WebProcess state, and initiates a load or reload without stopping an existing one.
2732     if (m_pendingProvisionalSandboxExtension) {
2733         m_pendingProvisionalSandboxExtension->invalidate();
2734         m_pendingProvisionalSandboxExtension = nullptr;
2735     }
2736
2737     // The provisional load has been committed. Invalidate the currently committed sandbox
2738     // extension and make the provisional sandbox extension the committed sandbox extension.
2739     if (m_committedSandboxExtension)
2740         m_committedSandboxExtension->invalidate();
2741
2742     m_committedSandboxExtension = m_provisionalSandboxExtension.release();
2743 }
2744
2745 void WebPage::SandboxExtensionTracker::didFailProvisionalLoad(WebFrame* frame)
2746 {
2747     if (!frame->isMainFrame())
2748         return;
2749
2750     // Generally, there should be no pending extension at this stage, but we can have one if UI process
2751     // has an out of date idea of WebProcess state, and initiates a load or reload without stopping an existing one.
2752     if (m_pendingProvisionalSandboxExtension) {
2753         m_pendingProvisionalSandboxExtension->invalidate();
2754         m_pendingProvisionalSandboxExtension = nullptr;
2755     }
2756
2757     if (!m_provisionalSandboxExtension)
2758         return;
2759
2760     m_provisionalSandboxExtension->invalidate();
2761     m_provisionalSandboxExtension = nullptr;
2762 }
2763
2764 bool WebPage::hasLocalDataForURL(const KURL& url)
2765 {
2766     if (url.isLocalFile())
2767         return true;
2768
2769     FrameLoader* frameLoader = m_page->mainFrame()->loader();
2770     DocumentLoader* documentLoader = frameLoader ? frameLoader->documentLoader() : 0;
2771     if (documentLoader && documentLoader->subresource(url))
2772         return true;
2773
2774     return platformHasLocalDataForURL(url);
2775 }
2776
2777 void WebPage::setCustomTextEncodingName(const String& encoding)
2778 {
2779     m_page->mainFrame()->loader()->reloadWithOverrideEncoding(encoding);
2780 }
2781
2782 void WebPage::didRemoveBackForwardItem(uint64_t itemID)
2783 {
2784     WebBackForwardListProxy::removeItem(itemID);
2785 }
2786
2787 #if PLATFORM(MAC)
2788
2789 bool WebPage::isSpeaking()
2790 {
2791     bool result;
2792     return sendSync(Messages::WebPageProxy::GetIsSpeaking(), Messages::WebPageProxy::GetIsSpeaking::Reply(result)) && result;
2793 }
2794
2795 void WebPage::speak(const String& string)
2796 {
2797     send(Messages::WebPageProxy::Speak(string));
2798 }
2799
2800 void WebPage::stopSpeaking()
2801 {
2802     send(Messages::WebPageProxy::StopSpeaking());
2803 }
2804
2805 #endif
2806
2807 #if PLATFORM(MAC)
2808 RetainPtr<PDFDocument> WebPage::pdfDocumentForPrintingFrame(Frame* coreFrame)
2809 {
2810     Document* document = coreFrame->document();
2811     if (!document)
2812         return 0;
2813
2814     if (!document->isPluginDocument())
2815         return 0;
2816
2817     PluginView* pluginView = static_cast<PluginView*>(toPluginDocument(document)->pluginWidget());
2818     if (!pluginView)
2819         return 0;
2820
2821     return pluginView->pdfDocumentForPrinting();
2822 }
2823 #endif // PLATFORM(MAC)
2824
2825 void WebPage::beginPrinting(uint64_t frameID, const PrintInfo& printInfo)
2826 {
2827     WebFrame* frame = WebProcess::shared().webFrame(frameID);
2828     if (!frame)
2829         return;
2830
2831     Frame* coreFrame = frame->coreFrame();
2832     if (!coreFrame)
2833         return;
2834
2835 #if PLATFORM(MAC)
2836     if (pdfDocumentForPrintingFrame(coreFrame))
2837         return;
2838 #endif // PLATFORM(MAC)
2839
2840     if (!m_printContext)
2841         m_printContext = adoptPtr(new PrintContext(coreFrame));
2842
2843     drawingArea()->setLayerTreeStateIsFrozen(true);
2844     m_printContext->begin(printInfo.availablePaperWidth, printInfo.availablePaperHeight);
2845
2846     float fullPageHeight;
2847     m_printContext->computePageRects(FloatRect(0, 0, printInfo.availablePaperWidth, printInfo.availablePaperHeight), 0, 0, printInfo.pageSetupScaleFactor, fullPageHeight, true);
2848
2849 #if PLATFORM(GTK)
2850     if (!m_printOperation)
2851         m_printOperation = WebPrintOperationGtk::create(this, printInfo);
2852 #endif
2853 }
2854
2855 void WebPage::endPrinting()
2856 {
2857     drawingArea()->setLayerTreeStateIsFrozen(false);
2858 #if PLATFORM(GTK)
2859     m_printOperation = 0;
2860 #endif
2861     m_printContext = nullptr;
2862 }
2863
2864 void WebPage::computePagesForPrinting(uint64_t frameID, const PrintInfo& printInfo, uint64_t callbackID)
2865 {
2866     Vector<IntRect> resultPageRects;
2867     double resultTotalScaleFactorForPrinting = 1;
2868
2869     beginPrinting(frameID, printInfo);
2870
2871     if (m_printContext) {
2872         resultPageRects = m_printContext->pageRects();
2873         resultTotalScaleFactorForPrinting = m_printContext->computeAutomaticScaleFactor(FloatSize(printInfo.availablePaperWidth, printInfo.availablePaperHeight)) * printInfo.pageSetupScaleFactor;
2874     }
2875 #if PLATFORM(MAC)
2876     else
2877         computePagesForPrintingPDFDocument(frameID, printInfo, resultPageRects);
2878 #endif // PLATFORM(MAC)
2879
2880     // If we're asked to print, we should actually print at least a blank page.
2881     if (resultPageRects.isEmpty())
2882         resultPageRects.append(IntRect(0, 0, 1, 1));
2883
2884     send(Messages::WebPageProxy::ComputedPagesCallback(resultPageRects, resultTotalScaleFactorForPrinting, callbackID));
2885 }
2886
2887 #if PLATFORM(MAC) || PLATFORM(WIN)
2888 void WebPage::drawRectToPDF(uint64_t frameID, const PrintInfo& printInfo, const WebCore::IntRect& rect, uint64_t callbackID)
2889 {
2890     WebFrame* frame = WebProcess::shared().webFrame(frameID);
2891     Frame* coreFrame = frame ? frame->coreFrame() : 0;
2892
2893     RetainPtr<CFMutableDataRef> pdfPageData(AdoptCF, CFDataCreateMutable(0, 0));
2894
2895     if (coreFrame) {
2896 #if PLATFORM(MAC)
2897         ASSERT(coreFrame->document()->printing() || pdfDocumentForPrintingFrame(coreFrame));
2898 #else
2899         ASSERT(coreFrame->document()->printing());
2900 #endif
2901
2902         // FIXME: Use CGDataConsumerCreate with callbacks to avoid copying the data.
2903         RetainPtr<CGDataConsumerRef> pdfDataConsumer(AdoptCF, CGDataConsumerCreateWithCFData(pdfPageData.get()));
2904
2905         CGRect mediaBox = CGRectMake(0, 0, rect.width(), rect.height());
2906         RetainPtr<CGContextRef> context(AdoptCF, CGPDFContextCreate(pdfDataConsumer.get(), &mediaBox, 0));
2907         RetainPtr<CFDictionaryRef> pageInfo(AdoptCF, CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
2908         CGPDFContextBeginPage(context.get(), pageInfo.get());
2909
2910 #if PLATFORM(MAC)
2911         if (RetainPtr<PDFDocument> pdfDocument = pdfDocumentForPrintingFrame(coreFrame)) {
2912             ASSERT(!m_printContext);
2913             drawRectToPDFFromPDFDocument(context.get(), pdfDocument.get(), printInfo, rect);
2914         } else
2915 #endif
2916         {
2917             GraphicsContext ctx(context.get());
2918             ctx.scale(FloatSize(1, -1));
2919             ctx.translate(0, -rect.height());
2920             m_printContext->spoolRect(ctx, rect);
2921         }
2922
2923         CGPDFContextEndPage(context.get());
2924         CGPDFContextClose(context.get());
2925     }
2926
2927     send(Messages::WebPageProxy::DataCallback(CoreIPC::DataReference(CFDataGetBytePtr(pdfPageData.get()), CFDataGetLength(pdfPageData.get())), callbackID));
2928 }
2929
2930 void WebPage::drawPagesToPDF(uint64_t frameID, const PrintInfo& printInfo, uint32_t first, uint32_t count, uint64_t callbackID)
2931 {
2932     WebFrame* frame = WebProcess::shared().webFrame(frameID);
2933     Frame* coreFrame = frame ? frame->coreFrame() : 0;
2934
2935     RetainPtr<CFMutableDataRef> pdfPageData(AdoptCF, CFDataCreateMutable(0, 0));
2936
2937     if (coreFrame) {
2938
2939 #if PLATFORM(MAC)
2940         ASSERT(coreFrame->document()->printing() || pdfDocumentForPrintingFrame(coreFrame));
2941 #else
2942         ASSERT(coreFrame->document()->printing());
2943 #endif
2944
2945         // FIXME: Use CGDataConsumerCreate with callbacks to avoid copying the data.
2946         RetainPtr<CGDataConsumerRef> pdfDataConsumer(AdoptCF, CGDataConsumerCreateWithCFData(pdfPageData.get()));
2947
2948         CGRect mediaBox = (m_printContext && m_printContext->pageCount()) ? m_printContext->pageRect(0) : CGRectMake(0, 0, printInfo.availablePaperWidth, printInfo.availablePaperHeight);
2949         RetainPtr<CGContextRef> context(AdoptCF, CGPDFContextCreate(pdfDataConsumer.get(), &mediaBox, 0));
2950
2951 #if PLATFORM(MAC)
2952         if (RetainPtr<PDFDocument> pdfDocument = pdfDocumentForPrintingFrame(coreFrame)) {
2953             ASSERT(!m_printContext);
2954             drawPagesToPDFFromPDFDocument(context.get(), pdfDocument.get(), printInfo, first, count);
2955         } else
2956 #endif
2957         {
2958             size_t pageCount = m_printContext->pageCount();
2959             for (uint32_t page = first; page < first + count; ++page) {
2960                 if (page >= pageCount)
2961                     break;
2962
2963                 RetainPtr<CFDictionaryRef> pageInfo(AdoptCF, CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
2964                 CGPDFContextBeginPage(context.get(), pageInfo.get());
2965
2966                 GraphicsContext ctx(context.get());
2967                 ctx.scale(FloatSize(1, -1));
2968                 ctx.translate(0, -m_printContext->pageRect(page).height());
2969                 m_printContext->spoolPage(ctx, page, m_printContext->pageRect(page).width());
2970
2971                 CGPDFContextEndPage(context.get());
2972             }
2973         }
2974         CGPDFContextClose(context.get());
2975     }
2976
2977     send(Messages::WebPageProxy::DataCallback(CoreIPC::DataReference(CFDataGetBytePtr(pdfPageData.get()), CFDataGetLength(pdfPageData.get())), callbackID));
2978 }
2979
2980 #elif PLATFORM(GTK)
2981
2982 void WebPage::drawPagesForPrinting(uint64_t frameID, const PrintInfo& printInfo, uint64_t callbackID)
2983 {
2984     beginPrinting(frameID, printInfo);
2985     if (m_printContext && m_printOperation) {
2986         m_printOperation->startPrint(m_printContext.get(), callbackID);
2987         return;
2988     }
2989
2990     send(Messages::WebPageProxy::VoidCallback(callbackID));
2991 }
2992 #endif
2993
2994 void WebPage::setMediaVolume(float volume)
2995 {
2996     m_page->setMediaVolume(volume);
2997 }
2998
2999 void WebPage::runModal()
3000 {
3001     if (m_isClosed)
3002         return;
3003     if (m_isRunningModal)
3004         return;
3005
3006     m_isRunningModal = true;
3007     send(Messages::WebPageProxy::RunModal());
3008     RunLoop::run();
3009     ASSERT(!m_isRunningModal);
3010 }
3011
3012 void WebPage::setMemoryCacheMessagesEnabled(bool memoryCacheMessagesEnabled)
3013 {
3014     m_page->setMemoryCacheClientCallsEnabled(memoryCacheMessagesEnabled);
3015 }
3016
3017 bool WebPage::canHandleRequest(const WebCore::ResourceRequest& request)
3018 {
3019     if (SchemeRegistry::shouldLoadURLSchemeAsEmptyDocument(request.url().protocol()))
3020         return true;
3021     return platformCanHandleRequest(request);
3022 }
3023
3024 #if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD)
3025 void WebPage::handleAlternativeTextUIResult(const String& result)
3026 {
3027     Frame* frame = m_page->focusController()->focusedOrMainFrame();
3028     if (!frame)
3029         return;
3030     frame->editor()->handleAlternativeTextUIResult(result);
3031 }
3032 #endif
3033
3034 void WebPage::simulateMouseDown(int button, WebCore::IntPoint position, int clickCount, WKEventModifiers modifiers, double time)
3035 {
3036     mouseEvent(WebMouseEvent(WebMouseEvent::MouseDown, static_cast<WebMouseEvent::Button>(button), position, position, 0, 0, 0, clickCount, static_cast<WebMouseEvent::Modifiers>(modifiers), time));
3037 }
3038
3039 void WebPage::simulateMouseUp(int button, WebCore::IntPoint position, int clickCount, WKEventModifiers modifiers, double time)
3040 {
3041     mouseEvent(WebMouseEvent(WebMouseEvent::MouseUp, static_cast<WebMouseEvent::Button>(button), position, position, 0, 0, 0, clickCount, static_cast<WebMouseEvent::Modifiers>(modifiers), time));
3042 }
3043
3044 void WebPage::simulateMouseMotion(WebCore::IntPoint position, double time)
3045 {
3046     mouseEvent(WebMouseEvent(WebMouseEvent::MouseMove, WebMouseEvent::NoButton, position, position, 0, 0, 0, 0, WebMouseEvent::Modifiers(), time));
3047 }
3048
3049 String WebPage::viewportConfigurationAsText(int deviceDPI, int deviceWidth, int deviceHeight, int availableWidth, int availableHeight)
3050 {
3051     ViewportArguments arguments = mainFrame()->document()->viewportArguments();
3052     ViewportAttributes attrs = WebCore::computeViewportAttributes(arguments, /* default layout width for non-mobile pages */ 980, deviceWidth, deviceHeight, deviceDPI, IntSize(availableWidth, availableHeight));
3053     WebCore::restrictMinimumScaleFactorToViewportSize(attrs, IntSize(availableWidth, availableHeight));
3054     WebCore::restrictScaleFactorToInitialScaleIfNotUserScalable(attrs);
3055     return String::format("viewport size %fx%f scale %f with limits [%f, %f] and userScalable %f\n", attrs.layoutSize.width(), attrs.layoutSize.height(), attrs.initialScale, attrs.minimumScale, attrs.maximumScale, attrs.userScalable);
3056 }
3057
3058 void WebPage::setCompositionForTesting(const String& compositionString, uint64_t from, uint64_t length)
3059 {
3060     Frame* frame = m_page->focusController()->focusedOrMainFrame();
3061     if (!frame || !frame->editor()->canEdit())
3062         return;
3063
3064     Vector<CompositionUnderline> underlines;
3065     underlines.append(CompositionUnderline(0, compositionString.length(), Color(Color::black), false));
3066     frame->editor()->setComposition(compositionString, underlines, from, from + length);
3067 }
3068
3069 bool WebPage::hasCompositionForTesting()
3070 {
3071     Frame* frame = m_page->focusController()->focusedOrMainFrame();
3072     return frame && frame->editor()->hasComposition();
3073 }
3074
3075 void WebPage::confirmCompositionForTesting(const String& compositionString)
3076 {
3077     Frame* frame = m_page->focusController()->focusedOrMainFrame();
3078     if (!frame || !frame->editor()->canEdit())
3079         return;
3080
3081     if (compositionString.isNull())
3082         frame->editor()->confirmComposition();
3083     frame->editor()->confirmComposition(compositionString);
3084 }
3085
3086 void WebPage::numWheelEventHandlersChanged(unsigned numWheelEventHandlers)
3087 {
3088     if (m_numWheelEventHandlers == numWheelEventHandlers)
3089         return;
3090
3091     m_numWheelEventHandlers = numWheelEventHandlers;
3092     recomputeShortCircuitHorizontalWheelEventsState();
3093 }
3094
3095 static bool hasEnabledHorizontalScrollbar(ScrollableArea* scrollableArea)
3096 {
3097     if (Scrollbar* scrollbar = scrollableArea->horizontalScrollbar())
3098         return scrollbar->enabled();
3099
3100     return false;
3101 }
3102
3103 static bool pageContainsAnyHorizontalScrollbars(Frame* mainFrame)
3104 {
3105     if (FrameView* frameView = mainFrame->view()) {
3106         if (hasEnabledHorizontalScrollbar(frameView))
3107             return true;
3108     }
3109
3110     for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext()) {
3111         FrameView* frameView = frame->view();
3112         if (!frameView)
3113             continue;
3114
3115         const HashSet<ScrollableArea*>* scrollableAreas = frameView->scrollableAreas();
3116         if (!scrollableAreas)
3117             continue;
3118
3119         for (HashSet<ScrollableArea*>::const_iterator it = scrollableAreas->begin(), end = scrollableAreas->end(); it != end; ++it) {
3120             ScrollableArea* scrollableArea = *it;
3121             if (!scrollableArea->isOnActivePage())
3122                 continue;
3123
3124             if (hasEnabledHorizontalScrollbar(scrollableArea))
3125                 return true;
3126         }
3127     }
3128
3129     return false;
3130 }
3131
3132 void WebPage::recomputeShortCircuitHorizontalWheelEventsState()
3133 {
3134     bool canShortCircuitHorizontalWheelEvents = !m_numWheelEventHandlers;
3135
3136     if (canShortCircuitHorizontalWheelEvents) {
3137         // Check if we have any horizontal scroll bars on the page.
3138         if (pageContainsAnyHorizontalScrollbars(mainFrame()))
3139             canShortCircuitHorizontalWheelEvents = false;
3140     }
3141
3142     if (m_canShortCircuitHorizontalWheelEvents == canShortCircuitHorizontalWheelEvents)
3143         return;
3144
3145     m_canShortCircuitHorizontalWheelEvents = canShortCircuitHorizontalWheelEvents;
3146     send(Messages::WebPageProxy::SetCanShortCircuitHorizontalWheelEvents(m_canShortCircuitHorizontalWheelEvents));
3147 }
3148
3149 Frame* WebPage::mainFrame() const
3150 {
3151     return m_page ? m_page->mainFrame() : 0;
3152 }
3153
3154 FrameView* WebPage::mainFrameView() const
3155 {
3156     if (Frame* frame = mainFrame())
3157         return frame->view();
3158     
3159     return 0;
3160 }
3161
3162 #if ENABLE(PAGE_VISIBILITY_API)
3163 void WebPage::setVisibilityState(int visibilityState, bool isInitialState)
3164 {
3165     if (!m_page)
3166         return;
3167     m_page->setVisibilityState(static_cast<WebCore::PageVisibilityState>(visibilityState), isInitialState);
3168 }
3169 #endif
3170
3171 } // namespace WebKit