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