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