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