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