[WK2] Color chooser API missing
[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     // The receiving end relies on DidReceiveEvent and InterpretQueuedKeyEvent arriving in the same order they are sent
1443     // (for keyboard events.) We set the DispatchMessageEvenWhenWaitingForSyncReply flag to ensure consistent ordering.
1444     connection()->send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(keyboardEvent.type()), handled), m_pageID, CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply);
1445 }
1446
1447 void WebPage::keyEventSyncForTesting(const WebKeyboardEvent& keyboardEvent, bool& handled)
1448 {
1449     CurrentEvent currentEvent(keyboardEvent);
1450
1451     handled = handleKeyEvent(keyboardEvent, m_page.get());
1452     if (!handled)
1453         handled = performDefaultBehaviorForKeyEvent(keyboardEvent);
1454 }
1455
1456 #if ENABLE(GESTURE_EVENTS)
1457 static bool handleGestureEvent(const WebGestureEvent& gestureEvent, Page* page)
1458 {
1459     Frame* frame = page->mainFrame();
1460     if (!frame->view())
1461         return false;
1462
1463     PlatformGestureEvent platformGestureEvent = platform(gestureEvent);
1464     return frame->eventHandler()->handleGestureEvent(platformGestureEvent);
1465 }
1466
1467 void WebPage::gestureEvent(const WebGestureEvent& gestureEvent)
1468 {
1469     CurrentEvent currentEvent(gestureEvent);
1470
1471     bool handled = handleGestureEvent(gestureEvent, m_page.get());
1472     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(gestureEvent.type()), handled));
1473 }
1474 #endif
1475
1476 void WebPage::validateCommand(const String& commandName, uint64_t callbackID)
1477 {
1478     bool isEnabled = false;
1479     int32_t state = 0;
1480     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1481     if (frame) {
1482         Editor::Command command = frame->editor()->command(commandName);
1483         state = command.state();
1484         isEnabled = command.isSupported() && command.isEnabled();
1485     }
1486
1487     send(Messages::WebPageProxy::ValidateCommandCallback(commandName, isEnabled, state, callbackID));
1488 }
1489
1490 void WebPage::executeEditCommand(const String& commandName)
1491 {
1492     executeEditingCommand(commandName, String());
1493 }
1494
1495 uint64_t WebPage::restoreSession(const SessionState& sessionState)
1496 {
1497     const BackForwardListItemVector& list = sessionState.list();
1498     size_t size = list.size();
1499     uint64_t currentItemID = 0;
1500     for (size_t i = 0; i < size; ++i) {
1501         WebBackForwardListItem* webItem = list[i].get();
1502         DecoderAdapter decoder(webItem->backForwardData().data(), webItem->backForwardData().size());
1503         
1504         RefPtr<HistoryItem> item = HistoryItem::decodeBackForwardTree(webItem->url(), webItem->title(), webItem->originalURL(), decoder);
1505         if (!item) {
1506             LOG_ERROR("Failed to decode a HistoryItem from session state data.");
1507             return 0;
1508         }
1509         
1510         if (i == sessionState.currentIndex())
1511             currentItemID = webItem->itemID();
1512         
1513         WebBackForwardListProxy::addItemFromUIProcess(list[i]->itemID(), item.release());
1514     }    
1515     ASSERT(currentItemID);
1516     return currentItemID;
1517 }
1518
1519 void WebPage::restoreSessionAndNavigateToCurrentItem(const SessionState& sessionState)
1520 {
1521     if (uint64_t currentItemID = restoreSession(sessionState))
1522         goToBackForwardItem(currentItemID);
1523 }
1524
1525 #if ENABLE(TOUCH_EVENTS)
1526 #if PLATFORM(QT)
1527 void WebPage::highlightPotentialActivation(const IntPoint& point, const IntSize& area)
1528 {
1529     if (point == IntPoint::zero()) {
1530         // An empty point deactivates the highlighting.
1531         tapHighlightController().hideHighlight();
1532     } else {
1533         Frame* mainframe = m_page->mainFrame();
1534         Node* activationNode = 0;
1535         Node* adjustedNode = 0;
1536         IntPoint adjustedPoint;
1537
1538 #if ENABLE(TOUCH_ADJUSTMENT)
1539         if (!mainframe->eventHandler()->bestClickableNodeForTouchPoint(point, IntSize(area.width() / 2, area.height() / 2), adjustedPoint, adjustedNode))
1540             return;
1541
1542 #else
1543         HitTestResult result = mainframe->eventHandler()->hitTestResultAtPoint(mainframe->view()->windowToContents(point), /*allowShadowContent*/ false, /*ignoreClipping*/ true);
1544         adjustedNode = result.innerNode();
1545 #endif
1546         // Find the node to highlight. This is not the same as the node responding the tap gesture, because many
1547         // pages has a global click handler and we do not want to highlight the body.
1548         // Instead find the enclosing link or focusable element, or the last enclosing inline element.
1549         for (Node* node = adjustedNode; node; node = node->parentOrHostNode()) {
1550             if (node->isMouseFocusable() || node->isLink()) {
1551                 activationNode = node;
1552                 break;
1553             }
1554             if (node->renderer() && node->renderer()->isInline())
1555                 activationNode = node;
1556             else if (activationNode)
1557                 break;
1558         }
1559
1560         if (activationNode)
1561             tapHighlightController().highlight(activationNode);
1562     }
1563 }
1564 #endif
1565
1566 static bool handleTouchEvent(const WebTouchEvent& touchEvent, Page* page)
1567 {
1568     Frame* frame = page->mainFrame();
1569     if (!frame->view())
1570         return false;
1571
1572     return frame->eventHandler()->handleTouchEvent(platform(touchEvent));
1573 }
1574
1575 void WebPage::touchEvent(const WebTouchEvent& touchEvent)
1576 {
1577     CurrentEvent currentEvent(touchEvent);
1578
1579     bool handled = handleTouchEvent(touchEvent, m_page.get());
1580
1581     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(touchEvent.type()), handled));
1582 }
1583
1584 void WebPage::touchEventSyncForTesting(const WebTouchEvent& touchEvent, bool& handled)
1585 {
1586     CurrentEvent currentEvent(touchEvent);
1587     handled = handleTouchEvent(touchEvent, m_page.get());
1588 }
1589 #endif
1590
1591 void WebPage::scroll(Page* page, ScrollDirection direction, ScrollGranularity granularity)
1592 {
1593     page->focusController()->focusedOrMainFrame()->eventHandler()->scrollRecursively(direction, granularity);
1594 }
1595
1596 void WebPage::logicalScroll(Page* page, ScrollLogicalDirection direction, ScrollGranularity granularity)
1597 {
1598     page->focusController()->focusedOrMainFrame()->eventHandler()->logicalScrollRecursively(direction, granularity);
1599 }
1600
1601 void WebPage::scrollBy(uint32_t scrollDirection, uint32_t scrollGranularity)
1602 {
1603     scroll(m_page.get(), static_cast<ScrollDirection>(scrollDirection), static_cast<ScrollGranularity>(scrollGranularity));
1604 }
1605
1606 void WebPage::centerSelectionInVisibleArea()
1607 {
1608     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1609     if (!frame)
1610         return;
1611     
1612     frame->selection()->revealSelection(ScrollAlignment::alignCenterAlways);
1613     m_findController.showFindIndicatorInSelection();
1614 }
1615
1616 void WebPage::setActive(bool isActive)
1617 {
1618     m_page->focusController()->setActive(isActive);
1619
1620 #if PLATFORM(MAC)    
1621     // Tell all our plug-in views that the window focus changed.
1622     for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
1623         (*it)->setWindowIsFocused(isActive);
1624 #endif
1625 }
1626
1627 void WebPage::setDrawsBackground(bool drawsBackground)
1628 {
1629     if (m_drawsBackground == drawsBackground)
1630         return;
1631
1632     m_drawsBackground = drawsBackground;
1633
1634     for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
1635         if (FrameView* view = coreFrame->view())
1636             view->setTransparent(!drawsBackground);
1637     }
1638
1639     m_drawingArea->pageBackgroundTransparencyChanged();
1640     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize));
1641 }
1642
1643 void WebPage::setDrawsTransparentBackground(bool drawsTransparentBackground)
1644 {
1645     if (m_drawsTransparentBackground == drawsTransparentBackground)
1646         return;
1647
1648     m_drawsTransparentBackground = drawsTransparentBackground;
1649
1650     Color backgroundColor = drawsTransparentBackground ? Color::transparent : Color::white;
1651     for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
1652         if (FrameView* view = coreFrame->view())
1653             view->setBaseBackgroundColor(backgroundColor);
1654     }
1655
1656     m_drawingArea->pageBackgroundTransparencyChanged();
1657     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize));
1658 }
1659
1660 void WebPage::viewWillStartLiveResize()
1661 {
1662     if (!m_page)
1663         return;
1664
1665     // FIXME: This should propagate to all ScrollableAreas.
1666     if (Frame* frame = m_page->focusController()->focusedOrMainFrame()) {
1667         if (FrameView* view = frame->view())
1668             view->willStartLiveResize();
1669     }
1670 }
1671
1672 void WebPage::viewWillEndLiveResize()
1673 {
1674     if (!m_page)
1675         return;
1676
1677     // FIXME: This should propagate to all ScrollableAreas.
1678     if (Frame* frame = m_page->focusController()->focusedOrMainFrame()) {
1679         if (FrameView* view = frame->view())
1680             view->willEndLiveResize();
1681     }
1682 }
1683
1684 void WebPage::setFocused(bool isFocused)
1685 {
1686     m_page->focusController()->setFocused(isFocused);
1687 }
1688
1689 void WebPage::setInitialFocus(bool forward, bool isKeyboardEventValid, const WebKeyboardEvent& event)
1690 {
1691     if (!m_page || !m_page->focusController())
1692         return;
1693
1694     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1695     frame->document()->setFocusedNode(0);
1696
1697     if (isKeyboardEventValid && event.type() == WebEvent::KeyDown) {
1698         PlatformKeyboardEvent platformEvent(platform(event));
1699         platformEvent.disambiguateKeyDownEvent(PlatformEvent::RawKeyDown);
1700         m_page->focusController()->setInitialFocus(forward ? FocusDirectionForward : FocusDirectionBackward, KeyboardEvent::create(platformEvent, frame->document()->defaultView()).get());
1701         return;
1702     }
1703
1704     m_page->focusController()->setInitialFocus(forward ? FocusDirectionForward : FocusDirectionBackward, 0);
1705 }
1706
1707 void WebPage::setWindowResizerSize(const IntSize& windowResizerSize)
1708 {
1709     if (m_windowResizerSize == windowResizerSize)
1710         return;
1711
1712     m_windowResizerSize = windowResizerSize;
1713
1714     for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
1715         FrameView* view = coreFrame->view();
1716         if (view)
1717             view->windowResizerRectChanged();
1718     }
1719 }
1720
1721 void WebPage::setCanStartMediaTimerFired()
1722 {
1723     if (m_page)
1724         m_page->setCanStartMedia(true);
1725 }
1726
1727 void WebPage::setIsInWindow(bool isInWindow)
1728 {
1729     if (!isInWindow) {
1730         m_setCanStartMediaTimer.stop();
1731         m_page->setCanStartMedia(false);
1732         m_page->willMoveOffscreen();
1733     } else {
1734         // Defer the call to Page::setCanStartMedia() since it ends up sending a syncrhonous messages to the UI process
1735         // in order to get plug-in connections, and the UI process will be waiting for the Web process to update the backing
1736         // store after moving the view into a window, until it times out and paints white. See <rdar://problem/9242771>.
1737         m_setCanStartMediaTimer.startOneShot(0);
1738         m_page->didMoveOnscreen();
1739     }
1740 }
1741
1742 void WebPage::didReceivePolicyDecision(uint64_t frameID, uint64_t listenerID, uint32_t policyAction, uint64_t downloadID)
1743 {
1744     WebFrame* frame = WebProcess::shared().webFrame(frameID);
1745     if (!frame)
1746         return;
1747     frame->didReceivePolicyDecision(listenerID, static_cast<PolicyAction>(policyAction), downloadID);
1748 }
1749
1750 void WebPage::show()
1751 {
1752     send(Messages::WebPageProxy::ShowPage());
1753 }
1754
1755 void WebPage::setUserAgent(const String& userAgent)
1756 {
1757     m_userAgent = userAgent;
1758 }
1759
1760 void WebPage::suspendActiveDOMObjectsAndAnimations()
1761 {
1762     m_page->suspendActiveDOMObjectsAndAnimations();
1763 }
1764
1765 void WebPage::resumeActiveDOMObjectsAndAnimations()
1766 {
1767     m_page->resumeActiveDOMObjectsAndAnimations();
1768
1769     // We need to repaint on resume to kickstart animated painting again.
1770     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize));
1771 }
1772
1773 IntPoint WebPage::screenToWindow(const IntPoint& point)
1774 {
1775     IntPoint windowPoint;
1776     sendSync(Messages::WebPageProxy::ScreenToWindow(point), Messages::WebPageProxy::ScreenToWindow::Reply(windowPoint));
1777     return windowPoint;
1778 }
1779     
1780 IntRect WebPage::windowToScreen(const IntRect& rect)
1781 {
1782     IntRect screenRect;
1783     sendSync(Messages::WebPageProxy::WindowToScreen(rect), Messages::WebPageProxy::WindowToScreen::Reply(screenRect));
1784     return screenRect;
1785 }
1786
1787 IntRect WebPage::windowResizerRect() const
1788 {
1789     if (m_windowResizerSize.isEmpty())
1790         return IntRect();
1791
1792     IntSize frameViewSize;
1793     if (Frame* coreFrame = m_mainFrame->coreFrame()) {
1794         if (FrameView* view = coreFrame->view())
1795             frameViewSize = view->size();
1796     }
1797
1798     return IntRect(frameViewSize.width() - m_windowResizerSize.width(), frameViewSize.height() - m_windowResizerSize.height(), 
1799                    m_windowResizerSize.width(), m_windowResizerSize.height());
1800 }
1801
1802 KeyboardUIMode WebPage::keyboardUIMode()
1803 {
1804     bool fullKeyboardAccessEnabled = WebProcess::shared().fullKeyboardAccessEnabled();
1805     return static_cast<KeyboardUIMode>((fullKeyboardAccessEnabled ? KeyboardAccessFull : KeyboardAccessDefault) | (m_tabToLinks ? KeyboardAccessTabsToLinks : 0));
1806 }
1807
1808 void WebPage::runJavaScriptInMainFrame(const String& script, uint64_t callbackID)
1809 {
1810     // NOTE: We need to be careful when running scripts that the objects we depend on don't
1811     // disappear during script execution.
1812
1813     // Retain the SerializedScriptValue at this level so it (and the internal data) lives
1814     // long enough for the DataReference to be encoded by the sent message.
1815     RefPtr<SerializedScriptValue> serializedResultValue;
1816     CoreIPC::DataReference dataReference;
1817
1818     JSLock lock(SilenceAssertionsOnly);
1819     if (JSValue resultValue = m_mainFrame->coreFrame()->script()->executeScript(script, true).jsValue()) {
1820         if ((serializedResultValue = SerializedScriptValue::create(m_mainFrame->jsContext(), toRef(m_mainFrame->coreFrame()->script()->globalObject(mainThreadNormalWorld())->globalExec(), resultValue), 0)))
1821             dataReference = serializedResultValue->data();
1822     }
1823
1824     send(Messages::WebPageProxy::ScriptValueCallback(dataReference, callbackID));
1825 }
1826
1827 void WebPage::getContentsAsString(uint64_t callbackID)
1828 {
1829     String resultString = m_mainFrame->contentsAsString();
1830     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1831 }
1832
1833 void WebPage::getRenderTreeExternalRepresentation(uint64_t callbackID)
1834 {
1835     String resultString = renderTreeExternalRepresentation();
1836     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1837 }
1838
1839 void WebPage::getSelectionOrContentsAsString(uint64_t callbackID)
1840 {
1841     String resultString = m_mainFrame->selectionAsString();
1842     if (resultString.isEmpty())
1843         resultString = m_mainFrame->contentsAsString();
1844     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1845 }
1846
1847 void WebPage::getSourceForFrame(uint64_t frameID, uint64_t callbackID)
1848 {
1849     String resultString;
1850     if (WebFrame* frame = WebProcess::shared().webFrame(frameID))
1851        resultString = frame->source();
1852
1853     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1854 }
1855
1856 void WebPage::getMainResourceDataOfFrame(uint64_t frameID, uint64_t callbackID)
1857 {
1858     CoreIPC::DataReference dataReference;
1859
1860     RefPtr<SharedBuffer> buffer;
1861     if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) {
1862         if (DocumentLoader* loader = frame->coreFrame()->loader()->documentLoader()) {
1863             if ((buffer = loader->mainResourceData()))
1864                 dataReference = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size());
1865         }
1866     }
1867
1868     send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
1869 }
1870
1871 static PassRefPtr<SharedBuffer> resourceDataForFrame(Frame* frame, const KURL& resourceURL)
1872 {
1873     DocumentLoader* loader = frame->loader()->documentLoader();
1874     if (!loader)
1875         return 0;
1876
1877     RefPtr<ArchiveResource> subresource = loader->subresource(resourceURL);
1878     if (!subresource)
1879         return 0;
1880
1881     return subresource->data();
1882 }
1883
1884 void WebPage::getResourceDataFromFrame(uint64_t frameID, const String& resourceURLString, uint64_t callbackID)
1885 {
1886     CoreIPC::DataReference dataReference;
1887     KURL resourceURL(KURL(), resourceURLString);
1888
1889     RefPtr<SharedBuffer> buffer;
1890     if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) {
1891         buffer = resourceDataForFrame(frame->coreFrame(), resourceURL);
1892         if (!buffer) {
1893             // Try to get the resource data from the cache.
1894             buffer = cachedResponseDataForURL(resourceURL);
1895         }
1896
1897         if (buffer)
1898             dataReference = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size());
1899     }
1900
1901     send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
1902 }
1903
1904 void WebPage::getWebArchiveOfFrame(uint64_t frameID, uint64_t callbackID)
1905 {
1906     CoreIPC::DataReference dataReference;
1907
1908 #if PLATFORM(MAC) || PLATFORM(WIN)
1909     RetainPtr<CFDataRef> data;
1910     if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) {
1911         if ((data = frame->webArchiveData(0, 0)))
1912             dataReference = CoreIPC::DataReference(CFDataGetBytePtr(data.get()), CFDataGetLength(data.get()));
1913     }
1914 #endif
1915
1916     send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
1917 }
1918
1919 void WebPage::forceRepaintWithoutCallback()
1920 {
1921     m_drawingArea->forceRepaint();
1922 }
1923
1924 void WebPage::forceRepaint(uint64_t callbackID)
1925 {
1926     if (m_drawingArea->forceRepaintAsync(callbackID))
1927         return;
1928
1929     forceRepaintWithoutCallback();
1930     send(Messages::WebPageProxy::VoidCallback(callbackID));
1931 }
1932
1933 #if ENABLE(WEB_INTENTS)
1934 void WebPage::deliverIntentToFrame(uint64_t frameID, const IntentData& intentData)
1935 {
1936     WebFrame* frame = WebProcess::shared().webFrame(frameID);
1937     if (!frame)
1938         return;
1939
1940     frame->deliverIntent(intentData);
1941 }
1942 #endif
1943
1944 void WebPage::preferencesDidChange(const WebPreferencesStore& store)
1945 {
1946     WebPreferencesStore::removeTestRunnerOverrides();
1947     updatePreferences(store);
1948 }
1949
1950 void WebPage::updatePreferences(const WebPreferencesStore& store)
1951 {
1952     Settings* settings = m_page->settings();
1953
1954     m_tabToLinks = store.getBoolValueForKey(WebPreferencesKey::tabsToLinksKey());
1955
1956     // FIXME: This should be generated from macro expansion for all preferences,
1957     // but we currently don't match the naming of WebCore exactly so we are
1958     // handrolling the boolean and integer preferences until that is fixed.
1959
1960 #define INITIALIZE_SETTINGS(KeyUpper, KeyLower, TypeName, Type, DefaultValue) settings->set##KeyUpper(store.get##TypeName##ValueForKey(WebPreferencesKey::KeyLower##Key()));
1961
1962     FOR_EACH_WEBKIT_STRING_PREFERENCE(INITIALIZE_SETTINGS)
1963
1964 #undef INITIALIZE_SETTINGS
1965
1966     settings->setScriptEnabled(store.getBoolValueForKey(WebPreferencesKey::javaScriptEnabledKey()));
1967     settings->setLoadsImagesAutomatically(store.getBoolValueForKey(WebPreferencesKey::loadsImagesAutomaticallyKey()));
1968     settings->setLoadsSiteIconsIgnoringImageLoadingSetting(store.getBoolValueForKey(WebPreferencesKey::loadsSiteIconsIgnoringImageLoadingPreferenceKey()));
1969     settings->setPluginsEnabled(store.getBoolValueForKey(WebPreferencesKey::pluginsEnabledKey()));
1970     settings->setJavaEnabled(store.getBoolValueForKey(WebPreferencesKey::javaEnabledKey()));
1971     settings->setJavaEnabledForLocalFiles(store.getBoolValueForKey(WebPreferencesKey::javaEnabledForLocalFilesKey()));    
1972     settings->setOfflineWebApplicationCacheEnabled(store.getBoolValueForKey(WebPreferencesKey::offlineWebApplicationCacheEnabledKey()));
1973     settings->setLocalStorageEnabled(store.getBoolValueForKey(WebPreferencesKey::localStorageEnabledKey()));
1974     settings->setXSSAuditorEnabled(store.getBoolValueForKey(WebPreferencesKey::xssAuditorEnabledKey()));
1975     settings->setFrameFlatteningEnabled(store.getBoolValueForKey(WebPreferencesKey::frameFlatteningEnabledKey()));
1976     settings->setPrivateBrowsingEnabled(store.getBoolValueForKey(WebPreferencesKey::privateBrowsingEnabledKey()));
1977     settings->setDeveloperExtrasEnabled(store.getBoolValueForKey(WebPreferencesKey::developerExtrasEnabledKey()));
1978     settings->setJavaScriptExperimentsEnabled(store.getBoolValueForKey(WebPreferencesKey::javaScriptExperimentsEnabledKey()));
1979     settings->setTextAreasAreResizable(store.getBoolValueForKey(WebPreferencesKey::textAreasAreResizableKey()));
1980     settings->setNeedsSiteSpecificQuirks(store.getBoolValueForKey(WebPreferencesKey::needsSiteSpecificQuirksKey()));
1981     settings->setJavaScriptCanOpenWindowsAutomatically(store.getBoolValueForKey(WebPreferencesKey::javaScriptCanOpenWindowsAutomaticallyKey()));
1982     settings->setForceFTPDirectoryListings(store.getBoolValueForKey(WebPreferencesKey::forceFTPDirectoryListingsKey()));
1983     settings->setDNSPrefetchingEnabled(store.getBoolValueForKey(WebPreferencesKey::dnsPrefetchingEnabledKey()));
1984 #if ENABLE(WEB_ARCHIVE)
1985     settings->setWebArchiveDebugModeEnabled(store.getBoolValueForKey(WebPreferencesKey::webArchiveDebugModeEnabledKey()));
1986 #endif
1987     settings->setLocalFileContentSniffingEnabled(store.getBoolValueForKey(WebPreferencesKey::localFileContentSniffingEnabledKey()));
1988     settings->setUsesPageCache(store.getBoolValueForKey(WebPreferencesKey::usesPageCacheKey()));
1989     settings->setPageCacheSupportsPlugins(store.getBoolValueForKey(WebPreferencesKey::pageCacheSupportsPluginsKey()));
1990     settings->setAuthorAndUserStylesEnabled(store.getBoolValueForKey(WebPreferencesKey::authorAndUserStylesEnabledKey()));
1991     settings->setPaginateDuringLayoutEnabled(store.getBoolValueForKey(WebPreferencesKey::paginateDuringLayoutEnabledKey()));
1992     settings->setDOMPasteAllowed(store.getBoolValueForKey(WebPreferencesKey::domPasteAllowedKey()));
1993     settings->setJavaScriptCanAccessClipboard(store.getBoolValueForKey(WebPreferencesKey::javaScriptCanAccessClipboardKey()));
1994     settings->setShouldPrintBackgrounds(store.getBoolValueForKey(WebPreferencesKey::shouldPrintBackgroundsKey()));
1995     settings->setWebSecurityEnabled(store.getBoolValueForKey(WebPreferencesKey::webSecurityEnabledKey()));
1996     settings->setAllowUniversalAccessFromFileURLs(store.getBoolValueForKey(WebPreferencesKey::allowUniversalAccessFromFileURLsKey()));
1997     settings->setAllowFileAccessFromFileURLs(store.getBoolValueForKey(WebPreferencesKey::allowFileAccessFromFileURLsKey()));
1998
1999     settings->setMinimumFontSize(store.getUInt32ValueForKey(WebPreferencesKey::minimumFontSizeKey()));
2000     settings->setMinimumLogicalFontSize(store.getUInt32ValueForKey(WebPreferencesKey::minimumLogicalFontSizeKey()));
2001     settings->setDefaultFontSize(store.getUInt32ValueForKey(WebPreferencesKey::defaultFontSizeKey()));
2002     settings->setDefaultFixedFontSize(store.getUInt32ValueForKey(WebPreferencesKey::defaultFixedFontSizeKey()));
2003     settings->setLayoutFallbackWidth(store.getUInt32ValueForKey(WebPreferencesKey::layoutFallbackWidthKey()));
2004     settings->setDeviceWidth(store.getUInt32ValueForKey(WebPreferencesKey::deviceWidthKey()));
2005     settings->setDeviceHeight(store.getUInt32ValueForKey(WebPreferencesKey::deviceHeightKey()));
2006     settings->setEditableLinkBehavior(static_cast<WebCore::EditableLinkBehavior>(store.getUInt32ValueForKey(WebPreferencesKey::editableLinkBehaviorKey())));
2007     settings->setShowsToolTipOverTruncatedText(store.getBoolValueForKey(WebPreferencesKey::showsToolTipOverTruncatedTextKey()));
2008
2009     settings->setAcceleratedCompositingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedCompositingEnabledKey()) && LayerTreeHost::supportsAcceleratedCompositing());
2010     settings->setAcceleratedDrawingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedDrawingEnabledKey()) && LayerTreeHost::supportsAcceleratedCompositing());
2011     settings->setCanvasUsesAcceleratedDrawing(store.getBoolValueForKey(WebPreferencesKey::canvasUsesAcceleratedDrawingKey()) && LayerTreeHost::supportsAcceleratedCompositing());
2012     settings->setShowDebugBorders(store.getBoolValueForKey(WebPreferencesKey::compositingBordersVisibleKey()));
2013     settings->setShowRepaintCounter(store.getBoolValueForKey(WebPreferencesKey::compositingRepaintCountersVisibleKey()));
2014     settings->setCSSCustomFilterEnabled(store.getBoolValueForKey(WebPreferencesKey::cssCustomFilterEnabledKey()));
2015     settings->setCSSRegionsEnabled(store.getBoolValueForKey(WebPreferencesKey::cssRegionsEnabledKey()));
2016     settings->setCSSGridLayoutEnabled(store.getBoolValueForKey(WebPreferencesKey::cssGridLayoutEnabledKey()));
2017     settings->setRegionBasedColumnsEnabled(store.getBoolValueForKey(WebPreferencesKey::regionBasedColumnsEnabledKey()));
2018     settings->setWebGLEnabled(store.getBoolValueForKey(WebPreferencesKey::webGLEnabledKey()));
2019     settings->setMediaPlaybackRequiresUserGesture(store.getBoolValueForKey(WebPreferencesKey::mediaPlaybackRequiresUserGestureKey()));
2020     settings->setMediaPlaybackAllowsInline(store.getBoolValueForKey(WebPreferencesKey::mediaPlaybackAllowsInlineKey()));
2021     settings->setMockScrollbarsEnabled(store.getBoolValueForKey(WebPreferencesKey::mockScrollbarsEnabledKey()));
2022     settings->setHyperlinkAuditingEnabled(store.getBoolValueForKey(WebPreferencesKey::hyperlinkAuditingEnabledKey()));
2023     settings->setRequestAnimationFrameEnabled(store.getBoolValueForKey(WebPreferencesKey::requestAnimationFrameEnabledKey()));
2024
2025     // <rdar://problem/10697417>: It is necessary to force compositing when accelerate drawing
2026     // is enabled on Mac so that scrollbars are always in their own layers.
2027 #if PLATFORM(MAC)
2028     if (settings->acceleratedDrawingEnabled())
2029         settings->setForceCompositingMode(LayerTreeHost::supportsAcceleratedCompositing());
2030     else
2031 #endif
2032         settings->setForceCompositingMode(store.getBoolValueForKey(WebPreferencesKey::forceCompositingModeKey()) && LayerTreeHost::supportsAcceleratedCompositing());
2033
2034 #if ENABLE(SQL_DATABASE)
2035     AbstractDatabase::setIsAvailable(store.getBoolValueForKey(WebPreferencesKey::databasesEnabledKey()));
2036 #endif
2037
2038 #if ENABLE(FULLSCREEN_API)
2039     settings->setFullScreenEnabled(store.getBoolValueForKey(WebPreferencesKey::fullScreenEnabledKey()));
2040 #endif
2041
2042     settings->setLocalStorageDatabasePath(WebProcess::shared().localStorageDirectory());
2043
2044 #if USE(AVFOUNDATION)
2045     settings->setAVFoundationEnabled(store.getBoolValueForKey(WebPreferencesKey::isAVFoundationEnabledKey()));
2046 #endif
2047
2048 #if ENABLE(WEB_SOCKETS)
2049     settings->setUseHixie76WebSocketProtocol(store.getBoolValueForKey(WebPreferencesKey::hixie76WebSocketProtocolEnabledKey()));
2050 #endif
2051
2052 #if ENABLE(WEB_AUDIO)
2053     settings->setWebAudioEnabled(store.getBoolValueForKey(WebPreferencesKey::webAudioEnabledKey()));
2054 #endif
2055
2056     settings->setApplicationChromeMode(store.getBoolValueForKey(WebPreferencesKey::applicationChromeModeKey()));
2057     settings->setSuppressesIncrementalRendering(store.getBoolValueForKey(WebPreferencesKey::suppressesIncrementalRenderingKey()));
2058     settings->setBackspaceKeyNavigationEnabled(store.getBoolValueForKey(WebPreferencesKey::backspaceKeyNavigationEnabledKey()));
2059     settings->setWantsBalancedSetDefersLoadingBehavior(store.getBoolValueForKey(WebPreferencesKey::wantsBalancedSetDefersLoadingBehaviorKey()));
2060     settings->setCaretBrowsingEnabled(store.getBoolValueForKey(WebPreferencesKey::caretBrowsingEnabledKey()));
2061
2062 #if ENABLE(VIDEO_TRACK)
2063     settings->setShouldDisplaySubtitles(store.getBoolValueForKey(WebPreferencesKey::shouldDisplaySubtitlesKey()));
2064     settings->setShouldDisplayCaptions(store.getBoolValueForKey(WebPreferencesKey::shouldDisplayCaptionsKey()));
2065     settings->setShouldDisplayTextDescriptions(store.getBoolValueForKey(WebPreferencesKey::shouldDisplayTextDescriptionsKey()));
2066 #endif
2067
2068 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
2069     settings->setNotificationsEnabled(store.getBoolValueForKey(WebPreferencesKey::notificationsEnabledKey()));
2070 #endif
2071
2072     settings->setShouldRespectImageOrientation(store.getBoolValueForKey(WebPreferencesKey::shouldRespectImageOrientationKey()));
2073
2074     platformPreferencesDidChange(store);
2075
2076     if (m_drawingArea)
2077         m_drawingArea->updatePreferences();
2078 }
2079
2080 #if ENABLE(INSPECTOR)
2081 WebInspector* WebPage::inspector()
2082 {
2083     if (m_isClosed)
2084         return 0;
2085     if (!m_inspector)
2086         m_inspector = WebInspector::create(this);
2087     return m_inspector.get();
2088 }
2089 #endif
2090
2091 #if ENABLE(FULLSCREEN_API)
2092 WebFullScreenManager* WebPage::fullScreenManager()
2093 {
2094     if (!m_fullScreenManager)
2095         m_fullScreenManager = WebFullScreenManager::create(this);
2096     return m_fullScreenManager.get();
2097 }
2098 #endif
2099
2100 NotificationPermissionRequestManager* WebPage::notificationPermissionRequestManager()
2101 {
2102     if (m_notificationPermissionRequestManager)
2103         return m_notificationPermissionRequestManager.get();
2104
2105     m_notificationPermissionRequestManager = NotificationPermissionRequestManager::create(this);
2106     return m_notificationPermissionRequestManager.get();
2107 }
2108
2109 #if !PLATFORM(GTK) && !PLATFORM(MAC)
2110 bool WebPage::handleEditingKeyboardEvent(KeyboardEvent* evt)
2111 {
2112     Node* node = evt->target()->toNode();
2113     ASSERT(node);
2114     Frame* frame = node->document()->frame();
2115     ASSERT(frame);
2116
2117     const PlatformKeyboardEvent* keyEvent = evt->keyEvent();
2118     if (!keyEvent)
2119         return false;
2120
2121     Editor::Command command = frame->editor()->command(interpretKeyEvent(evt));
2122
2123     if (keyEvent->type() == PlatformEvent::RawKeyDown) {
2124         // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated,
2125         // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated
2126         // (e.g. Tab that inserts a Tab character, or Enter).
2127         return !command.isTextInsertion() && command.execute(evt);
2128     }
2129
2130     if (command.execute(evt))
2131         return true;
2132
2133     // Don't insert null or control characters as they can result in unexpected behaviour
2134     if (evt->charCode() < ' ')
2135         return false;
2136
2137     return frame->editor()->insertText(evt->keyEvent()->text(), evt);
2138 }
2139 #endif
2140
2141 #if ENABLE(DRAG_SUPPORT)
2142
2143 #if PLATFORM(WIN)
2144 void WebPage::performDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, const WebCore::DragDataMap& dataMap, uint32_t flags)
2145 {
2146     if (!m_page) {
2147         send(Messages::WebPageProxy::DidPerformDragControllerAction(WebCore::DragSession()));
2148         return;
2149     }
2150
2151     DragData dragData(dataMap, clientPosition, globalPosition, static_cast<DragOperation>(draggingSourceOperationMask), static_cast<DragApplicationFlags>(flags));
2152     switch (action) {
2153     case DragControllerActionEntered:
2154         send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragEntered(&dragData)));
2155         break;
2156
2157     case DragControllerActionUpdated:
2158         send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragUpdated(&dragData)));
2159         break;
2160         
2161     case DragControllerActionExited:
2162         m_page->dragController()->dragExited(&dragData);
2163         break;
2164         
2165     case DragControllerActionPerformDrag:
2166         m_page->dragController()->performDrag(&dragData);
2167         break;
2168         
2169     default:
2170         ASSERT_NOT_REACHED();
2171     }
2172 }
2173
2174 #elif PLATFORM(QT) || PLATFORM(GTK)
2175 void WebPage::performDragControllerAction(uint64_t action, WebCore::DragData dragData)
2176 {
2177     if (!m_page) {
2178         send(Messages::WebPageProxy::DidPerformDragControllerAction(WebCore::DragSession()));
2179 #if PLATFORM(QT)
2180         QMimeData* data = const_cast<QMimeData*>(dragData.platformData());
2181         delete data;
2182 #elif PLATFORM(GTK)
2183         DataObjectGtk* data = const_cast<DataObjectGtk*>(dragData.platformData());
2184         data->deref();
2185 #endif
2186         return;
2187     }
2188
2189     switch (action) {
2190     case DragControllerActionEntered:
2191         send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragEntered(&dragData)));
2192         break;
2193
2194     case DragControllerActionUpdated:
2195         send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragUpdated(&dragData)));
2196         break;
2197
2198     case DragControllerActionExited:
2199         m_page->dragController()->dragExited(&dragData);
2200         break;
2201
2202     case DragControllerActionPerformDrag: {
2203         m_page->dragController()->performDrag(&dragData);
2204         break;
2205     }
2206
2207     default:
2208         ASSERT_NOT_REACHED();
2209     }
2210     // DragData does not delete its platformData so we need to do that here.
2211 #if PLATFORM(QT)
2212     QMimeData* data = const_cast<QMimeData*>(dragData.platformData());
2213     delete data;
2214 #elif PLATFORM(GTK)
2215     DataObjectGtk* data = const_cast<DataObjectGtk*>(dragData.platformData());
2216     data->deref();
2217 #endif
2218 }
2219
2220 #else
2221 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)
2222 {
2223     if (!m_page) {
2224         send(Messages::WebPageProxy::DidPerformDragControllerAction(WebCore::DragSession()));
2225         return;
2226     }
2227
2228     DragData dragData(dragStorageName, clientPosition, globalPosition, static_cast<DragOperation>(draggingSourceOperationMask), static_cast<DragApplicationFlags>(flags));
2229     switch (action) {
2230     case DragControllerActionEntered:
2231         send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragEntered(&dragData)));
2232         break;
2233
2234     case DragControllerActionUpdated:
2235         send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragUpdated(&dragData)));
2236         break;
2237         
2238     case DragControllerActionExited:
2239         m_page->dragController()->dragExited(&dragData);
2240         break;
2241         
2242     case DragControllerActionPerformDrag: {
2243         ASSERT(!m_pendingDropSandboxExtension);
2244
2245         m_pendingDropSandboxExtension = SandboxExtension::create(sandboxExtensionHandle);
2246         for (size_t i = 0; i < sandboxExtensionsHandleArray.size(); i++) {
2247             if (RefPtr<SandboxExtension> extension = SandboxExtension::create(sandboxExtensionsHandleArray[i]))
2248                 m_pendingDropExtensionsForFileUpload.append(extension);
2249         }
2250
2251         m_page->dragController()->performDrag(&dragData);
2252
2253         // If we started loading a local file, the sandbox extension tracker would have adopted this
2254         // pending drop sandbox extension. If not, we'll play it safe and invalidate it.
2255         if (m_pendingDropSandboxExtension) {
2256             m_pendingDropSandboxExtension->invalidate();
2257             m_pendingDropSandboxExtension = nullptr;
2258         }
2259         for (size_t i = 0; i < m_pendingDropExtensionsForFileUpload.size(); i++)
2260             m_pendingDropExtensionsForFileUpload[i]->invalidate();
2261
2262         m_pendingDropExtensionsForFileUpload.clear();
2263         break;
2264     }
2265
2266     default:
2267         ASSERT_NOT_REACHED();
2268     }
2269 }
2270 #endif
2271
2272 void WebPage::dragEnded(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t operation)
2273 {
2274     IntPoint adjustedClientPosition(clientPosition.x() + m_page->dragController()->dragOffset().x(), clientPosition.y() + m_page->dragController()->dragOffset().y());
2275     IntPoint adjustedGlobalPosition(globalPosition.x() + m_page->dragController()->dragOffset().x(), globalPosition.y() + m_page->dragController()->dragOffset().y());
2276
2277     m_page->dragController()->dragEnded();
2278     FrameView* view = m_page->mainFrame()->view();
2279     if (!view)
2280         return;
2281     // FIXME: These are fake modifier keys here, but they should be real ones instead.
2282     PlatformMouseEvent event(adjustedClientPosition, adjustedGlobalPosition, LeftButton, PlatformEvent::MouseMoved, 0, false, false, false, false, currentTime());
2283     m_page->mainFrame()->eventHandler()->dragSourceEndedAt(event, (DragOperation)operation);
2284 }
2285
2286 void WebPage::willPerformLoadDragDestinationAction()
2287 {
2288     m_sandboxExtensionTracker.willPerformLoadDragDestinationAction(m_pendingDropSandboxExtension.release());
2289 }
2290
2291 void WebPage::mayPerformUploadDragDestinationAction()
2292 {
2293     for (size_t i = 0; i < m_pendingDropExtensionsForFileUpload.size(); i++)
2294         m_pendingDropExtensionsForFileUpload[i]->consumePermanently();
2295     m_pendingDropExtensionsForFileUpload.clear();
2296 }
2297     
2298 #endif // ENABLE(DRAG_SUPPORT)
2299
2300 WebUndoStep* WebPage::webUndoStep(uint64_t stepID)
2301 {
2302     return m_undoStepMap.get(stepID).get();
2303 }
2304
2305 void WebPage::addWebUndoStep(uint64_t stepID, WebUndoStep* entry)
2306 {
2307     m_undoStepMap.set(stepID, entry);
2308 }
2309
2310 void WebPage::removeWebEditCommand(uint64_t stepID)
2311 {
2312     m_undoStepMap.remove(stepID);
2313 }
2314
2315 void WebPage::unapplyEditCommand(uint64_t stepID)
2316 {
2317     WebUndoStep* step = webUndoStep(stepID);
2318     if (!step)
2319         return;
2320
2321     step->step()->unapply();
2322 }
2323
2324 void WebPage::reapplyEditCommand(uint64_t stepID)
2325 {
2326     WebUndoStep* step = webUndoStep(stepID);
2327     if (!step)
2328         return;
2329
2330     m_isInRedo = true;
2331     step->step()->reapply();
2332     m_isInRedo = false;
2333 }
2334
2335 void WebPage::didRemoveEditCommand(uint64_t commandID)
2336 {
2337     removeWebEditCommand(commandID);
2338 }
2339
2340 void WebPage::setActivePopupMenu(WebPopupMenu* menu)
2341 {
2342     m_activePopupMenu = menu;
2343 }
2344
2345 #if ENABLE(INPUT_TYPE_COLOR)
2346 void WebPage::setActiveColorChooser(WebColorChooser* colorChooser)
2347 {
2348     m_activeColorChooser = colorChooser;
2349 }
2350
2351 void WebPage::didEndColorChooser()
2352 {
2353     m_activeColorChooser->didEndChooser();
2354 }
2355
2356 void WebPage::didChooseColor(const WebCore::Color& color)
2357 {
2358     m_activeColorChooser->didChooseColor(color);
2359 }
2360 #endif
2361
2362 void WebPage::setActiveOpenPanelResultListener(PassRefPtr<WebOpenPanelResultListener> openPanelResultListener)
2363 {
2364     m_activeOpenPanelResultListener = openPanelResultListener;
2365 }
2366
2367 bool WebPage::findStringFromInjectedBundle(const String& target, FindOptions options)
2368 {
2369     return m_page->findString(target, options);
2370 }
2371
2372 void WebPage::findString(const String& string, uint32_t options, uint32_t maxMatchCount)
2373 {
2374     m_findController.findString(string, static_cast<FindOptions>(options), maxMatchCount);
2375 }
2376
2377 void WebPage::hideFindUI()
2378 {
2379     m_findController.hideFindUI();
2380 }
2381
2382 void WebPage::countStringMatches(const String& string, uint32_t options, uint32_t maxMatchCount)
2383 {
2384     m_findController.countStringMatches(string, static_cast<FindOptions>(options), maxMatchCount);
2385 }
2386
2387 void WebPage::didChangeSelectedIndexForActivePopupMenu(int32_t newIndex)
2388 {
2389     if (!m_activePopupMenu)
2390         return;
2391
2392     m_activePopupMenu->didChangeSelectedIndex(newIndex);
2393     m_activePopupMenu = 0;
2394 }
2395
2396 void WebPage::didChooseFilesForOpenPanel(const Vector<String>& files)
2397 {
2398     if (!m_activeOpenPanelResultListener)
2399         return;
2400
2401     m_activeOpenPanelResultListener->didChooseFiles(files);
2402     m_activeOpenPanelResultListener = 0;
2403 }
2404
2405 void WebPage::didCancelForOpenPanel()
2406 {
2407     m_activeOpenPanelResultListener = 0;
2408 }
2409
2410 #if ENABLE(WEB_PROCESS_SANDBOX)
2411 void WebPage::extendSandboxForFileFromOpenPanel(const SandboxExtension::Handle& handle)
2412 {
2413     SandboxExtension::create(handle)->consumePermanently();
2414 }
2415 #endif
2416
2417 #if ENABLE(GEOLOCATION)
2418 void WebPage::didReceiveGeolocationPermissionDecision(uint64_t geolocationID, bool allowed)
2419 {
2420     m_geolocationPermissionRequestManager.didReceiveGeolocationPermissionDecision(geolocationID, allowed);
2421 }
2422 #endif
2423
2424 void WebPage::didReceiveNotificationPermissionDecision(uint64_t notificationID, bool allowed)
2425 {
2426     notificationPermissionRequestManager()->didReceiveNotificationPermissionDecision(notificationID, allowed);
2427 }
2428
2429 void WebPage::advanceToNextMisspelling(bool startBeforeSelection)
2430 {
2431     Frame* frame = m_page->focusController()->focusedOrMainFrame();
2432     frame->editor()->advanceToNextMisspelling(startBeforeSelection);
2433 }
2434
2435 void WebPage::changeSpellingToWord(const String& word)
2436 {
2437     replaceSelectionWithText(m_page->focusController()->focusedOrMainFrame(), word);
2438 }
2439
2440 void WebPage::unmarkAllMisspellings()
2441 {
2442     for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
2443         if (Document* document = frame->document())
2444             document->markers()->removeMarkers(DocumentMarker::Spelling);
2445     }
2446 }
2447
2448 void WebPage::unmarkAllBadGrammar()
2449 {
2450     for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
2451         if (Document* document = frame->document())
2452             document->markers()->removeMarkers(DocumentMarker::Grammar);
2453     }
2454 }
2455
2456 #if USE(APPKIT)
2457 void WebPage::uppercaseWord()
2458 {
2459     m_page->focusController()->focusedOrMainFrame()->editor()->uppercaseWord();
2460 }
2461
2462 void WebPage::lowercaseWord()
2463 {
2464     m_page->focusController()->focusedOrMainFrame()->editor()->lowercaseWord();
2465 }
2466
2467 void WebPage::capitalizeWord()
2468 {
2469     m_page->focusController()->focusedOrMainFrame()->editor()->capitalizeWord();
2470 }
2471 #endif
2472     
2473 void WebPage::setTextForActivePopupMenu(int32_t index)
2474 {
2475     if (!m_activePopupMenu)
2476         return;
2477
2478     m_activePopupMenu->setTextForIndex(index);
2479 }
2480
2481 #if PLATFORM(GTK)
2482 void WebPage::failedToShowPopupMenu()
2483 {
2484     if (!m_activePopupMenu)
2485         return;
2486
2487     m_activePopupMenu->client()->popupDidHide();
2488 }
2489 #endif
2490
2491 #if ENABLE(CONTEXT_MENUS)
2492 void WebPage::didSelectItemFromActiveContextMenu(const WebContextMenuItemData& item)
2493 {
2494     if (!m_contextMenu)
2495         return;
2496
2497     m_contextMenu->itemSelected(item);
2498     m_contextMenu = 0;
2499 }
2500 #endif
2501
2502 void WebPage::replaceSelectionWithText(Frame* frame, const String& text)
2503 {
2504     bool selectReplacement = true;
2505     bool smartReplace = false;
2506     return frame->editor()->replaceSelectionWithText(text, selectReplacement, smartReplace);
2507 }
2508
2509 void WebPage::clearSelection()
2510 {
2511     m_page->focusController()->focusedOrMainFrame()->selection()->clear();
2512 }
2513
2514 bool WebPage::mainFrameHasCustomRepresentation() const
2515 {
2516     if (Frame* frame = mainFrame())
2517         return static_cast<WebFrameLoaderClient*>(frame->loader()->client())->frameHasCustomRepresentation();
2518
2519     return false;
2520 }
2521
2522 void WebPage::didChangeScrollOffsetForMainFrame()
2523 {
2524     Frame* frame = m_page->mainFrame();
2525     IntPoint scrollPosition = frame->view()->scrollPosition();
2526     IntPoint maximumScrollPosition = frame->view()->maximumScrollPosition();
2527     IntPoint minimumScrollPosition = frame->view()->minimumScrollPosition();
2528
2529     bool isPinnedToLeftSide = (scrollPosition.x() <= minimumScrollPosition.x());
2530     bool isPinnedToRightSide = (scrollPosition.x() >= maximumScrollPosition.x());
2531
2532     if (isPinnedToLeftSide != m_cachedMainFrameIsPinnedToLeftSide || isPinnedToRightSide != m_cachedMainFrameIsPinnedToRightSide) {
2533         send(Messages::WebPageProxy::DidChangeScrollOffsetPinningForMainFrame(isPinnedToLeftSide, isPinnedToRightSide));
2534         
2535         m_cachedMainFrameIsPinnedToLeftSide = isPinnedToLeftSide;
2536         m_cachedMainFrameIsPinnedToRightSide = isPinnedToRightSide;
2537     }
2538 }
2539
2540 void WebPage::mainFrameDidLayout()
2541 {
2542     unsigned pageCount = m_page->pageCount();
2543     if (pageCount != m_cachedPageCount) {
2544         send(Messages::WebPageProxy::DidChangePageCount(pageCount));
2545         m_cachedPageCount = pageCount;
2546     }
2547 }
2548
2549 void WebPage::addPluginView(PluginView* pluginView)
2550 {
2551     ASSERT(!m_pluginViews.contains(pluginView));
2552
2553     m_pluginViews.add(pluginView);
2554 }
2555
2556 void WebPage::removePluginView(PluginView* pluginView)
2557 {
2558     ASSERT(m_pluginViews.contains(pluginView));
2559
2560     m_pluginViews.remove(pluginView);
2561 }
2562
2563 #if PLATFORM(MAC)
2564 void WebPage::setWindowIsVisible(bool windowIsVisible)
2565 {
2566     m_windowIsVisible = windowIsVisible;
2567
2568     corePage()->focusController()->setContainingWindowIsVisible(windowIsVisible);
2569
2570     // Tell all our plug-in views that the window visibility changed.
2571     for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
2572         (*it)->setWindowIsVisible(windowIsVisible);
2573 }
2574
2575 void WebPage::windowAndViewFramesChanged(const WebCore::IntRect& windowFrameInScreenCoordinates, const WebCore::IntRect& viewFrameInWindowCoordinates, const WebCore::IntPoint& accessibilityViewCoordinates)
2576 {
2577     m_windowFrameInScreenCoordinates = windowFrameInScreenCoordinates;
2578     m_viewFrameInWindowCoordinates = viewFrameInWindowCoordinates;
2579     m_accessibilityPosition = accessibilityViewCoordinates;
2580     
2581     // Tell all our plug-in views that the window and view frames have changed.
2582     for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
2583         (*it)->windowAndViewFramesChanged(windowFrameInScreenCoordinates, viewFrameInWindowCoordinates);
2584 }
2585 #endif
2586
2587 bool WebPage::windowIsFocused() const
2588 {
2589     return m_page->focusController()->isActive();
2590 }
2591
2592 bool WebPage::windowAndWebPageAreFocused() const
2593 {
2594 #if PLATFORM(MAC)
2595     if (!m_windowIsVisible)
2596         return false;
2597 #endif
2598     return m_page->focusController()->isFocused() && m_page->focusController()->isActive();
2599 }
2600
2601 void WebPage::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
2602 {
2603     if (messageID.is<CoreIPC::MessageClassDrawingArea>()) {
2604         if (m_drawingArea)
2605             m_drawingArea->didReceiveDrawingAreaMessage(connection, messageID, arguments);
2606         return;
2607     }
2608
2609 #if USE(TILED_BACKING_STORE) && USE(ACCELERATED_COMPOSITING)
2610     if (messageID.is<CoreIPC::MessageClassLayerTreeHost>()) {
2611         if (m_drawingArea)
2612             m_drawingArea->didReceiveLayerTreeHostMessage(connection, messageID, arguments);
2613         return;
2614     }
2615 #endif
2616     
2617 #if ENABLE(INSPECTOR)
2618     if (messageID.is<CoreIPC::MessageClassWebInspector>()) {
2619         if (WebInspector* inspector = this->inspector())
2620             inspector->didReceiveWebInspectorMessage(connection, messageID, arguments);
2621         return;
2622     }
2623 #endif
2624
2625 #if ENABLE(FULLSCREEN_API)
2626     if (messageID.is<CoreIPC::MessageClassWebFullScreenManager>()) {
2627         fullScreenManager()->didReceiveMessage(connection, messageID, arguments);
2628         return;
2629     }
2630 #endif
2631
2632     didReceiveWebPageMessage(connection, messageID, arguments);
2633 }
2634
2635 void WebPage::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments, OwnPtr<CoreIPC::ArgumentEncoder>& reply)
2636 {   
2637     didReceiveSyncWebPageMessage(connection, messageID, arguments, reply);
2638 }
2639     
2640 InjectedBundleBackForwardList* WebPage::backForwardList()
2641 {
2642     if (!m_backForwardList)
2643         m_backForwardList = InjectedBundleBackForwardList::create(this);
2644     return m_backForwardList.get();
2645 }
2646
2647 #if PLATFORM(QT)
2648 #if ENABLE(TOUCH_ADJUSTMENT)
2649 void WebPage::findZoomableAreaForPoint(const WebCore::IntPoint& point, const WebCore::IntSize& area)
2650 {
2651     Node* node = 0;
2652     IntRect zoomableArea;
2653     bool foundAreaForTouchPoint = m_mainFrame->coreFrame()->eventHandler()->bestZoomableAreaForTouchPoint(point, IntSize(area.width() / 2, area.height() / 2), zoomableArea, node);
2654     ASSERT(node);
2655
2656     if (!foundAreaForTouchPoint)
2657         return;
2658
2659     if (node->document() && node->document()->view())
2660         zoomableArea = node->document()->view()->contentsToWindow(zoomableArea);
2661
2662     send(Messages::WebPageProxy::DidFindZoomableArea(point, zoomableArea));
2663 }
2664
2665 #else
2666 void WebPage::findZoomableAreaForPoint(const WebCore::IntPoint& point, const WebCore::IntSize& area)
2667 {
2668     UNUSED_PARAM(area);
2669     Frame* mainframe = m_mainFrame->coreFrame();
2670     HitTestResult result = mainframe->eventHandler()->hitTestResultAtPoint(mainframe->view()->windowToContents(point), /*allowShadowContent*/ false, /*ignoreClipping*/ true);
2671
2672     Node* node = result.innerNode();
2673
2674     if (!node)
2675         return;
2676
2677     IntRect zoomableArea = node->getRect();
2678
2679     while (true) {
2680         bool found = !node->isTextNode() && !node->isShadowRoot();
2681
2682         // No candidate found, bail out.
2683         if (!found && !node->parentNode())
2684             return;
2685
2686         // Candidate found, and it is a better candidate than its parent.
2687         // NB: A parent is considered a better candidate iff the node is
2688         // contained by it and it is the only child.
2689         if (found && (!node->parentNode() || node->parentNode()->childNodeCount() != 1))
2690             break;
2691
2692         node = node->parentNode();
2693         zoomableArea.unite(node->getRect());
2694     }
2695
2696     if (node->document() && node->document()->frame() && node->document()->frame()->view()) {
2697         const ScrollView* view = node->document()->frame()->view();
2698         zoomableArea = view->contentsToWindow(zoomableArea);
2699     }
2700
2701     send(Messages::WebPageProxy::DidFindZoomableArea(point, zoomableArea));
2702 }
2703 #endif
2704 #endif
2705
2706 WebPage::SandboxExtensionTracker::~SandboxExtensionTracker()
2707 {
2708     invalidate();
2709 }
2710
2711 void WebPage::SandboxExtensionTracker::invalidate()
2712 {
2713     if (m_pendingProvisionalSandboxExtension) {
2714         m_pendingProvisionalSandboxExtension->invalidate();
2715         m_pendingProvisionalSandboxExtension = 0;
2716     }
2717
2718     if (m_provisionalSandboxExtension) {
2719         m_provisionalSandboxExtension->invalidate();
2720         m_provisionalSandboxExtension = 0;
2721     }
2722
2723     if (m_committedSandboxExtension) {
2724         m_committedSandboxExtension->invalidate();
2725         m_committedSandboxExtension = 0;
2726     }
2727 }
2728
2729 void WebPage::SandboxExtensionTracker::willPerformLoadDragDestinationAction(PassRefPtr<SandboxExtension> pendingDropSandboxExtension)
2730 {
2731     setPendingProvisionalSandboxExtension(pendingDropSandboxExtension);
2732 }
2733
2734 void WebPage::SandboxExtensionTracker::beginLoad(WebFrame* frame, const SandboxExtension::Handle& handle)
2735 {
2736     ASSERT(frame->isMainFrame());
2737
2738     setPendingProvisionalSandboxExtension(SandboxExtension::create(handle));
2739 }
2740
2741 void WebPage::SandboxExtensionTracker::setPendingProvisionalSandboxExtension(PassRefPtr<SandboxExtension> pendingProvisionalSandboxExtension)
2742 {
2743     // If we get two beginLoad calls in succession, without a provisional load starting, then
2744     // m_pendingProvisionalSandboxExtension will be non-null. Invalidate and null out the extension if that is the case.
2745     if (m_pendingProvisionalSandboxExtension) {
2746         m_pendingProvisionalSandboxExtension->invalidate();
2747         m_pendingProvisionalSandboxExtension = nullptr;
2748     }
2749     
2750     m_pendingProvisionalSandboxExtension = pendingProvisionalSandboxExtension;    
2751 }
2752
2753 static bool shouldReuseCommittedSandboxExtension(WebFrame* frame)
2754 {
2755     ASSERT(frame->isMainFrame());
2756
2757     FrameLoader* frameLoader = frame->coreFrame()->loader();
2758     FrameLoadType frameLoadType = frameLoader->loadType();
2759
2760     // If the page is being reloaded, it should reuse whatever extension is committed.
2761     if (frameLoadType == FrameLoadTypeReload || frameLoadType == FrameLoadTypeReloadFromOrigin)
2762         return true;
2763
2764     DocumentLoader* documentLoader = frameLoader->documentLoader();
2765     DocumentLoader* provisionalDocumentLoader = frameLoader->provisionalDocumentLoader();
2766     if (!documentLoader || !provisionalDocumentLoader)
2767         return false;
2768
2769     if (documentLoader->url().isLocalFile() && provisionalDocumentLoader->url().isLocalFile())
2770         return true;
2771
2772     return false;
2773 }
2774
2775 void WebPage::SandboxExtensionTracker::didStartProvisionalLoad(WebFrame* frame)
2776 {
2777     if (!frame->isMainFrame())
2778         return;
2779
2780     // We should only reuse the commited sandbox extension if it is not null. It can be
2781     // null if the last load was for an error page.
2782     if (m_committedSandboxExtension && shouldReuseCommittedSandboxExtension(frame)) {
2783         m_pendingProvisionalSandboxExtension = m_committedSandboxExtension.release();
2784         ASSERT(!m_committedSandboxExtension);
2785     }
2786
2787     ASSERT(!m_provisionalSandboxExtension);
2788
2789     m_provisionalSandboxExtension = m_pendingProvisionalSandboxExtension.release();
2790     if (!m_provisionalSandboxExtension)
2791         return;
2792
2793     m_provisionalSandboxExtension->consume();
2794 }
2795
2796 void WebPage::SandboxExtensionTracker::didCommitProvisionalLoad(WebFrame* frame)
2797 {
2798     if (!frame->isMainFrame())
2799         return;
2800
2801     // Generally, there should be no pending extension at this stage, but we can have one if UI process
2802     // has an out of date idea of WebProcess state, and initiates a load or reload without stopping an existing one.
2803     if (m_pendingProvisionalSandboxExtension) {
2804         m_pendingProvisionalSandboxExtension->invalidate();
2805         m_pendingProvisionalSandboxExtension = nullptr;
2806     }
2807
2808     // The provisional load has been committed. Invalidate the currently committed sandbox
2809     // extension and make the provisional sandbox extension the committed sandbox extension.
2810     if (m_committedSandboxExtension)
2811         m_committedSandboxExtension->invalidate();
2812
2813     m_committedSandboxExtension = m_provisionalSandboxExtension.release();
2814 }
2815
2816 void WebPage::SandboxExtensionTracker::didFailProvisionalLoad(WebFrame* frame)
2817 {
2818     if (!frame->isMainFrame())
2819         return;
2820
2821     // Generally, there should be no pending extension at this stage, but we can have one if UI process
2822     // has an out of date idea of WebProcess state, and initiates a load or reload without stopping an existing one.
2823     if (m_pendingProvisionalSandboxExtension) {
2824         m_pendingProvisionalSandboxExtension->invalidate();
2825         m_pendingProvisionalSandboxExtension = nullptr;
2826     }
2827
2828     if (!m_provisionalSandboxExtension)
2829         return;
2830
2831     m_provisionalSandboxExtension->invalidate();
2832     m_provisionalSandboxExtension = nullptr;
2833 }
2834
2835 bool WebPage::hasLocalDataForURL(const KURL& url)
2836 {
2837     if (url.isLocalFile())
2838         return true;
2839
2840     FrameLoader* frameLoader = m_page->mainFrame()->loader();
2841     DocumentLoader* documentLoader = frameLoader ? frameLoader->documentLoader() : 0;
2842     if (documentLoader && documentLoader->subresource(url))
2843         return true;
2844
2845     return platformHasLocalDataForURL(url);
2846 }
2847
2848 void WebPage::setCustomTextEncodingName(const String& encoding)
2849 {
2850     m_page->mainFrame()->loader()->reloadWithOverrideEncoding(encoding);
2851 }
2852
2853 void WebPage::didRemoveBackForwardItem(uint64_t itemID)
2854 {
2855     WebBackForwardListProxy::removeItem(itemID);
2856 }
2857
2858 #if PLATFORM(MAC)
2859
2860 bool WebPage::isSpeaking()
2861 {
2862     bool result;
2863     return sendSync(Messages::WebPageProxy::GetIsSpeaking(), Messages::WebPageProxy::GetIsSpeaking::Reply(result)) && result;
2864 }
2865
2866 void WebPage::speak(const String& string)
2867 {
2868     send(Messages::WebPageProxy::Speak(string));
2869 }
2870
2871 void WebPage::stopSpeaking()
2872 {
2873     send(Messages::WebPageProxy::StopSpeaking());
2874 }
2875
2876 #endif
2877
2878 #if PLATFORM(MAC)
2879 RetainPtr<PDFDocument> WebPage::pdfDocumentForPrintingFrame(Frame* coreFrame)
2880 {
2881     Document* document = coreFrame->document();
2882     if (!document)
2883         return 0;
2884
2885     if (!document->isPluginDocument())
2886         return 0;
2887
2888     PluginView* pluginView = static_cast<PluginView*>(toPluginDocument(document)->pluginWidget());
2889     if (!pluginView)
2890         return 0;
2891
2892     return pluginView->pdfDocumentForPrinting();
2893 }
2894 #endif // PLATFORM(MAC)
2895
2896 void WebPage::beginPrinting(uint64_t frameID, const PrintInfo& printInfo)
2897 {
2898     WebFrame* frame = WebProcess::shared().webFrame(frameID);
2899     if (!frame)
2900         return;
2901
2902     Frame* coreFrame = frame->coreFrame();
2903     if (!coreFrame)
2904         return;
2905
2906 #if PLATFORM(MAC)
2907     if (pdfDocumentForPrintingFrame(coreFrame))
2908         return;
2909 #endif // PLATFORM(MAC)
2910
2911     if (!m_printContext)
2912         m_printContext = adoptPtr(new PrintContext(coreFrame));
2913
2914     drawingArea()->setLayerTreeStateIsFrozen(true);
2915     m_printContext->begin(printInfo.availablePaperWidth, printInfo.availablePaperHeight);
2916
2917     float fullPageHeight;
2918     m_printContext->computePageRects(FloatRect(0, 0, printInfo.availablePaperWidth, printInfo.availablePaperHeight), 0, 0, printInfo.pageSetupScaleFactor, fullPageHeight, true);
2919
2920 #if PLATFORM(GTK)
2921     if (!m_printOperation)
2922         m_printOperation = WebPrintOperationGtk::create(this, printInfo);
2923 #endif
2924 }
2925
2926 void WebPage::endPrinting()
2927 {
2928     drawingArea()->setLayerTreeStateIsFrozen(false);
2929 #if PLATFORM(GTK)
2930     m_printOperation = 0;
2931 #endif
2932     m_printContext = nullptr;
2933 }
2934
2935 void WebPage::computePagesForPrinting(uint64_t frameID, const PrintInfo& printInfo, uint64_t callbackID)
2936 {
2937     Vector<IntRect> resultPageRects;
2938     double resultTotalScaleFactorForPrinting = 1;
2939
2940     beginPrinting(frameID, printInfo);
2941
2942     if (m_printContext) {
2943         resultPageRects = m_printContext->pageRects();
2944         resultTotalScaleFactorForPrinting = m_printContext->computeAutomaticScaleFactor(FloatSize(printInfo.availablePaperWidth, printInfo.availablePaperHeight)) * printInfo.pageSetupScaleFactor;
2945     }
2946 #if PLATFORM(MAC)
2947     else
2948         computePagesForPrintingPDFDocument(frameID, printInfo, resultPageRects);
2949 #endif // PLATFORM(MAC)
2950
2951     // If we're asked to print, we should actually print at least a blank page.
2952     if (resultPageRects.isEmpty())
2953         resultPageRects.append(IntRect(0, 0, 1, 1));
2954
2955     send(Messages::WebPageProxy::ComputedPagesCallback(resultPageRects, resultTotalScaleFactorForPrinting, callbackID));
2956 }
2957
2958 #if PLATFORM(MAC) || PLATFORM(WIN)
2959 void WebPage::drawRectToPDF(uint64_t frameID, const PrintInfo& printInfo, const WebCore::IntRect& rect, uint64_t callbackID)
2960 {
2961     WebFrame* frame = WebProcess::shared().webFrame(frameID);
2962     Frame* coreFrame = frame ? frame->coreFrame() : 0;
2963
2964     RetainPtr<CFMutableDataRef> pdfPageData(AdoptCF, CFDataCreateMutable(0, 0));
2965
2966 #if USE(CG)
2967     if (coreFrame) {
2968 #if PLATFORM(MAC)
2969         ASSERT(coreFrame->document()->printing() || pdfDocumentForPrintingFrame(coreFrame));
2970 #else
2971         ASSERT(coreFrame->document()->printing());
2972 #endif
2973
2974         // FIXME: Use CGDataConsumerCreate with callbacks to avoid copying the data.
2975         RetainPtr<CGDataConsumerRef> pdfDataConsumer(AdoptCF, CGDataConsumerCreateWithCFData(pdfPageData.get()));
2976
2977         CGRect mediaBox = CGRectMake(0, 0, rect.width(), rect.height());
2978         RetainPtr<CGContextRef> context(AdoptCF, CGPDFContextCreate(pdfDataConsumer.get(), &mediaBox, 0));
2979         RetainPtr<CFDictionaryRef> pageInfo(AdoptCF, CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
2980         CGPDFContextBeginPage(context.get(), pageInfo.get());
2981
2982 #if PLATFORM(MAC)
2983         if (RetainPtr<PDFDocument> pdfDocument = pdfDocumentForPrintingFrame(coreFrame)) {
2984             ASSERT(!m_printContext);
2985             drawRectToPDFFromPDFDocument(context.get(), pdfDocument.get(), printInfo, rect);
2986         } else
2987 #endif
2988         {
2989             GraphicsContext ctx(context.get());
2990             ctx.scale(FloatSize(1, -1));
2991             ctx.translate(0, -rect.height());
2992             m_printContext->spoolRect(ctx, rect);
2993         }
2994
2995         CGPDFContextEndPage(context.get());
2996         CGPDFContextClose(context.get());
2997     }
2998 #endif
2999
3000     send(Messages::WebPageProxy::DataCallback(CoreIPC::DataReference(CFDataGetBytePtr(pdfPageData.get()), CFDataGetLength(pdfPageData.get())), callbackID));
3001 }
3002
3003 void WebPage::drawPagesToPDF(uint64_t frameID, const PrintInfo& printInfo, uint32_t first, uint32_t count, uint64_t callbackID)
3004 {
3005     WebFrame* frame = WebProcess::shared().webFrame(frameID);
3006     Frame* coreFrame = frame ? frame->coreFrame() : 0;
3007
3008     RetainPtr<CFMutableDataRef> pdfPageData(AdoptCF, CFDataCreateMutable(0, 0));
3009
3010 #if USE(CG)
3011     if (coreFrame) {
3012
3013 #if PLATFORM(MAC)
3014         ASSERT(coreFrame->document()->printing() || pdfDocumentForPrintingFrame(coreFrame));
3015 #else
3016         ASSERT(coreFrame->document()->printing());
3017 #endif
3018
3019         // FIXME: Use CGDataConsumerCreate with callbacks to avoid copying the data.
3020         RetainPtr<CGDataConsumerRef> pdfDataConsumer(AdoptCF, CGDataConsumerCreateWithCFData(pdfPageData.get()));
3021
3022         CGRect mediaBox = (m_printContext && m_printContext->pageCount()) ? m_printContext->pageRect(0) : CGRectMake(0, 0, printInfo.availablePaperWidth, printInfo.availablePaperHeight);
3023         RetainPtr<CGContextRef> context(AdoptCF, CGPDFContextCreate(pdfDataConsumer.get(), &mediaBox, 0));
3024
3025 #if PLATFORM(MAC)
3026         if (RetainPtr<PDFDocument> pdfDocument = pdfDocumentForPrintingFrame(coreFrame)) {
3027             ASSERT(!m_printContext);
3028             drawPagesToPDFFromPDFDocument(context.get(), pdfDocument.get(), printInfo, first, count);
3029         } else
3030 #endif
3031         {
3032             size_t pageCount = m_printContext->pageCount();
3033             for (uint32_t page = first; page < first + count; ++page) {
3034                 if (page >= pageCount)
3035                     break;
3036
3037                 RetainPtr<CFDictionaryRef> pageInfo(AdoptCF, CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
3038                 CGPDFContextBeginPage(context.get(), pageInfo.get());
3039
3040                 GraphicsContext ctx(context.get());
3041                 ctx.scale(FloatSize(1, -1));
3042                 ctx.translate(0, -m_printContext->pageRect(page).height());
3043                 m_printContext->spoolPage(ctx, page, m_printContext->pageRect(page).width());
3044
3045                 CGPDFContextEndPage(context.get());
3046             }
3047         }
3048         CGPDFContextClose(context.get());
3049     }
3050 #endif
3051
3052     send(Messages::WebPageProxy::DataCallback(CoreIPC::DataReference(CFDataGetBytePtr(pdfPageData.get()), CFDataGetLength(pdfPageData.get())), callbackID));
3053 }
3054
3055 #elif PLATFORM(GTK)
3056
3057 void WebPage::drawPagesForPrinting(uint64_t frameID, const PrintInfo& printInfo, uint64_t callbackID)
3058 {
3059     beginPrinting(frameID, printInfo);
3060     if (m_printContext && m_printOperation) {
3061         m_printOperation->startPrint(m_printContext.get(), callbackID);
3062         return;
3063     }
3064
3065     send(Messages::WebPageProxy::VoidCallback(callbackID));
3066 }
3067 #endif
3068
3069 void WebPage::setMediaVolume(float volume)
3070 {
3071     m_page->setMediaVolume(volume);
3072 }
3073
3074 void WebPage::runModal()
3075 {
3076     if (m_isClosed)
3077         return;
3078     if (m_isRunningModal)
3079         return;
3080
3081     m_isRunningModal = true;
3082     send(Messages::WebPageProxy::RunModal());
3083     RunLoop::run();
3084     ASSERT(!m_isRunningModal);
3085 }
3086
3087 void WebPage::setMemoryCacheMessagesEnabled(bool memoryCacheMessagesEnabled)
3088 {
3089     m_page->setMemoryCacheClientCallsEnabled(memoryCacheMessagesEnabled);
3090 }
3091
3092 bool WebPage::canHandleRequest(const WebCore::ResourceRequest& request)
3093 {
3094     if (SchemeRegistry::shouldLoadURLSchemeAsEmptyDocument(request.url().protocol()))
3095         return true;
3096     return platformCanHandleRequest(request);
3097 }
3098
3099 #if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD)
3100 void WebPage::handleAlternativeTextUIResult(const String& result)
3101 {
3102     Frame* frame = m_page->focusController()->focusedOrMainFrame();
3103     if (!frame)
3104         return;
3105     frame->editor()->handleAlternativeTextUIResult(result);
3106 }
3107 #endif
3108
3109 void WebPage::simulateMouseDown(int button, WebCore::IntPoint position, int clickCount, WKEventModifiers modifiers, double time)
3110 {
3111     mouseEvent(WebMouseEvent(WebMouseEvent::MouseDown, static_cast<WebMouseEvent::Button>(button), position, position, 0, 0, 0, clickCount, static_cast<WebMouseEvent::Modifiers>(modifiers), time));
3112 }
3113
3114 void WebPage::simulateMouseUp(int button, WebCore::IntPoint position, int clickCount, WKEventModifiers modifiers, double time)
3115 {
3116     mouseEvent(WebMouseEvent(WebMouseEvent::MouseUp, static_cast<WebMouseEvent::Button>(button), position, position, 0, 0, 0, clickCount, static_cast<WebMouseEvent::Modifiers>(modifiers), time));
3117 }
3118
3119 void WebPage::simulateMouseMotion(WebCore::IntPoint position, double time)
3120 {
3121     mouseEvent(WebMouseEvent(WebMouseEvent::MouseMove, WebMouseEvent::NoButton, position, position, 0, 0, 0, 0, WebMouseEvent::Modifiers(), time));
3122 }
3123
3124 String WebPage::viewportConfigurationAsText(int deviceDPI, int deviceWidth, int deviceHeight, int availableWidth, int availableHeight)
3125 {
3126     ViewportArguments arguments = mainFrame()->document()->viewportArguments();
3127     ViewportAttributes attrs = WebCore::computeViewportAttributes(arguments, /* default layout width for non-mobile pages */ 980, deviceWidth, deviceHeight, deviceDPI, IntSize(availableWidth, availableHeight));
3128     WebCore::restrictMinimumScaleFactorToViewportSize(attrs, IntSize(availableWidth, availableHeight));
3129     WebCore::restrictScaleFactorToInitialScaleIfNotUserScalable(attrs);
3130     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);
3131 }
3132
3133 void WebPage::setCompositionForTesting(const String& compositionString, uint64_t from, uint64_t length)
3134 {
3135     Frame* frame = m_page->focusController()->focusedOrMainFrame();
3136     if (!frame || !frame->editor()->canEdit())
3137         return;
3138
3139     Vector<CompositionUnderline> underlines;
3140     underlines.append(CompositionUnderline(0, compositionString.length(), Color(Color::black), false));
3141     frame->editor()->setComposition(compositionString, underlines, from, from + length);
3142 }
3143
3144 bool WebPage::hasCompositionForTesting()
3145 {
3146     Frame* frame = m_page->focusController()->focusedOrMainFrame();
3147     return frame && frame->editor()->hasComposition();
3148 }
3149
3150 void WebPage::confirmCompositionForTesting(const String& compositionString)
3151 {
3152     Frame* frame = m_page->focusController()->focusedOrMainFrame();
3153     if (!frame || !frame->editor()->canEdit())
3154         return;
3155
3156     if (compositionString.isNull())
3157         frame->editor()->confirmComposition();
3158     frame->editor()->confirmComposition(compositionString);
3159 }
3160
3161 void WebPage::numWheelEventHandlersChanged(unsigned numWheelEventHandlers)
3162 {
3163     if (m_numWheelEventHandlers == numWheelEventHandlers)
3164         return;
3165
3166     m_numWheelEventHandlers = numWheelEventHandlers;
3167     recomputeShortCircuitHorizontalWheelEventsState();
3168 }
3169
3170 static bool hasEnabledHorizontalScrollbar(ScrollableArea* scrollableArea)
3171 {
3172     if (Scrollbar* scrollbar = scrollableArea->horizontalScrollbar())
3173         return scrollbar->enabled();
3174
3175     return false;
3176 }
3177
3178 static bool pageContainsAnyHorizontalScrollbars(Frame* mainFrame)
3179 {
3180     if (FrameView* frameView = mainFrame->view()) {
3181         if (hasEnabledHorizontalScrollbar(frameView))
3182             return true;
3183     }
3184
3185     for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext()) {
3186         FrameView* frameView = frame->view();
3187         if (!frameView)
3188             continue;
3189
3190         const HashSet<ScrollableArea*>* scrollableAreas = frameView->scrollableAreas();
3191         if (!scrollableAreas)
3192             continue;
3193
3194         for (HashSet<ScrollableArea*>::const_iterator it = scrollableAreas->begin(), end = scrollableAreas->end(); it != end; ++it) {
3195             ScrollableArea* scrollableArea = *it;
3196             if (!scrollableArea->isOnActivePage())
3197                 continue;
3198
3199             if (hasEnabledHorizontalScrollbar(scrollableArea))
3200                 return true;
3201         }
3202     }
3203
3204     return false;
3205 }
3206
3207 void WebPage::recomputeShortCircuitHorizontalWheelEventsState()
3208 {
3209     bool canShortCircuitHorizontalWheelEvents = !m_numWheelEventHandlers;
3210
3211     if (canShortCircuitHorizontalWheelEvents) {
3212         // Check if we have any horizontal scroll bars on the page.
3213         if (pageContainsAnyHorizontalScrollbars(mainFrame()))
3214             canShortCircuitHorizontalWheelEvents = false;
3215     }
3216
3217     if (m_canShortCircuitHorizontalWheelEvents == canShortCircuitHorizontalWheelEvents)
3218         return;
3219
3220     m_canShortCircuitHorizontalWheelEvents = canShortCircuitHorizontalWheelEvents;
3221     send(Messages::WebPageProxy::SetCanShortCircuitHorizontalWheelEvents(m_canShortCircuitHorizontalWheelEvents));
3222 }
3223
3224 Frame* WebPage::mainFrame() const
3225 {
3226     return m_page ? m_page->mainFrame() : 0;
3227 }
3228
3229 FrameView* WebPage::mainFrameView() const
3230 {
3231     if (Frame* frame = mainFrame())
3232         return frame->view();
3233     
3234     return 0;
3235 }
3236
3237 #if ENABLE(PAGE_VISIBILITY_API)
3238 void WebPage::setVisibilityState(int visibilityState, bool isInitialState)
3239 {
3240     if (!m_page)
3241         return;
3242
3243     WebCore::PageVisibilityState state = static_cast<WebCore::PageVisibilityState>(visibilityState);
3244
3245     if (m_visibilityState == state)
3246         return;
3247
3248     FrameView* view = m_page->mainFrame() ? m_page->mainFrame()->view() : 0;
3249
3250     if (state == WebCore::PageVisibilityStateVisible) {
3251         m_page->didMoveOnscreen();
3252         if (view)
3253             view->show();
3254     }
3255
3256     m_page->setVisibilityState(state, isInitialState);
3257     m_visibilityState = state;
3258
3259     if (state == WebCore::PageVisibilityStateHidden) {
3260         m_page->willMoveOffscreen();
3261         if (view)
3262             view->hide();
3263     }
3264 }
3265 #endif
3266
3267 } // namespace WebKit