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