1/*
2 * Copyright (C) 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
3 * Copyright (C) 2012 Intel Corporation. All rights reserved.
4 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
19 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
25 * THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "config.h"
29#include "WebPage.h"
30
31#include "Arguments.h"
32#include "DataReference.h"
33#include "DecoderAdapter.h"
34#include "DrawingArea.h"
35#include "DrawingAreaMessages.h"
36#include "InjectedBundle.h"
37#include "InjectedBundleBackForwardList.h"
38#include "InjectedBundleUserMessageCoders.h"
39#include "LayerTreeHost.h"
40#include "Logging.h"
41#include "NetscapePlugin.h"
42#include "NotificationPermissionRequestManager.h"
43#include "PageBanner.h"
44#include "PageOverlay.h"
45#include "PluginProcessAttributes.h"
46#include "PluginProxy.h"
47#include "PluginView.h"
48#include "PrintInfo.h"
49#include "SessionState.h"
50#include "ShareableBitmap.h"
51#include "WebAlternativeTextClient.h"
52#include "WebBackForwardList.h"
53#include "WebBackForwardListItem.h"
54#include "WebBackForwardListProxy.h"
55#include "WebChromeClient.h"
56#include "WebColorChooser.h"
57#include "WebContextMenu.h"
58#include "WebContextMenuClient.h"
59#include "WebContextMessages.h"
60#include "WebCoreArgumentCoders.h"
61#include "WebDragClient.h"
62#include "WebEditorClient.h"
63#include "WebEvent.h"
64#include "WebEventConversion.h"
65#include "WebFrame.h"
66#include "WebFullScreenManager.h"
67#include "WebFullScreenManagerMessages.h"
68#include "WebGeolocationClient.h"
69#include "WebGeometry.h"
70#include "WebImage.h"
71#include "WebInspector.h"
72#include "WebInspectorClient.h"
73#include "WebInspectorMessages.h"
74#include "WebNotificationClient.h"
75#include "WebOpenPanelResultListener.h"
76#include "WebPageCreationParameters.h"
77#include "WebPageGroupProxy.h"
78#include "WebPageMessages.h"
79#include "WebPageProxyMessages.h"
80#include "WebPlugInClient.h"
81#include "WebPopupMenu.h"
82#include "WebPreferencesStore.h"
83#include "WebProcess.h"
84#include "WebProcessProxyMessages.h"
85#include <JavaScriptCore/APICast.h>
86#include <WebCore/ArchiveResource.h>
87#include <WebCore/Chrome.h>
88#include <WebCore/ContextMenuController.h>
89#include <WebCore/DatabaseManager.h>
90#include <WebCore/DocumentFragment.h>
91#include <WebCore/DocumentLoader.h>
92#include <WebCore/DocumentMarkerController.h>
93#include <WebCore/DragController.h>
94#include <WebCore/DragData.h>
95#include <WebCore/DragSession.h>
96#include <WebCore/EventHandler.h>
97#include <WebCore/FocusController.h>
98#include <WebCore/FormState.h>
99#include <WebCore/Frame.h>
100#include <WebCore/FrameLoadRequest.h>
101#include <WebCore/FrameLoaderTypes.h>
102#include <WebCore/FrameView.h>
103#include <WebCore/HTMLFormElement.h>
104#include <WebCore/HTMLInputElement.h>
105#include <WebCore/HTMLPlugInElement.h>
106#include <WebCore/HTMLPlugInImageElement.h>
107#include <WebCore/HistoryController.h>
108#include <WebCore/HistoryItem.h>
109#include <WebCore/JSDOMWindow.h>
110#include <WebCore/KeyboardEvent.h>
111#include <WebCore/MIMETypeRegistry.h>
112#include <WebCore/MouseEvent.h>
113#include <WebCore/Page.h>
114#include <WebCore/PlatformKeyboardEvent.h>
115#include <WebCore/PluginDocument.h>
116#include <WebCore/PrintContext.h>
117#include <WebCore/Range.h>
118#include <WebCore/RenderLayer.h>
119#include <WebCore/RenderTreeAsText.h>
120#include <WebCore/RenderView.h>
121#include <WebCore/ResourceBuffer.h>
122#include <WebCore/ResourceRequest.h>
123#include <WebCore/ResourceResponse.h>
124#include <WebCore/RunLoop.h>
125#include <WebCore/RuntimeEnabledFeatures.h>
126#include <WebCore/SchemeRegistry.h>
127#include <WebCore/ScriptController.h>
128#include <WebCore/ScriptValue.h>
129#include <WebCore/SerializedScriptValue.h>
130#include <WebCore/Settings.h>
131#include <WebCore/SharedBuffer.h>
132#include <WebCore/SubstituteData.h>
133#include <WebCore/TextIterator.h>
134#include <WebCore/VisiblePosition.h>
135#include <WebCore/markup.h>
136#include <runtime/JSCJSValue.h>
137#include <runtime/JSLock.h>
138#include <runtime/Operations.h>
139
140#if ENABLE(MHTML)
141#include <WebCore/MHTMLArchive.h>
142#endif
143
144#if ENABLE(PLUGIN_PROCESS)
145#if PLATFORM(MAC)
146#include "MachPort.h"
147#endif
148#endif
149
150#if ENABLE(BATTERY_STATUS)
151#include "WebBatteryClient.h"
152#endif
153
154#if ENABLE(NETWORK_INFO)
155#include "WebNetworkInfoClient.h"
156#endif
157
158#if ENABLE(VIBRATION)
159#include "WebVibrationClient.h"
160#endif
161
162#if ENABLE(PROXIMITY_EVENTS)
163#include "WebDeviceProximityClient.h"
164#endif
165
166#if PLATFORM(MAC)
167#include "SimplePDFPlugin.h"
168#if ENABLE(PDFKIT_PLUGIN)
169#include "PDFPlugin.h"
170#endif
171#include <WebCore/LegacyWebArchive.h>
172#endif
173
174#if PLATFORM(QT)
175#if ENABLE(DEVICE_ORIENTATION) && HAVE(QTSENSORS)
176#include "DeviceMotionClientQt.h"
177#include "DeviceOrientationClientQt.h"
178#endif
179#include "HitTestResult.h"
180#include <QMimeData>
181#endif
182
183#if PLATFORM(GTK)
184#include <gtk/gtk.h>
185#include "DataObjectGtk.h"
186#include "WebPrintOperationGtk.h"
187#endif
188
189#ifndef NDEBUG
190#include <wtf/RefCountedLeakCounter.h>
191#endif
192
193#if USE(COORDINATED_GRAPHICS)
194#include "CoordinatedLayerTreeHostMessages.h"
195#endif
196
197using namespace JSC;
198using namespace WebCore;
199
200namespace WebKit {
201
202class SendStopResponsivenessTimer {
203public:
204    SendStopResponsivenessTimer(WebPage* page)
205        : m_page(page)
206    {
207    }
208
209    ~SendStopResponsivenessTimer()
210    {
211        m_page->send(Messages::WebPageProxy::StopResponsivenessTimer());
212    }
213
214private:
215    WebPage* m_page;
216};
217
218DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, webPageCounter, ("WebPage"));
219
220PassRefPtr<WebPage> WebPage::create(uint64_t pageID, const WebPageCreationParameters& parameters)
221{
222    RefPtr<WebPage> page = adoptRef(new WebPage(pageID, parameters));
223
224    if (page->pageGroup()->isVisibleToInjectedBundle() && WebProcess::shared().injectedBundle())
225        WebProcess::shared().injectedBundle()->didCreatePage(page.get());
226
227    return page.release();
228}
229
230WebPage::WebPage(uint64_t pageID, const WebPageCreationParameters& parameters)
231    : m_viewSize(parameters.viewSize)
232    , m_hasSeenPlugin(false)
233    , m_useFixedLayout(false)
234    , m_drawsBackground(true)
235    , m_drawsTransparentBackground(false)
236    , m_isInRedo(false)
237    , m_isClosed(false)
238    , m_tabToLinks(false)
239    , m_asynchronousPluginInitializationEnabled(false)
240    , m_asynchronousPluginInitializationEnabledForAllPlugins(false)
241    , m_artificialPluginInitializationDelayEnabled(false)
242    , m_scrollingPerformanceLoggingEnabled(false)
243    , m_mainFrameIsScrollable(true)
244#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC)
245    , m_readyToFindPrimarySnapshottedPlugin(false)
246    , m_didFindPrimarySnapshottedPlugin(false)
247    , m_numberOfPrimarySnapshotDetectionAttempts(0)
248    , m_determinePrimarySnapshottedPlugInTimer(RunLoop::main(), this, &WebPage::determinePrimarySnapshottedPlugInTimerFired)
249#endif
250#if PLATFORM(MAC)
251    , m_pdfPluginEnabled(false)
252    , m_hasCachedWindowFrame(false)
253    , m_windowIsVisible(false)
254    , m_layerHostingMode(parameters.layerHostingMode)
255    , m_keyboardEventBeingInterpreted(0)
256#elif PLATFORM(GTK)
257    , m_accessibilityObject(0)
258#endif
259    , m_setCanStartMediaTimer(RunLoop::main(), this, &WebPage::setCanStartMediaTimerFired)
260    , m_sendDidUpdateInWindowStateTimer(RunLoop::main(), this, &WebPage::didUpdateInWindowStateTimerFired)
261    , m_findController(this)
262#if ENABLE(TOUCH_EVENTS)
263#if PLATFORM(QT)
264    , m_tapHighlightController(this)
265#endif
266#endif
267#if ENABLE(INPUT_TYPE_COLOR)
268    , m_activeColorChooser(0)
269#endif
270#if ENABLE(GEOLOCATION)
271    , m_geolocationPermissionRequestManager(this)
272#endif
273    , m_pageID(pageID)
274    , m_canRunBeforeUnloadConfirmPanel(parameters.canRunBeforeUnloadConfirmPanel)
275    , m_canRunModal(parameters.canRunModal)
276    , m_isRunningModal(false)
277    , m_cachedMainFrameIsPinnedToLeftSide(false)
278    , m_cachedMainFrameIsPinnedToRightSide(false)
279    , m_cachedMainFrameIsPinnedToTopSide(false)
280    , m_cachedMainFrameIsPinnedToBottomSide(false)
281    , m_canShortCircuitHorizontalWheelEvents(false)
282    , m_numWheelEventHandlers(0)
283    , m_cachedPageCount(0)
284    , m_autoSizingShouldExpandToViewHeight(false)
285#if ENABLE(CONTEXT_MENUS)
286    , m_isShowingContextMenu(false)
287#endif
288    , m_willGoToBackForwardItemCallbackEnabled(true)
289#if ENABLE(PAGE_VISIBILITY_API)
290    , m_visibilityState(WebCore::PageVisibilityStateVisible)
291#endif
292    , m_inspectorClient(0)
293    , m_backgroundColor(Color::white)
294    , m_maximumRenderingSuppressionToken(0)
295    , m_scrollPinningBehavior(DoNotPin)
296{
297    ASSERT(m_pageID);
298    // FIXME: This is a non-ideal location for this Setting and
299    // 4ms should be adopted project-wide now, https://bugs.webkit.org/show_bug.cgi?id=61214
300    Settings::setDefaultMinDOMTimerInterval(0.004);
301
302    Page::PageClients pageClients;
303    pageClients.chromeClient = new WebChromeClient(this);
304#if ENABLE(CONTEXT_MENUS)
305    pageClients.contextMenuClient = new WebContextMenuClient(this);
306#endif
307    pageClients.editorClient = new WebEditorClient(this);
308#if ENABLE(DRAG_SUPPORT)
309    pageClients.dragClient = new WebDragClient(this);
310#endif
311    pageClients.backForwardClient = WebBackForwardListProxy::create(this);
312#if ENABLE(INSPECTOR)
313    m_inspectorClient = new WebInspectorClient(this);
314    pageClients.inspectorClient = m_inspectorClient;
315#endif
316#if USE(AUTOCORRECTION_PANEL)
317    pageClients.alternativeTextClient = new WebAlternativeTextClient(this);
318#endif
319    pageClients.plugInClient = new WebPlugInClient(this);
320
321    m_page = adoptPtr(new Page(pageClients));
322
323#if ENABLE(BATTERY_STATUS)
324    WebCore::provideBatteryTo(m_page.get(), new WebBatteryClient(this));
325#endif
326#if ENABLE(GEOLOCATION)
327    WebCore::provideGeolocationTo(m_page.get(), new WebGeolocationClient(this));
328#endif
329#if ENABLE(DEVICE_ORIENTATION) && PLATFORM(QT) && HAVE(QTSENSORS)
330    WebCore::provideDeviceMotionTo(m_page.get(), new DeviceMotionClientQt);
331    WebCore::provideDeviceOrientationTo(m_page.get(), new DeviceOrientationClientQt);
332#endif
333#if ENABLE(NETWORK_INFO)
334    WebCore::provideNetworkInfoTo(m_page.get(), new WebNetworkInfoClient(this));
335#endif
336#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
337    WebCore::provideNotification(m_page.get(), new WebNotificationClient(this));
338#endif
339#if ENABLE(VIBRATION)
340    WebCore::provideVibrationTo(m_page.get(), new WebVibrationClient(this));
341#endif
342#if ENABLE(PROXIMITY_EVENTS)
343    WebCore::provideDeviceProximityTo(m_page.get(), new WebDeviceProximityClient(this));
344#endif
345
346    m_page->setCanStartMedia(false);
347    m_mayStartMediaWhenInWindow = parameters.mayStartMediaWhenInWindow;
348
349    m_pageGroup = WebProcess::shared().webPageGroup(parameters.pageGroupData);
350    m_page->setGroupName(m_pageGroup->identifier());
351    m_page->setDeviceScaleFactor(parameters.deviceScaleFactor);
352
353    m_drawingArea = DrawingArea::create(this, parameters);
354    m_drawingArea->setPaintingEnabled(false);
355
356    updatePreferences(parameters.store);
357    platformInitialize();
358
359    m_mainFrame = WebFrame::createMainFrame(this);
360
361    setUseFixedLayout(parameters.useFixedLayout);
362
363    setDrawsBackground(parameters.drawsBackground);
364    setDrawsTransparentBackground(parameters.drawsTransparentBackground);
365
366    setUnderlayColor(parameters.underlayColor);
367
368    setPaginationMode(parameters.paginationMode);
369    setPaginationBehavesLikeColumns(parameters.paginationBehavesLikeColumns);
370    setPageLength(parameters.pageLength);
371    setGapBetweenPages(parameters.gapBetweenPages);
372
373    setMemoryCacheMessagesEnabled(parameters.areMemoryCacheClientCallsEnabled);
374
375    setActive(parameters.isActive);
376    setFocused(parameters.isFocused);
377
378    // Page defaults to in-window, but setIsInWindow depends on it being a valid indicator of actually having been put into a window.
379    if (!parameters.isInWindow)
380        m_page->setIsInWindow(false);
381    else
382        WebProcess::shared().pageDidEnterWindow(m_pageID);
383
384    setIsInWindow(parameters.isInWindow);
385
386    setMinimumLayoutSize(parameters.minimumLayoutSize);
387    setAutoSizingShouldExpandToViewHeight(parameters.autoSizingShouldExpandToViewHeight);
388
389    setScrollPinningBehavior(parameters.scrollPinningBehavior);
390
391    m_userAgent = parameters.userAgent;
392
393    WebBackForwardListProxy::setHighestItemIDFromUIProcess(parameters.highestUsedBackForwardItemID);
394
395    if (!parameters.sessionState.isEmpty())
396        restoreSession(parameters.sessionState);
397
398    m_drawingArea->setPaintingEnabled(true);
399
400    setMediaVolume(parameters.mediaVolume);
401
402    // We use the DidFirstLayout milestone to determine when to unfreeze the layer tree.
403    m_page->addLayoutMilestones(DidFirstLayout);
404
405    WebProcess::shared().addMessageReceiver(Messages::WebPage::messageReceiverName(), m_pageID, this);
406
407    // FIXME: This should be done in the object constructors, and the objects themselves should be message receivers.
408    WebProcess::shared().addMessageReceiver(Messages::DrawingArea::messageReceiverName(), m_pageID, this);
409#if USE(COORDINATED_GRAPHICS)
410    WebProcess::shared().addMessageReceiver(Messages::CoordinatedLayerTreeHost::messageReceiverName(), m_pageID, this);
411#endif
412#if ENABLE(INSPECTOR)
413    WebProcess::shared().addMessageReceiver(Messages::WebInspector::messageReceiverName(), m_pageID, this);
414#endif
415#if ENABLE(FULLSCREEN_API)
416    WebProcess::shared().addMessageReceiver(Messages::WebFullScreenManager::messageReceiverName(), m_pageID, this);
417#endif
418
419#ifndef NDEBUG
420    webPageCounter.increment();
421#endif
422}
423
424WebPage::~WebPage()
425{
426    if (m_backForwardList)
427        m_backForwardList->detach();
428
429    ASSERT(!m_page);
430
431    m_sandboxExtensionTracker.invalidate();
432
433    for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
434        (*it)->webPageDestroyed();
435
436    if (m_headerBanner)
437        m_headerBanner->detachFromPage();
438    if (m_footerBanner)
439        m_footerBanner->detachFromPage();
440
441    WebProcess::shared().removeMessageReceiver(Messages::WebPage::messageReceiverName(), m_pageID);
442
443    // FIXME: This should be done in the object destructors, and the objects themselves should be message receivers.
444    WebProcess::shared().removeMessageReceiver(Messages::DrawingArea::messageReceiverName(), m_pageID);
445#if USE(COORDINATED_GRAPHICS)
446    WebProcess::shared().removeMessageReceiver(Messages::CoordinatedLayerTreeHost::messageReceiverName(), m_pageID);
447#endif
448#if ENABLE(INSPECTOR)
449    WebProcess::shared().removeMessageReceiver(Messages::WebInspector::messageReceiverName(), m_pageID);
450#endif
451#if ENABLE(FULLSCREEN_API)
452    WebProcess::shared().removeMessageReceiver(Messages::WebFullScreenManager::messageReceiverName(), m_pageID);
453#endif
454
455#ifndef NDEBUG
456    webPageCounter.decrement();
457#endif
458}
459
460void WebPage::dummy(bool&)
461{
462}
463
464CoreIPC::Connection* WebPage::messageSenderConnection()
465{
466    return WebProcess::shared().parentProcessConnection();
467}
468
469uint64_t WebPage::messageSenderDestinationID()
470{
471    return pageID();
472}
473
474#if ENABLE(CONTEXT_MENUS)
475void WebPage::initializeInjectedBundleContextMenuClient(WKBundlePageContextMenuClient* client)
476{
477    m_contextMenuClient.initialize(client);
478}
479#endif
480
481void WebPage::initializeInjectedBundleEditorClient(WKBundlePageEditorClient* client)
482{
483    m_editorClient.initialize(client);
484}
485
486void WebPage::initializeInjectedBundleFormClient(WKBundlePageFormClient* client)
487{
488    m_formClient.initialize(client);
489}
490
491void WebPage::initializeInjectedBundleLoaderClient(WKBundlePageLoaderClient* client)
492{
493    // It would be nice to get rid of this code and transition all clients to using didLayout instead of
494    // didFirstLayoutInFrame and didFirstVisuallyNonEmptyLayoutInFrame. In the meantime, this is required
495    // for backwards compatibility.
496    LayoutMilestones milestones = 0;
497    if (client) {
498        if (client->didFirstLayoutForFrame)
499            milestones |= WebCore::DidFirstLayout;
500        if (client->didFirstVisuallyNonEmptyLayoutForFrame)
501            milestones |= WebCore::DidFirstVisuallyNonEmptyLayout;
502        if (client->didNewFirstVisuallyNonEmptyLayout)
503            milestones |= WebCore::DidHitRelevantRepaintedObjectsAreaThreshold;
504    }
505
506    if (milestones)
507        listenForLayoutMilestones(milestones);
508
509    m_loaderClient.initialize(client);
510}
511
512void WebPage::initializeInjectedBundlePolicyClient(WKBundlePagePolicyClient* client)
513{
514    m_policyClient.initialize(client);
515}
516
517void WebPage::initializeInjectedBundleResourceLoadClient(WKBundlePageResourceLoadClient* client)
518{
519    m_resourceLoadClient.initialize(client);
520}
521
522void WebPage::initializeInjectedBundleUIClient(WKBundlePageUIClient* client)
523{
524    m_uiClient.initialize(client);
525}
526
527#if ENABLE(FULLSCREEN_API)
528void WebPage::initializeInjectedBundleFullScreenClient(WKBundlePageFullScreenClient* client)
529{
530    m_fullScreenClient.initialize(client);
531}
532#endif
533
534void WebPage::initializeInjectedBundleDiagnosticLoggingClient(WKBundlePageDiagnosticLoggingClient* client)
535{
536    m_logDiagnosticMessageClient.initialize(client);
537}
538
539#if ENABLE(NETSCAPE_PLUGIN_API)
540PassRefPtr<Plugin> WebPage::createPlugin(WebFrame* frame, HTMLPlugInElement* pluginElement, const Plugin::Parameters& parameters, String& newMIMEType)
541{
542    String frameURLString = frame->coreFrame()->loader()->documentLoader()->responseURL().string();
543    String pageURLString = m_page->mainFrame()->loader()->documentLoader()->responseURL().string();
544    PluginProcessType processType = pluginElement->displayState() == HTMLPlugInElement::WaitingForSnapshot ? PluginProcessTypeSnapshot : PluginProcessTypeNormal;
545
546    bool allowOnlyApplicationPlugins = !frame->coreFrame()->loader()->subframeLoader()->allowPlugins(NotAboutToInstantiatePlugin);
547
548    uint64_t pluginProcessToken;
549    uint32_t pluginLoadPolicy;
550    String unavailabilityDescription;
551    if (!sendSync(Messages::WebPageProxy::FindPlugin(parameters.mimeType, static_cast<uint32_t>(processType), parameters.url.string(), frameURLString, pageURLString, allowOnlyApplicationPlugins), Messages::WebPageProxy::FindPlugin::Reply(pluginProcessToken, newMIMEType, pluginLoadPolicy, unavailabilityDescription))) {
552        return 0;
553    }
554
555    switch (static_cast<PluginModuleLoadPolicy>(pluginLoadPolicy)) {
556    case PluginModuleLoadNormally:
557    case PluginModuleLoadUnsandboxed:
558        break;
559
560    case PluginModuleBlocked:
561        bool replacementObscured = false;
562        if (pluginElement->renderer()->isEmbeddedObject()) {
563            RenderEmbeddedObject* renderObject = toRenderEmbeddedObject(pluginElement->renderer());
564            renderObject->setPluginUnavailabilityReasonWithDescription(RenderEmbeddedObject::InsecurePluginVersion, unavailabilityDescription);
565            replacementObscured = renderObject->isReplacementObscured();
566            renderObject->setUnavailablePluginIndicatorIsHidden(replacementObscured);
567        }
568
569        send(Messages::WebPageProxy::DidBlockInsecurePluginVersion(parameters.mimeType, parameters.url.string(), frameURLString, pageURLString, replacementObscured));
570        return 0;
571    }
572
573    if (!pluginProcessToken) {
574#if PLATFORM(MAC)
575        String path = parameters.url.path();
576        if (MIMETypeRegistry::isPDFOrPostScriptMIMEType(parameters.mimeType) || (parameters.mimeType.isEmpty() && (path.endsWith(".pdf", false) || path.endsWith(".ps", false)))) {
577#if ENABLE(PDFKIT_PLUGIN)
578            if (shouldUsePDFPlugin())
579                return PDFPlugin::create(frame);
580#endif
581            return SimplePDFPlugin::create(frame);
582        }
583#else
584        UNUSED_PARAM(frame);
585#endif
586        return 0;
587    }
588
589    bool isRestartedProcess = (pluginElement->displayState() == HTMLPlugInElement::Restarting || pluginElement->displayState() == HTMLPlugInElement::RestartingWithPendingMouseClick);
590    return PluginProxy::create(pluginProcessToken, isRestartedProcess);
591}
592
593#endif // ENABLE(NETSCAPE_PLUGIN_API)
594
595EditorState WebPage::editorState() const
596{
597    Frame* frame = m_page->focusController()->focusedOrMainFrame();
598    ASSERT(frame);
599
600    EditorState result;
601
602    if (PluginView* pluginView = focusedPluginViewForFrame(frame)) {
603        if (!pluginView->getSelectionString().isNull()) {
604            result.selectionIsNone = false;
605            result.selectionIsRange = true;
606            result.isInPlugin = true;
607            return result;
608        }
609    }
610
611    result.selectionIsNone = frame->selection()->isNone();
612    result.selectionIsRange = frame->selection()->isRange();
613    result.isContentEditable = frame->selection()->isContentEditable();
614    result.isContentRichlyEditable = frame->selection()->isContentRichlyEditable();
615    result.isInPasswordField = frame->selection()->isInPasswordField();
616    result.hasComposition = frame->editor().hasComposition();
617    result.shouldIgnoreCompositionSelectionChange = frame->editor().ignoreCompositionSelectionChange();
618
619#if PLATFORM(QT)
620    size_t location = 0;
621    size_t length = 0;
622
623    Element* selectionRoot = frame->selection()->rootEditableElementRespectingShadowTree();
624    Element* scope = selectionRoot ? selectionRoot : frame->document()->documentElement();
625
626    if (!scope)
627        return result;
628
629    if (scope->hasTagName(HTMLNames::inputTag)) {
630        HTMLInputElement* input = static_cast<HTMLInputElement*>(scope);
631        if (input->isTelephoneField())
632            result.inputMethodHints |= Qt::ImhDialableCharactersOnly;
633        else if (input->isNumberField())
634            result.inputMethodHints |= Qt::ImhDigitsOnly;
635        else if (input->isEmailField()) {
636            result.inputMethodHints |= Qt::ImhEmailCharactersOnly;
637            result.inputMethodHints |= Qt::ImhNoAutoUppercase;
638        } else if (input->isURLField()) {
639            result.inputMethodHints |= Qt::ImhUrlCharactersOnly;
640            result.inputMethodHints |= Qt::ImhNoAutoUppercase;
641        } else if (input->isPasswordField()) {
642            // Set ImhHiddenText flag for password fields. The Qt platform
643            // is responsible for determining which widget will receive input
644            // method events for password fields.
645            result.inputMethodHints |= Qt::ImhHiddenText;
646            result.inputMethodHints |= Qt::ImhNoAutoUppercase;
647            result.inputMethodHints |= Qt::ImhNoPredictiveText;
648            result.inputMethodHints |= Qt::ImhSensitiveData;
649        }
650    }
651
652    if (selectionRoot)
653        result.editorRect = frame->view()->contentsToWindow(selectionRoot->pixelSnappedBoundingBox());
654
655    RefPtr<Range> range;
656    if (result.hasComposition && (range = frame->editor().compositionRange())) {
657        frame->editor().getCompositionSelection(result.anchorPosition, result.cursorPosition);
658
659        result.compositionRect = frame->view()->contentsToWindow(range->boundingBox());
660    }
661
662    if (!result.hasComposition && !result.selectionIsNone && (range = frame->selection()->selection().firstRange())) {
663        TextIterator::getLocationAndLengthFromRange(scope, range.get(), location, length);
664        bool baseIsFirst = frame->selection()->selection().isBaseFirst();
665
666        result.cursorPosition = (baseIsFirst) ? location + length : location;
667        result.anchorPosition = (baseIsFirst) ? location : location + length;
668        result.selectedText = range->text();
669    }
670
671    if (range)
672        result.cursorRect = frame->view()->contentsToWindow(frame->editor().firstRectForRange(range.get()));
673
674    // FIXME: We should only transfer innerText when it changes and do this on the UI side.
675    if (result.isContentEditable && !result.isInPasswordField) {
676        result.surroundingText = scope->innerText();
677        if (result.hasComposition) {
678            // The anchor is always the left position when they represent a composition.
679            result.surroundingText.remove(result.anchorPosition, result.cursorPosition - result.anchorPosition);
680        }
681    }
682#endif
683
684#if PLATFORM(GTK)
685    result.cursorRect = frame->selection()->absoluteCaretBounds();
686#endif
687
688    return result;
689}
690
691String WebPage::renderTreeExternalRepresentation() const
692{
693    return externalRepresentation(m_mainFrame->coreFrame(), RenderAsTextBehaviorNormal);
694}
695
696String WebPage::renderTreeExternalRepresentationForPrinting() const
697{
698    return externalRepresentation(m_mainFrame->coreFrame(), RenderAsTextPrintingMode);
699}
700
701uint64_t WebPage::renderTreeSize() const
702{
703    if (!m_page)
704        return 0;
705    return m_page->renderTreeSize().treeSize;
706}
707
708void WebPage::setTracksRepaints(bool trackRepaints)
709{
710    if (FrameView* view = mainFrameView())
711        view->setTracksRepaints(trackRepaints);
712}
713
714bool WebPage::isTrackingRepaints() const
715{
716    if (FrameView* view = mainFrameView())
717        return view->isTrackingRepaints();
718
719    return false;
720}
721
722void WebPage::resetTrackedRepaints()
723{
724    if (FrameView* view = mainFrameView())
725        view->resetTrackedRepaints();
726}
727
728PassRefPtr<ImmutableArray> WebPage::trackedRepaintRects()
729{
730    FrameView* view = mainFrameView();
731    if (!view)
732        return ImmutableArray::create();
733
734    const Vector<IntRect>& rects = view->trackedRepaintRects();
735    size_t size = rects.size();
736    if (!size)
737        return ImmutableArray::create();
738
739    Vector<RefPtr<APIObject>> vector;
740    vector.reserveInitialCapacity(size);
741
742    for (size_t i = 0; i < size; ++i)
743        vector.uncheckedAppend(WebRect::create(toAPI(rects[i])));
744
745    return ImmutableArray::adopt(vector);
746}
747
748PluginView* WebPage::focusedPluginViewForFrame(Frame* frame)
749{
750    if (!frame->document()->isPluginDocument())
751        return 0;
752
753    PluginDocument* pluginDocument = static_cast<PluginDocument*>(frame->document());
754
755    if (pluginDocument->focusedElement() != pluginDocument->pluginElement())
756        return 0;
757
758    PluginView* pluginView = static_cast<PluginView*>(pluginDocument->pluginWidget());
759    return pluginView;
760}
761
762PluginView* WebPage::pluginViewForFrame(Frame* frame)
763{
764    if (!frame->document()->isPluginDocument())
765        return 0;
766
767    PluginDocument* pluginDocument = static_cast<PluginDocument*>(frame->document());
768    PluginView* pluginView = static_cast<PluginView*>(pluginDocument->pluginWidget());
769    return pluginView;
770}
771
772void WebPage::executeEditingCommand(const String& commandName, const String& argument)
773{
774    Frame* frame = m_page->focusController()->focusedOrMainFrame();
775    if (!frame)
776        return;
777
778    if (PluginView* pluginView = focusedPluginViewForFrame(frame)) {
779        pluginView->handleEditingCommand(commandName, argument);
780        return;
781    }
782
783    frame->editor().command(commandName).execute(argument);
784}
785
786bool WebPage::isEditingCommandEnabled(const String& commandName)
787{
788    Frame* frame = m_page->focusController()->focusedOrMainFrame();
789    if (!frame)
790        return false;
791
792    if (PluginView* pluginView = focusedPluginViewForFrame(frame))
793        return pluginView->isEditingCommandEnabled(commandName);
794
795    Editor::Command command = frame->editor().command(commandName);
796    return command.isSupported() && command.isEnabled();
797}
798
799void WebPage::clearMainFrameName()
800{
801    if (Frame* frame = mainFrame())
802        frame->tree()->clearName();
803}
804
805#if USE(ACCELERATED_COMPOSITING)
806void WebPage::enterAcceleratedCompositingMode(GraphicsLayer* layer)
807{
808    m_drawingArea->setRootCompositingLayer(layer);
809}
810
811void WebPage::exitAcceleratedCompositingMode()
812{
813    m_drawingArea->setRootCompositingLayer(0);
814}
815#endif
816
817void WebPage::close()
818{
819    if (m_isClosed)
820        return;
821
822    m_isClosed = true;
823
824    // If there is still no URL, then we never loaded anything in this page, so nothing to report.
825    if (!mainWebFrame()->url().isEmpty())
826        reportUsedFeatures();
827
828    if (pageGroup()->isVisibleToInjectedBundle() && WebProcess::shared().injectedBundle())
829        WebProcess::shared().injectedBundle()->willDestroyPage(this);
830
831#if ENABLE(INSPECTOR)
832    m_inspector = 0;
833#endif
834#if ENABLE(FULLSCREEN_API)
835    m_fullScreenManager = 0;
836#endif
837
838    if (m_activePopupMenu) {
839        m_activePopupMenu->disconnectFromPage();
840        m_activePopupMenu = 0;
841    }
842
843    if (m_activeOpenPanelResultListener) {
844        m_activeOpenPanelResultListener->disconnectFromPage();
845        m_activeOpenPanelResultListener = 0;
846    }
847
848#if ENABLE(INPUT_TYPE_COLOR)
849    if (m_activeColorChooser) {
850        m_activeColorChooser->disconnectFromPage();
851        m_activeColorChooser = 0;
852    }
853#endif
854
855    m_sandboxExtensionTracker.invalidate();
856
857#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC)
858    m_determinePrimarySnapshottedPlugInTimer.stop();
859#endif
860
861#if ENABLE(CONTEXT_MENUS)
862    m_contextMenuClient.initialize(0);
863#endif
864    m_editorClient.initialize(0);
865    m_formClient.initialize(0);
866    m_loaderClient.initialize(0);
867    m_policyClient.initialize(0);
868    m_resourceLoadClient.initialize(0);
869    m_uiClient.initialize(0);
870#if ENABLE(FULLSCREEN_API)
871    m_fullScreenClient.initialize(0);
872#endif
873    m_logDiagnosticMessageClient.initialize(0);
874
875    m_underlayPage = nullptr;
876    m_printContext = nullptr;
877    m_mainFrame->coreFrame()->loader()->detachFromParent();
878    m_page = nullptr;
879    m_drawingArea = nullptr;
880
881    bool isRunningModal = m_isRunningModal;
882    m_isRunningModal = false;
883
884    // The WebPage can be destroyed by this call.
885    WebProcess::shared().removeWebPage(m_pageID);
886
887    if (isRunningModal)
888        RunLoop::main()->stop();
889}
890
891void WebPage::tryClose()
892{
893    SendStopResponsivenessTimer stopper(this);
894
895    if (!m_mainFrame->coreFrame()->loader()->shouldClose()) {
896        send(Messages::WebPageProxy::StopResponsivenessTimer());
897        return;
898    }
899
900    send(Messages::WebPageProxy::ClosePage(true));
901}
902
903void WebPage::sendClose()
904{
905    send(Messages::WebPageProxy::ClosePage(false));
906}
907
908void WebPage::loadURL(const String& url, const SandboxExtension::Handle& sandboxExtensionHandle, CoreIPC::MessageDecoder& decoder)
909{
910    loadURLRequest(ResourceRequest(KURL(KURL(), url)), sandboxExtensionHandle, decoder);
911}
912
913void WebPage::loadURLRequest(const ResourceRequest& request, const SandboxExtension::Handle& sandboxExtensionHandle, CoreIPC::MessageDecoder& decoder)
914{
915    SendStopResponsivenessTimer stopper(this);
916
917    RefPtr<APIObject> userData;
918    InjectedBundleUserMessageDecoder userMessageDecoder(userData);
919    if (!decoder.decode(userMessageDecoder))
920        return;
921
922    m_sandboxExtensionTracker.beginLoad(m_mainFrame.get(), sandboxExtensionHandle);
923
924    // Let the InjectedBundle know we are about to start the load, passing the user data from the UIProcess
925    // to all the client to set up any needed state.
926    m_loaderClient.willLoadURLRequest(this, request, userData.get());
927
928    // Initate the load in WebCore.
929    m_mainFrame->coreFrame()->loader()->load(FrameLoadRequest(m_mainFrame->coreFrame(), request));
930}
931
932void WebPage::loadDataImpl(PassRefPtr<SharedBuffer> sharedBuffer, const String& MIMEType, const String& encodingName, const KURL& baseURL, const KURL& unreachableURL, CoreIPC::MessageDecoder& decoder)
933{
934    SendStopResponsivenessTimer stopper(this);
935
936    RefPtr<APIObject> userData;
937    InjectedBundleUserMessageDecoder userMessageDecoder(userData);
938    if (!decoder.decode(userMessageDecoder))
939        return;
940
941    ResourceRequest request(baseURL);
942    SubstituteData substituteData(sharedBuffer, MIMEType, encodingName, unreachableURL);
943
944    // Let the InjectedBundle know we are about to start the load, passing the user data from the UIProcess
945    // to all the client to set up any needed state.
946    m_loaderClient.willLoadDataRequest(this, request, substituteData.content(), substituteData.mimeType(), substituteData.textEncoding(), substituteData.failingURL(), userData.get());
947
948    // Initate the load in WebCore.
949    m_mainFrame->coreFrame()->loader()->load(FrameLoadRequest(m_mainFrame->coreFrame(), request, substituteData));
950}
951
952void WebPage::loadData(const CoreIPC::DataReference& data, const String& MIMEType, const String& encodingName, const String& baseURLString, CoreIPC::MessageDecoder& decoder)
953{
954    RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(data.data()), data.size());
955    KURL baseURL = baseURLString.isEmpty() ? blankURL() : KURL(KURL(), baseURLString);
956    loadDataImpl(sharedBuffer, MIMEType, encodingName, baseURL, KURL(), decoder);
957}
958
959void WebPage::loadHTMLString(const String& htmlString, const String& baseURLString, CoreIPC::MessageDecoder& decoder)
960{
961    RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(htmlString.characters()), htmlString.length() * sizeof(UChar));
962    KURL baseURL = baseURLString.isEmpty() ? blankURL() : KURL(KURL(), baseURLString);
963    loadDataImpl(sharedBuffer, "text/html", "utf-16", baseURL, KURL(), decoder);
964}
965
966void WebPage::loadAlternateHTMLString(const String& htmlString, const String& baseURLString, const String& unreachableURLString, CoreIPC::MessageDecoder& decoder)
967{
968    RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(htmlString.characters()), htmlString.length() * sizeof(UChar));
969    KURL baseURL = baseURLString.isEmpty() ? blankURL() : KURL(KURL(), baseURLString);
970    KURL unreachableURL = unreachableURLString.isEmpty() ? KURL() : KURL(KURL(), unreachableURLString);
971    loadDataImpl(sharedBuffer, "text/html", "utf-16", baseURL, unreachableURL, decoder);
972}
973
974void WebPage::loadPlainTextString(const String& string, CoreIPC::MessageDecoder& decoder)
975{
976    RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(string.characters()), string.length() * sizeof(UChar));
977    loadDataImpl(sharedBuffer, "text/plain", "utf-16", blankURL(), KURL(), decoder);
978}
979
980void WebPage::loadWebArchiveData(const CoreIPC::DataReference& webArchiveData, CoreIPC::MessageDecoder& decoder)
981{
982    RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(webArchiveData.data()), webArchiveData.size() * sizeof(uint8_t));
983    loadDataImpl(sharedBuffer, "application/x-webarchive", "utf-16", blankURL(), KURL(), decoder);
984}
985
986void WebPage::linkClicked(const String& url, const WebMouseEvent& event)
987{
988    Frame* frame = m_page->mainFrame();
989    if (!frame)
990        return;
991
992    RefPtr<Event> coreEvent;
993    if (event.type() != WebEvent::NoType)
994        coreEvent = MouseEvent::create(eventNames().clickEvent, frame->document()->defaultView(), platform(event), 0, 0);
995
996    frame->loader()->loadFrameRequest(FrameLoadRequest(frame, ResourceRequest(url)), false, false, coreEvent.get(), 0, MaybeSendReferrer);
997}
998
999void WebPage::stopLoadingFrame(uint64_t frameID)
1000{
1001    WebFrame* frame = WebProcess::shared().webFrame(frameID);
1002    if (!frame)
1003        return;
1004
1005    frame->coreFrame()->loader()->stopForUserCancel();
1006}
1007
1008void WebPage::stopLoading()
1009{
1010    SendStopResponsivenessTimer stopper(this);
1011
1012    m_mainFrame->coreFrame()->loader()->stopForUserCancel();
1013}
1014
1015void WebPage::setDefersLoading(bool defersLoading)
1016{
1017    m_page->setDefersLoading(defersLoading);
1018}
1019
1020void WebPage::reload(bool reloadFromOrigin, const SandboxExtension::Handle& sandboxExtensionHandle)
1021{
1022    SendStopResponsivenessTimer stopper(this);
1023
1024    m_sandboxExtensionTracker.beginLoad(m_mainFrame.get(), sandboxExtensionHandle);
1025    m_mainFrame->coreFrame()->loader()->reload(reloadFromOrigin);
1026}
1027
1028void WebPage::goForward(uint64_t backForwardItemID)
1029{
1030    SendStopResponsivenessTimer stopper(this);
1031
1032    HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
1033    ASSERT(item);
1034    if (!item)
1035        return;
1036
1037    m_page->goToItem(item, FrameLoadTypeForward);
1038}
1039
1040void WebPage::goBack(uint64_t backForwardItemID)
1041{
1042    SendStopResponsivenessTimer stopper(this);
1043
1044    HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
1045    ASSERT(item);
1046    if (!item)
1047        return;
1048
1049    m_page->goToItem(item, FrameLoadTypeBack);
1050}
1051
1052void WebPage::goToBackForwardItem(uint64_t backForwardItemID)
1053{
1054    SendStopResponsivenessTimer stopper(this);
1055
1056    HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
1057    ASSERT(item);
1058    if (!item)
1059        return;
1060
1061    m_page->goToItem(item, FrameLoadTypeIndexedBackForward);
1062}
1063
1064void WebPage::tryRestoreScrollPosition()
1065{
1066    m_page->mainFrame()->loader()->history()->restoreScrollPositionAndViewState();
1067}
1068
1069void WebPage::layoutIfNeeded()
1070{
1071    if (m_mainFrame->coreFrame()->view())
1072        m_mainFrame->coreFrame()->view()->updateLayoutAndStyleIfNeededRecursive();
1073
1074    if (m_underlayPage) {
1075        if (FrameView *frameView = m_underlayPage->mainFrameView())
1076            frameView->updateLayoutAndStyleIfNeededRecursive();
1077    }
1078}
1079
1080WebPage* WebPage::fromCorePage(Page* page)
1081{
1082    return static_cast<WebChromeClient*>(page->chrome().client())->page();
1083}
1084
1085void WebPage::setSize(const WebCore::IntSize& viewSize)
1086{
1087    FrameView* view = m_page->mainFrame()->view();
1088
1089    if (m_viewSize == viewSize)
1090        return;
1091
1092    view->resize(viewSize);
1093    view->setNeedsLayout();
1094    m_drawingArea->setNeedsDisplay();
1095
1096    m_viewSize = viewSize;
1097
1098#if USE(TILED_BACKING_STORE)
1099    if (view->useFixedLayout())
1100        sendViewportAttributesChanged();
1101#endif
1102}
1103
1104#if USE(TILED_BACKING_STORE)
1105void WebPage::setFixedVisibleContentRect(const IntRect& rect)
1106{
1107    ASSERT(m_useFixedLayout);
1108
1109    m_page->mainFrame()->view()->setFixedVisibleContentRect(rect);
1110}
1111
1112void WebPage::sendViewportAttributesChanged()
1113{
1114    ASSERT(m_useFixedLayout);
1115
1116    // Viewport properties have no impact on zero sized fixed viewports.
1117    if (m_viewSize.isEmpty())
1118        return;
1119
1120    // Recalculate the recommended layout size, when the available size (device pixel) changes.
1121    Settings* settings = m_page->settings();
1122
1123    int minimumLayoutFallbackWidth = std::max(settings->layoutFallbackWidth(), m_viewSize.width());
1124
1125    // If unset  we use the viewport dimensions. This fits with the behavior of desktop browsers.
1126    int deviceWidth = (settings->deviceWidth() > 0) ? settings->deviceWidth() : m_viewSize.width();
1127    int deviceHeight = (settings->deviceHeight() > 0) ? settings->deviceHeight() : m_viewSize.height();
1128
1129    ViewportAttributes attr = computeViewportAttributes(m_page->viewportArguments(), minimumLayoutFallbackWidth, deviceWidth, deviceHeight, 1, m_viewSize);
1130
1131    FrameView* view = m_page->mainFrame()->view();
1132
1133    // If no layout was done yet set contentFixedOrigin to (0,0).
1134    IntPoint contentFixedOrigin = view->didFirstLayout() ? view->fixedVisibleContentRect().location() : IntPoint();
1135
1136    // Put the width and height to the viewport width and height. In css units however.
1137    // Use FloatSize to avoid truncated values during scale.
1138    FloatSize contentFixedSize = m_viewSize;
1139
1140#if ENABLE(CSS_DEVICE_ADAPTATION)
1141    // CSS viewport descriptors might be applied to already affected viewport size
1142    // if the page enables/disables stylesheets, so need to keep initial viewport size.
1143    view->setInitialViewportSize(roundedIntSize(contentFixedSize));
1144#endif
1145
1146    contentFixedSize.scale(1 / attr.initialScale);
1147    setFixedVisibleContentRect(IntRect(contentFixedOrigin, roundedIntSize(contentFixedSize)));
1148
1149    attr.initialScale = m_page->viewportArguments().zoom; // Resets auto (-1) if no value was set by user.
1150
1151    // This also takes care of the relayout.
1152    setFixedLayoutSize(roundedIntSize(attr.layoutSize));
1153
1154    send(Messages::WebPageProxy::DidChangeViewportProperties(attr));
1155}
1156#endif
1157
1158void WebPage::scrollMainFrameIfNotAtMaxScrollPosition(const IntSize& scrollOffset)
1159{
1160    Frame* frame = m_page->mainFrame();
1161
1162    IntPoint scrollPosition = frame->view()->scrollPosition();
1163    IntPoint maximumScrollPosition = frame->view()->maximumScrollPosition();
1164
1165    // If the current scroll position in a direction is the max scroll position
1166    // we don't want to scroll at all.
1167    IntSize newScrollOffset;
1168    if (scrollPosition.x() < maximumScrollPosition.x())
1169        newScrollOffset.setWidth(scrollOffset.width());
1170    if (scrollPosition.y() < maximumScrollPosition.y())
1171        newScrollOffset.setHeight(scrollOffset.height());
1172
1173    if (newScrollOffset.isZero())
1174        return;
1175
1176    frame->view()->setScrollPosition(frame->view()->scrollPosition() + newScrollOffset);
1177}
1178
1179void WebPage::drawRect(GraphicsContext& graphicsContext, const IntRect& rect)
1180{
1181    GraphicsContextStateSaver stateSaver(graphicsContext);
1182    graphicsContext.clip(rect);
1183
1184    if (m_underlayPage) {
1185        m_underlayPage->drawRect(graphicsContext, rect);
1186
1187        graphicsContext.beginTransparencyLayer(1);
1188        m_mainFrame->coreFrame()->view()->paint(&graphicsContext, rect);
1189        graphicsContext.endTransparencyLayer();
1190        return;
1191    }
1192
1193    m_mainFrame->coreFrame()->view()->paint(&graphicsContext, rect);
1194}
1195
1196void WebPage::drawPageOverlay(PageOverlay* pageOverlay, GraphicsContext& graphicsContext, const IntRect& rect)
1197{
1198    ASSERT(pageOverlay);
1199
1200    GraphicsContextStateSaver stateSaver(graphicsContext);
1201    graphicsContext.clip(rect);
1202    pageOverlay->drawRect(graphicsContext, rect);
1203}
1204
1205double WebPage::textZoomFactor() const
1206{
1207    Frame* frame = m_mainFrame->coreFrame();
1208    if (!frame)
1209        return 1;
1210    return frame->textZoomFactor();
1211}
1212
1213void WebPage::setTextZoomFactor(double zoomFactor)
1214{
1215    PluginView* pluginView = pluginViewForFrame(m_page->mainFrame());
1216    if (pluginView && pluginView->handlesPageScaleFactor())
1217        return;
1218
1219    Frame* frame = m_mainFrame->coreFrame();
1220    if (!frame)
1221        return;
1222    frame->setTextZoomFactor(static_cast<float>(zoomFactor));
1223}
1224
1225double WebPage::pageZoomFactor() const
1226{
1227    PluginView* pluginView = pluginViewForFrame(m_page->mainFrame());
1228    if (pluginView && pluginView->handlesPageScaleFactor())
1229        return pluginView->pageScaleFactor();
1230
1231    Frame* frame = m_mainFrame->coreFrame();
1232    if (!frame)
1233        return 1;
1234    return frame->pageZoomFactor();
1235}
1236
1237void WebPage::setPageZoomFactor(double zoomFactor)
1238{
1239    PluginView* pluginView = pluginViewForFrame(m_page->mainFrame());
1240    if (pluginView && pluginView->handlesPageScaleFactor()) {
1241        pluginView->setPageScaleFactor(zoomFactor, IntPoint());
1242        return;
1243    }
1244
1245    Frame* frame = m_mainFrame->coreFrame();
1246    if (!frame)
1247        return;
1248    frame->setPageZoomFactor(static_cast<float>(zoomFactor));
1249}
1250
1251void WebPage::setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor)
1252{
1253    PluginView* pluginView = pluginViewForFrame(m_page->mainFrame());
1254    if (pluginView && pluginView->handlesPageScaleFactor()) {
1255        pluginView->setPageScaleFactor(pageZoomFactor, IntPoint());
1256        return;
1257    }
1258
1259    Frame* frame = m_mainFrame->coreFrame();
1260    if (!frame)
1261        return;
1262    return frame->setPageAndTextZoomFactors(static_cast<float>(pageZoomFactor), static_cast<float>(textZoomFactor));
1263}
1264
1265void WebPage::windowScreenDidChange(uint64_t displayID)
1266{
1267    m_page->windowScreenDidChange(static_cast<PlatformDisplayID>(displayID));
1268}
1269
1270void WebPage::scalePage(double scale, const IntPoint& origin)
1271{
1272    PluginView* pluginView = pluginViewForFrame(m_page->mainFrame());
1273    if (pluginView && pluginView->handlesPageScaleFactor()) {
1274        pluginView->setPageScaleFactor(scale, origin);
1275        return;
1276    }
1277
1278    m_page->setPageScaleFactor(scale, origin);
1279
1280    for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
1281        (*it)->pageScaleFactorDidChange();
1282
1283    if (m_drawingArea->layerTreeHost())
1284        m_drawingArea->layerTreeHost()->deviceOrPageScaleFactorChanged();
1285
1286    send(Messages::WebPageProxy::PageScaleFactorDidChange(scale));
1287}
1288
1289double WebPage::pageScaleFactor() const
1290{
1291    PluginView* pluginView = pluginViewForFrame(m_page->mainFrame());
1292    if (pluginView && pluginView->handlesPageScaleFactor())
1293        return pluginView->pageScaleFactor();
1294
1295    return m_page->pageScaleFactor();
1296}
1297
1298void WebPage::setDeviceScaleFactor(float scaleFactor)
1299{
1300    if (scaleFactor == m_page->deviceScaleFactor())
1301        return;
1302
1303    m_page->setDeviceScaleFactor(scaleFactor);
1304
1305    // Tell all our plug-in views that the device scale factor changed.
1306#if PLATFORM(MAC)
1307    for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
1308        (*it)->setDeviceScaleFactor(scaleFactor);
1309
1310    updateHeaderAndFooterLayersForDeviceScaleChange(scaleFactor);
1311#endif
1312
1313    if (m_findController.isShowingOverlay()) {
1314        // We must have updated layout to get the selection rects right.
1315        layoutIfNeeded();
1316        m_findController.deviceScaleFactorDidChange();
1317    }
1318
1319    if (m_drawingArea->layerTreeHost())
1320        m_drawingArea->layerTreeHost()->deviceOrPageScaleFactorChanged();
1321}
1322
1323float WebPage::deviceScaleFactor() const
1324{
1325    return m_page->deviceScaleFactor();
1326}
1327
1328void WebPage::setUseFixedLayout(bool fixed)
1329{
1330    // Do not overwrite current settings if initially setting it to false.
1331    if (m_useFixedLayout == fixed)
1332        return;
1333    m_useFixedLayout = fixed;
1334
1335    m_page->settings()->setFixedElementsLayoutRelativeToFrame(fixed);
1336#if USE(COORDINATED_GRAPHICS)
1337    m_page->settings()->setAcceleratedCompositingForFixedPositionEnabled(fixed);
1338    m_page->settings()->setFixedPositionCreatesStackingContext(fixed);
1339    m_page->settings()->setApplyPageScaleFactorInCompositor(fixed);
1340    m_page->settings()->setScrollingCoordinatorEnabled(fixed);
1341#endif
1342
1343#if USE(TILED_BACKING_STORE) && ENABLE(SMOOTH_SCROLLING)
1344    // Delegated scrolling will be enabled when the FrameView is created if fixed layout is enabled.
1345    // Ensure we don't do animated scrolling in the WebProcess in that case.
1346    m_page->settings()->setScrollAnimatorEnabled(!fixed);
1347#endif
1348
1349    FrameView* view = mainFrameView();
1350    if (!view)
1351        return;
1352
1353#if USE(TILED_BACKING_STORE)
1354    view->setDelegatesScrolling(fixed);
1355    view->setPaintsEntireContents(fixed);
1356#endif
1357    view->setUseFixedLayout(fixed);
1358    if (!fixed)
1359        setFixedLayoutSize(IntSize());
1360}
1361
1362void WebPage::setFixedLayoutSize(const IntSize& size)
1363{
1364    FrameView* view = mainFrameView();
1365    if (!view || view->fixedLayoutSize() == size)
1366        return;
1367
1368    view->setFixedLayoutSize(size);
1369    // Do not force it until the first layout, this would then become our first layout prematurely.
1370    if (view->didFirstLayout())
1371        view->forceLayout();
1372}
1373
1374void WebPage::listenForLayoutMilestones(uint32_t milestones)
1375{
1376    if (!m_page)
1377        return;
1378    m_page->addLayoutMilestones(static_cast<LayoutMilestones>(milestones));
1379}
1380
1381void WebPage::setSuppressScrollbarAnimations(bool suppressAnimations)
1382{
1383    m_page->setShouldSuppressScrollbarAnimations(suppressAnimations);
1384}
1385
1386void WebPage::setRubberBandsAtBottom(bool rubberBandsAtBottom)
1387{
1388    m_page->setRubberBandsAtBottom(rubberBandsAtBottom);
1389}
1390
1391void WebPage::setRubberBandsAtTop(bool rubberBandsAtTop)
1392{
1393    m_page->setRubberBandsAtTop(rubberBandsAtTop);
1394}
1395
1396void WebPage::setPaginationMode(uint32_t mode)
1397{
1398    Pagination pagination = m_page->pagination();
1399    pagination.mode = static_cast<Pagination::Mode>(mode);
1400    m_page->setPagination(pagination);
1401}
1402
1403void WebPage::setPaginationBehavesLikeColumns(bool behavesLikeColumns)
1404{
1405    Pagination pagination = m_page->pagination();
1406    pagination.behavesLikeColumns = behavesLikeColumns;
1407    m_page->setPagination(pagination);
1408}
1409
1410void WebPage::setPageLength(double pageLength)
1411{
1412    Pagination pagination = m_page->pagination();
1413    pagination.pageLength = pageLength;
1414    m_page->setPagination(pagination);
1415}
1416
1417void WebPage::setGapBetweenPages(double gap)
1418{
1419    Pagination pagination = m_page->pagination();
1420    pagination.gap = gap;
1421    m_page->setPagination(pagination);
1422}
1423
1424void WebPage::postInjectedBundleMessage(const String& messageName, CoreIPC::MessageDecoder& decoder)
1425{
1426    InjectedBundle* injectedBundle = WebProcess::shared().injectedBundle();
1427    if (!injectedBundle)
1428        return;
1429
1430    RefPtr<APIObject> messageBody;
1431    InjectedBundleUserMessageDecoder messageBodyDecoder(messageBody);
1432    if (!decoder.decode(messageBodyDecoder))
1433        return;
1434
1435    injectedBundle->didReceiveMessageToPage(this, messageName, messageBody.get());
1436}
1437
1438void WebPage::installPageOverlay(PassRefPtr<PageOverlay> pageOverlay, bool shouldFadeIn)
1439{
1440    RefPtr<PageOverlay> overlay = pageOverlay;
1441
1442    if (m_pageOverlays.contains(overlay.get()))
1443        return;
1444
1445    m_pageOverlays.append(overlay);
1446    overlay->setPage(this);
1447
1448    if (shouldFadeIn)
1449        overlay->startFadeInAnimation();
1450
1451    m_drawingArea->didInstallPageOverlay(overlay.get());
1452}
1453
1454void WebPage::uninstallPageOverlay(PageOverlay* pageOverlay, bool shouldFadeOut)
1455{
1456    size_t existingOverlayIndex = m_pageOverlays.find(pageOverlay);
1457    if (existingOverlayIndex == notFound)
1458        return;
1459
1460    if (shouldFadeOut) {
1461        pageOverlay->startFadeOutAnimation();
1462        return;
1463    }
1464
1465    pageOverlay->setPage(0);
1466    m_pageOverlays.remove(existingOverlayIndex);
1467
1468    m_drawingArea->didUninstallPageOverlay(pageOverlay);
1469}
1470
1471void WebPage::setHeaderPageBanner(PassRefPtr<PageBanner> pageBanner)
1472{
1473    if (m_headerBanner)
1474        m_headerBanner->detachFromPage();
1475
1476    m_headerBanner = pageBanner;
1477
1478    if (m_headerBanner)
1479        m_headerBanner->addToPage(PageBanner::Header, this);
1480}
1481
1482PageBanner* WebPage::headerPageBanner()
1483{
1484    return m_headerBanner.get();
1485}
1486
1487void WebPage::setFooterPageBanner(PassRefPtr<PageBanner> pageBanner)
1488{
1489    if (m_footerBanner)
1490        m_footerBanner->detachFromPage();
1491
1492    m_footerBanner = pageBanner;
1493
1494    if (m_footerBanner)
1495        m_footerBanner->addToPage(PageBanner::Footer, this);
1496}
1497
1498PageBanner* WebPage::footerPageBanner()
1499{
1500    return m_footerBanner.get();
1501}
1502
1503void WebPage::hidePageBanners()
1504{
1505    if (m_headerBanner)
1506        m_headerBanner->hide();
1507    if (m_footerBanner)
1508        m_footerBanner->hide();
1509}
1510
1511void WebPage::showPageBanners()
1512{
1513    if (m_headerBanner)
1514        m_headerBanner->showIfHidden();
1515    if (m_footerBanner)
1516        m_footerBanner->showIfHidden();
1517}
1518
1519PassRefPtr<WebImage> WebPage::scaledSnapshotWithOptions(const IntRect& rect, double scaleFactor, SnapshotOptions options)
1520{
1521    Frame* coreFrame = m_mainFrame->coreFrame();
1522    if (!coreFrame)
1523        return 0;
1524
1525    FrameView* frameView = coreFrame->view();
1526    if (!frameView)
1527        return 0;
1528
1529    IntSize bitmapSize = rect.size();
1530    float combinedScaleFactor = scaleFactor * corePage()->deviceScaleFactor();
1531    bitmapSize.scale(combinedScaleFactor);
1532
1533    RefPtr<WebImage> snapshot = WebImage::create(bitmapSize, snapshotOptionsToImageOptions(options));
1534    if (!snapshot->bitmap())
1535        return 0;
1536
1537    OwnPtr<WebCore::GraphicsContext> graphicsContext = snapshot->bitmap()->createGraphicsContext();
1538
1539    graphicsContext->clearRect(IntRect(IntPoint(), bitmapSize));
1540
1541    graphicsContext->applyDeviceScaleFactor(combinedScaleFactor);
1542    graphicsContext->translate(-rect.x(), -rect.y());
1543
1544    FrameView::SelectionInSnaphot shouldPaintSelection = FrameView::IncludeSelection;
1545    if (options & SnapshotOptionsExcludeSelectionHighlighting)
1546        shouldPaintSelection = FrameView::ExcludeSelection;
1547
1548    FrameView::CoordinateSpaceForSnapshot coordinateSpace = FrameView::DocumentCoordinates;
1549    if (options & SnapshotOptionsInViewCoordinates)
1550        coordinateSpace = FrameView::ViewCoordinates;
1551
1552    frameView->paintContentsForSnapshot(graphicsContext.get(), rect, shouldPaintSelection, coordinateSpace);
1553
1554    if (options & SnapshotOptionsPaintSelectionRectangle) {
1555        FloatRect selectionRectangle = m_mainFrame->coreFrame()->selection()->bounds();
1556        graphicsContext->setStrokeColor(Color(0xFF, 0, 0), ColorSpaceDeviceRGB);
1557        graphicsContext->strokeRect(selectionRectangle, 1);
1558    }
1559
1560    return snapshot.release();
1561}
1562
1563void WebPage::pageDidScroll()
1564{
1565    m_uiClient.pageDidScroll(this);
1566
1567    send(Messages::WebPageProxy::PageDidScroll());
1568}
1569
1570#if USE(TILED_BACKING_STORE)
1571void WebPage::pageDidRequestScroll(const IntPoint& point)
1572{
1573    send(Messages::WebPageProxy::PageDidRequestScroll(point));
1574}
1575#endif
1576
1577#if ENABLE(CONTEXT_MENUS)
1578WebContextMenu* WebPage::contextMenu()
1579{
1580    if (!m_contextMenu)
1581        m_contextMenu = WebContextMenu::create(this);
1582    return m_contextMenu.get();
1583}
1584
1585WebContextMenu* WebPage::contextMenuAtPointInWindow(const IntPoint& point)
1586{
1587    corePage()->contextMenuController()->clearContextMenu();
1588
1589    // Simulate a mouse click to generate the correct menu.
1590    PlatformMouseEvent mouseEvent(point, point, RightButton, PlatformEvent::MousePressed, 1, false, false, false, false, currentTime());
1591    bool handled = corePage()->mainFrame()->eventHandler()->sendContextMenuEvent(mouseEvent);
1592    if (!handled)
1593        return 0;
1594
1595    return contextMenu();
1596}
1597#endif
1598
1599// Events
1600
1601static const WebEvent* g_currentEvent = 0;
1602
1603// FIXME: WebPage::currentEvent is used by the plug-in code to avoid having to convert from DOM events back to
1604// WebEvents. When we get the event handling sorted out, this should go away and the Widgets should get the correct
1605// platform events passed to the event handler code.
1606const WebEvent* WebPage::currentEvent()
1607{
1608    return g_currentEvent;
1609}
1610
1611class CurrentEvent {
1612public:
1613    explicit CurrentEvent(const WebEvent& event)
1614        : m_previousCurrentEvent(g_currentEvent)
1615    {
1616        g_currentEvent = &event;
1617    }
1618
1619    ~CurrentEvent()
1620    {
1621        g_currentEvent = m_previousCurrentEvent;
1622    }
1623
1624private:
1625    const WebEvent* m_previousCurrentEvent;
1626};
1627
1628#if ENABLE(CONTEXT_MENUS)
1629static bool isContextClick(const PlatformMouseEvent& event)
1630{
1631    if (event.button() == WebCore::RightButton)
1632        return true;
1633
1634#if PLATFORM(MAC)
1635    // FIXME: this really should be about OSX-style UI, not about the Mac port
1636    if (event.button() == WebCore::LeftButton && event.ctrlKey())
1637        return true;
1638#endif
1639
1640    return false;
1641}
1642
1643static bool handleContextMenuEvent(const PlatformMouseEvent& platformMouseEvent, WebPage* page)
1644{
1645    IntPoint point = page->corePage()->mainFrame()->view()->windowToContents(platformMouseEvent.position());
1646    HitTestResult result = page->corePage()->mainFrame()->eventHandler()->hitTestResultAtPoint(point);
1647
1648    Frame* frame = page->corePage()->mainFrame();
1649    if (result.innerNonSharedNode())
1650        frame = result.innerNonSharedNode()->document()->frame();
1651
1652    bool handled = frame->eventHandler()->sendContextMenuEvent(platformMouseEvent);
1653    if (handled)
1654        page->contextMenu()->show();
1655
1656    return handled;
1657}
1658#endif
1659
1660static bool handleMouseEvent(const WebMouseEvent& mouseEvent, WebPage* page, bool onlyUpdateScrollbars)
1661{
1662    Frame* frame = page->corePage()->mainFrame();
1663    if (!frame->view())
1664        return false;
1665
1666    PlatformMouseEvent platformMouseEvent = platform(mouseEvent);
1667
1668    switch (platformMouseEvent.type()) {
1669        case PlatformEvent::MousePressed: {
1670#if ENABLE(CONTEXT_MENUS)
1671            if (isContextClick(platformMouseEvent))
1672                page->corePage()->contextMenuController()->clearContextMenu();
1673#endif
1674
1675            bool handled = frame->eventHandler()->handleMousePressEvent(platformMouseEvent);
1676#if ENABLE(CONTEXT_MENUS)
1677            if (isContextClick(platformMouseEvent))
1678                handled = handleContextMenuEvent(platformMouseEvent, page);
1679#endif
1680            return handled;
1681        }
1682        case PlatformEvent::MouseReleased:
1683            return frame->eventHandler()->handleMouseReleaseEvent(platformMouseEvent);
1684
1685        case PlatformEvent::MouseMoved:
1686            if (onlyUpdateScrollbars)
1687                return frame->eventHandler()->passMouseMovedEventToScrollbars(platformMouseEvent);
1688            return frame->eventHandler()->mouseMoved(platformMouseEvent);
1689        default:
1690            ASSERT_NOT_REACHED();
1691            return false;
1692    }
1693}
1694
1695void WebPage::mouseEvent(const WebMouseEvent& mouseEvent)
1696{
1697#if ENABLE(CONTEXT_MENUS)
1698    // Don't try to handle any pending mouse events if a context menu is showing.
1699    if (m_isShowingContextMenu) {
1700        send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(mouseEvent.type()), false));
1701        return;
1702    }
1703#endif
1704    bool handled = false;
1705    if (m_pageOverlays.size()) {
1706        // Let the page overlay handle the event.
1707        PageOverlayList::reverse_iterator end = m_pageOverlays.rend();
1708        for (PageOverlayList::reverse_iterator it = m_pageOverlays.rbegin(); it != end; ++it)
1709            if ((handled = (*it)->mouseEvent(mouseEvent)))
1710                break;
1711    }
1712
1713    if (!handled && m_headerBanner)
1714        handled = m_headerBanner->mouseEvent(mouseEvent);
1715    if (!handled && m_footerBanner)
1716        handled = m_footerBanner->mouseEvent(mouseEvent);
1717
1718    if (!handled && canHandleUserEvents()) {
1719        CurrentEvent currentEvent(mouseEvent);
1720
1721        // We need to do a full, normal hit test during this mouse event if the page is active or if a mouse
1722        // button is currently pressed. It is possible that neither of those things will be true since on
1723        // Lion when legacy scrollbars are enabled, WebKit receives mouse events all the time. If it is one
1724        // of those cases where the page is not active and the mouse is not pressed, then we can fire a more
1725        // efficient scrollbars-only version of the event.
1726        bool onlyUpdateScrollbars = !(m_page->focusController()->isActive() || (mouseEvent.button() != WebMouseEvent::NoButton));
1727        handled = handleMouseEvent(mouseEvent, this, onlyUpdateScrollbars);
1728    }
1729
1730    send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(mouseEvent.type()), handled));
1731}
1732
1733void WebPage::mouseEventSyncForTesting(const WebMouseEvent& mouseEvent, bool& handled)
1734{
1735    handled = false;
1736
1737    if (m_pageOverlays.size()) {
1738        PageOverlayList::reverse_iterator end = m_pageOverlays.rend();
1739        for (PageOverlayList::reverse_iterator it = m_pageOverlays.rbegin(); it != end; ++it)
1740            if ((handled = (*it)->mouseEvent(mouseEvent)))
1741                break;
1742    }
1743    if (!handled && m_headerBanner)
1744        handled = m_headerBanner->mouseEvent(mouseEvent);
1745    if (!handled && m_footerBanner)
1746        handled = m_footerBanner->mouseEvent(mouseEvent);
1747
1748    if (!handled) {
1749        CurrentEvent currentEvent(mouseEvent);
1750
1751        // We need to do a full, normal hit test during this mouse event if the page is active or if a mouse
1752        // button is currently pressed. It is possible that neither of those things will be true since on
1753        // Lion when legacy scrollbars are enabled, WebKit receives mouse events all the time. If it is one
1754        // of those cases where the page is not active and the mouse is not pressed, then we can fire a more
1755        // efficient scrollbars-only version of the event.
1756        bool onlyUpdateScrollbars = !(m_page->focusController()->isActive() || (mouseEvent.button() != WebMouseEvent::NoButton));
1757        handled = handleMouseEvent(mouseEvent, this, onlyUpdateScrollbars);
1758    }
1759}
1760
1761static bool handleWheelEvent(const WebWheelEvent& wheelEvent, Page* page)
1762{
1763    Frame* frame = page->mainFrame();
1764    if (!frame->view())
1765        return false;
1766
1767    PlatformWheelEvent platformWheelEvent = platform(wheelEvent);
1768    return frame->eventHandler()->handleWheelEvent(platformWheelEvent);
1769}
1770
1771void WebPage::wheelEvent(const WebWheelEvent& wheelEvent)
1772{
1773    bool handled = false;
1774
1775    if (canHandleUserEvents()) {
1776        CurrentEvent currentEvent(wheelEvent);
1777
1778        handled = handleWheelEvent(wheelEvent, m_page.get());
1779    }
1780    send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(wheelEvent.type()), handled));
1781}
1782
1783void WebPage::wheelEventSyncForTesting(const WebWheelEvent& wheelEvent, bool& handled)
1784{
1785    CurrentEvent currentEvent(wheelEvent);
1786
1787    handled = handleWheelEvent(wheelEvent, m_page.get());
1788}
1789
1790static bool handleKeyEvent(const WebKeyboardEvent& keyboardEvent, Page* page)
1791{
1792    if (!page->mainFrame()->view())
1793        return false;
1794
1795    if (keyboardEvent.type() == WebEvent::Char && keyboardEvent.isSystemKey())
1796        return page->focusController()->focusedOrMainFrame()->eventHandler()->handleAccessKey(platform(keyboardEvent));
1797    return page->focusController()->focusedOrMainFrame()->eventHandler()->keyEvent(platform(keyboardEvent));
1798}
1799
1800void WebPage::keyEvent(const WebKeyboardEvent& keyboardEvent)
1801{
1802    bool handled = false;
1803
1804    if (canHandleUserEvents()) {
1805        CurrentEvent currentEvent(keyboardEvent);
1806
1807        handled = handleKeyEvent(keyboardEvent, m_page.get());
1808        // FIXME: Platform default behaviors should be performed during normal DOM event dispatch (in most cases, in default keydown event handler).
1809        if (!handled)
1810            handled = performDefaultBehaviorForKeyEvent(keyboardEvent);
1811    }
1812    send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(keyboardEvent.type()), handled));
1813}
1814
1815void WebPage::keyEventSyncForTesting(const WebKeyboardEvent& keyboardEvent, bool& handled)
1816{
1817    CurrentEvent currentEvent(keyboardEvent);
1818
1819    handled = handleKeyEvent(keyboardEvent, m_page.get());
1820    if (!handled)
1821        handled = performDefaultBehaviorForKeyEvent(keyboardEvent);
1822}
1823
1824#if ENABLE(GESTURE_EVENTS)
1825static bool handleGestureEvent(const WebGestureEvent& gestureEvent, Page* page)
1826{
1827    Frame* frame = page->mainFrame();
1828    if (!frame->view())
1829        return false;
1830
1831    PlatformGestureEvent platformGestureEvent = platform(gestureEvent);
1832    return frame->eventHandler()->handleGestureEvent(platformGestureEvent);
1833}
1834
1835void WebPage::gestureEvent(const WebGestureEvent& gestureEvent)
1836{
1837    bool handled = false;
1838
1839    if (canHandleUserEvents()) {
1840        CurrentEvent currentEvent(gestureEvent);
1841
1842        handled = handleGestureEvent(gestureEvent, m_page.get());
1843    }
1844    send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(gestureEvent.type()), handled));
1845}
1846#endif
1847
1848WKTypeRef WebPage::pageOverlayCopyAccessibilityAttributeValue(WKStringRef attribute, WKTypeRef parameter)
1849{
1850    if (!m_pageOverlays.size())
1851        return 0;
1852    PageOverlayList::reverse_iterator end = m_pageOverlays.rend();
1853    for (PageOverlayList::reverse_iterator it = m_pageOverlays.rbegin(); it != end; ++it) {
1854        WKTypeRef value = (*it)->copyAccessibilityAttributeValue(attribute, parameter);
1855        if (value)
1856            return value;
1857    }
1858    return 0;
1859}
1860
1861WKArrayRef WebPage::pageOverlayCopyAccessibilityAttributesNames(bool parameterizedNames)
1862{
1863    if (!m_pageOverlays.size())
1864        return 0;
1865    PageOverlayList::reverse_iterator end = m_pageOverlays.rend();
1866    for (PageOverlayList::reverse_iterator it = m_pageOverlays.rbegin(); it != end; ++it) {
1867        WKArrayRef value = (*it)->copyAccessibilityAttributeNames(parameterizedNames);
1868        if (value)
1869            return value;
1870    }
1871    return 0;
1872}
1873
1874void WebPage::validateCommand(const String& commandName, uint64_t callbackID)
1875{
1876    bool isEnabled = false;
1877    int32_t state = 0;
1878    Frame* frame = m_page->focusController()->focusedOrMainFrame();
1879    if (frame) {
1880        if (PluginView* pluginView = focusedPluginViewForFrame(frame))
1881            isEnabled = pluginView->isEditingCommandEnabled(commandName);
1882        else {
1883            Editor::Command command = frame->editor().command(commandName);
1884            state = command.state();
1885            isEnabled = command.isSupported() && command.isEnabled();
1886        }
1887    }
1888
1889    send(Messages::WebPageProxy::ValidateCommandCallback(commandName, isEnabled, state, callbackID));
1890}
1891
1892void WebPage::executeEditCommand(const String& commandName)
1893{
1894    executeEditingCommand(commandName, String());
1895}
1896
1897uint64_t WebPage::restoreSession(const SessionState& sessionState)
1898{
1899    const BackForwardListItemVector& list = sessionState.list();
1900    size_t size = list.size();
1901    uint64_t currentItemID = 0;
1902    for (size_t i = 0; i < size; ++i) {
1903        WebBackForwardListItem* webItem = list[i].get();
1904        DecoderAdapter decoder(webItem->backForwardData().data(), webItem->backForwardData().size());
1905
1906        RefPtr<HistoryItem> item = HistoryItem::decodeBackForwardTree(webItem->url(), webItem->title(), webItem->originalURL(), decoder);
1907        if (!item) {
1908            LOG_ERROR("Failed to decode a HistoryItem from session state data.");
1909            return 0;
1910        }
1911
1912        if (i == sessionState.currentIndex())
1913            currentItemID = webItem->itemID();
1914
1915        WebBackForwardListProxy::addItemFromUIProcess(list[i]->itemID(), item.release());
1916    }
1917    ASSERT(currentItemID);
1918    return currentItemID;
1919}
1920
1921void WebPage::restoreSessionAndNavigateToCurrentItem(const SessionState& sessionState)
1922{
1923    if (uint64_t currentItemID = restoreSession(sessionState))
1924        goToBackForwardItem(currentItemID);
1925}
1926
1927#if ENABLE(TOUCH_EVENTS)
1928#if PLATFORM(QT)
1929void WebPage::highlightPotentialActivation(const IntPoint& point, const IntSize& area)
1930{
1931    if (point == IntPoint::zero()) {
1932        // An empty point deactivates the highlighting.
1933        tapHighlightController().hideHighlight();
1934    } else {
1935        Frame* mainframe = m_page->mainFrame();
1936        Node* activationNode = 0;
1937        Node* adjustedNode = 0;
1938        IntPoint adjustedPoint;
1939
1940#if ENABLE(TOUCH_ADJUSTMENT)
1941        if (!mainframe->eventHandler()->bestClickableNodeForTouchPoint(point, IntSize(area.width() / 2, area.height() / 2), adjustedPoint, adjustedNode))
1942            return;
1943
1944#else
1945        HitTestResult result = mainframe->eventHandler()->hitTestResultAtPoint(mainframe->view()->windowToContents(point), HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowShadowContent);
1946        adjustedNode = result.innerNode();
1947#endif
1948        // Find the node to highlight. This is not the same as the node responding the tap gesture, because many
1949        // pages has a global click handler and we do not want to highlight the body.
1950        for (Node* node = adjustedNode; node; node = node->parentOrShadowHostNode()) {
1951            if (node->isDocumentNode() || node->isFrameOwnerElement())
1952                break;
1953
1954            // We always highlight focusable (form-elements), image links or content-editable elements.
1955            if ((node->isElementNode() && toElement(node)->isMouseFocusable()) || node->isLink() || node->isContentEditable())
1956                activationNode = node;
1957            else if (node->willRespondToMouseClickEvents()) {
1958                // Highlight elements with default mouse-click handlers, but highlight only inline elements with
1959                // scripted event-handlers.
1960                if (!node->Node::willRespondToMouseClickEvents() || (node->renderer() && node->renderer()->isInline()))
1961                    activationNode = node;
1962            }
1963
1964            if (activationNode)
1965                break;
1966        }
1967
1968        if (activationNode)
1969            tapHighlightController().highlight(activationNode);
1970    }
1971}
1972#endif
1973
1974static bool handleTouchEvent(const WebTouchEvent& touchEvent, Page* page)
1975{
1976    Frame* frame = page->mainFrame();
1977    if (!frame->view())
1978        return false;
1979
1980    return frame->eventHandler()->handleTouchEvent(platform(touchEvent));
1981}
1982
1983void WebPage::touchEvent(const WebTouchEvent& touchEvent)
1984{
1985    bool handled = false;
1986
1987    if (canHandleUserEvents()) {
1988        CurrentEvent currentEvent(touchEvent);
1989
1990        handled = handleTouchEvent(touchEvent, m_page.get());
1991    }
1992    send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(touchEvent.type()), handled));
1993}
1994
1995void WebPage::touchEventSyncForTesting(const WebTouchEvent& touchEvent, bool& handled)
1996{
1997    CurrentEvent currentEvent(touchEvent);
1998    handled = handleTouchEvent(touchEvent, m_page.get());
1999}
2000#endif
2001
2002bool WebPage::scroll(Page* page, ScrollDirection direction, ScrollGranularity granularity)
2003{
2004    return page->focusController()->focusedOrMainFrame()->eventHandler()->scrollRecursively(direction, granularity);
2005}
2006
2007bool WebPage::logicalScroll(Page* page, ScrollLogicalDirection direction, ScrollGranularity granularity)
2008{
2009    return page->focusController()->focusedOrMainFrame()->eventHandler()->logicalScrollRecursively(direction, granularity);
2010}
2011
2012bool WebPage::scrollBy(uint32_t scrollDirection, uint32_t scrollGranularity)
2013{
2014    return scroll(m_page.get(), static_cast<ScrollDirection>(scrollDirection), static_cast<ScrollGranularity>(scrollGranularity));
2015}
2016
2017void WebPage::centerSelectionInVisibleArea()
2018{
2019    Frame* frame = m_page->focusController()->focusedOrMainFrame();
2020    if (!frame)
2021        return;
2022
2023    frame->selection()->revealSelection(ScrollAlignment::alignCenterAlways);
2024    m_findController.showFindIndicatorInSelection();
2025}
2026
2027void WebPage::setActive(bool isActive)
2028{
2029    m_page->focusController()->setActive(isActive);
2030
2031#if PLATFORM(MAC)
2032    // Tell all our plug-in views that the window focus changed.
2033    for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
2034        (*it)->setWindowIsFocused(isActive);
2035#endif
2036}
2037
2038void WebPage::setDrawsBackground(bool drawsBackground)
2039{
2040    if (m_drawsBackground == drawsBackground)
2041        return;
2042
2043    m_drawsBackground = drawsBackground;
2044
2045    for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
2046        if (FrameView* view = coreFrame->view())
2047            view->setTransparent(!drawsBackground);
2048    }
2049
2050    m_drawingArea->pageBackgroundTransparencyChanged();
2051    m_drawingArea->setNeedsDisplay();
2052}
2053
2054void WebPage::setDrawsTransparentBackground(bool drawsTransparentBackground)
2055{
2056    if (m_drawsTransparentBackground == drawsTransparentBackground)
2057        return;
2058
2059    m_drawsTransparentBackground = drawsTransparentBackground;
2060
2061    Color backgroundColor = drawsTransparentBackground ? Color::transparent : Color::white;
2062    for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
2063        if (FrameView* view = coreFrame->view())
2064            view->setBaseBackgroundColor(backgroundColor);
2065    }
2066
2067    m_drawingArea->pageBackgroundTransparencyChanged();
2068    m_drawingArea->setNeedsDisplay();
2069}
2070
2071void WebPage::viewWillStartLiveResize()
2072{
2073    if (!m_page)
2074        return;
2075
2076    // FIXME: This should propagate to all ScrollableAreas.
2077    if (Frame* frame = m_page->focusController()->focusedOrMainFrame()) {
2078        if (FrameView* view = frame->view())
2079            view->willStartLiveResize();
2080    }
2081}
2082
2083void WebPage::viewWillEndLiveResize()
2084{
2085    if (!m_page)
2086        return;
2087
2088    // FIXME: This should propagate to all ScrollableAreas.
2089    if (Frame* frame = m_page->focusController()->focusedOrMainFrame()) {
2090        if (FrameView* view = frame->view())
2091            view->willEndLiveResize();
2092    }
2093}
2094
2095void WebPage::setFocused(bool isFocused)
2096{
2097    m_page->focusController()->setFocused(isFocused);
2098}
2099
2100void WebPage::setInitialFocus(bool forward, bool isKeyboardEventValid, const WebKeyboardEvent& event)
2101{
2102    if (!m_page || !m_page->focusController())
2103        return;
2104
2105    Frame* frame = m_page->focusController()->focusedOrMainFrame();
2106    frame->document()->setFocusedElement(0);
2107
2108    if (isKeyboardEventValid && event.type() == WebEvent::KeyDown) {
2109        PlatformKeyboardEvent platformEvent(platform(event));
2110        platformEvent.disambiguateKeyDownEvent(PlatformEvent::RawKeyDown);
2111        m_page->focusController()->setInitialFocus(forward ? FocusDirectionForward : FocusDirectionBackward, KeyboardEvent::create(platformEvent, frame->document()->defaultView()).get());
2112        return;
2113    }
2114
2115    m_page->focusController()->setInitialFocus(forward ? FocusDirectionForward : FocusDirectionBackward, 0);
2116}
2117
2118void WebPage::setWindowResizerSize(const IntSize& windowResizerSize)
2119{
2120    if (m_windowResizerSize == windowResizerSize)
2121        return;
2122
2123    m_windowResizerSize = windowResizerSize;
2124
2125    for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
2126        FrameView* view = coreFrame->view();
2127        if (view)
2128            view->windowResizerRectChanged();
2129    }
2130}
2131
2132void WebPage::setCanStartMediaTimerFired()
2133{
2134    if (m_page)
2135        m_page->setCanStartMedia(true);
2136}
2137
2138#if !PLATFORM(MAC)
2139void WebPage::didUpdateInWindowStateTimerFired()
2140{
2141    send(Messages::WebPageProxy::DidUpdateInWindowState());
2142}
2143#endif
2144
2145inline bool WebPage::canHandleUserEvents() const
2146{
2147#if USE(TILED_BACKING_STORE)
2148    // Should apply only if the area was frozen by didStartPageTransition().
2149    return !m_drawingArea->layerTreeStateIsFrozen();
2150#endif
2151    return true;
2152}
2153
2154void WebPage::setIsInWindow(bool isInWindow, bool wantsDidUpdateViewInWindowState)
2155{
2156    bool pageWasInWindow = m_page->isInWindow();
2157
2158    if (!isInWindow) {
2159        m_setCanStartMediaTimer.stop();
2160        m_page->setCanStartMedia(false);
2161        m_page->willMoveOffscreen();
2162
2163        if (pageWasInWindow)
2164            WebProcess::shared().pageWillLeaveWindow(m_pageID);
2165    } else {
2166        // Defer the call to Page::setCanStartMedia() since it ends up sending a synchronous message to the UI process
2167        // in order to get plug-in connections, and the UI process will be waiting for the Web process to update the backing
2168        // store after moving the view into a window, until it times out and paints white. See <rdar://problem/9242771>.
2169        if (m_mayStartMediaWhenInWindow)
2170            m_setCanStartMediaTimer.startOneShot(0);
2171
2172        m_page->didMoveOnscreen();
2173
2174        if (!pageWasInWindow)
2175            WebProcess::shared().pageDidEnterWindow(m_pageID);
2176    }
2177
2178    m_page->setIsInWindow(isInWindow);
2179
2180    if (wantsDidUpdateViewInWindowState)
2181        m_sendDidUpdateInWindowStateTimer.startOneShot(0);
2182}
2183
2184void WebPage::didReceivePolicyDecision(uint64_t frameID, uint64_t listenerID, uint32_t policyAction, uint64_t downloadID)
2185{
2186    WebFrame* frame = WebProcess::shared().webFrame(frameID);
2187    if (!frame)
2188        return;
2189    frame->didReceivePolicyDecision(listenerID, static_cast<PolicyAction>(policyAction), downloadID);
2190}
2191
2192void WebPage::didStartPageTransition()
2193{
2194    m_drawingArea->setLayerTreeStateIsFrozen(true);
2195}
2196
2197void WebPage::didCompletePageTransition()
2198{
2199#if USE(TILED_BACKING_STORE)
2200    if (m_mainFrame->coreFrame()->view()->delegatesScrolling())
2201        // Wait until the UI process sent us the visible rect it wants rendered.
2202        send(Messages::WebPageProxy::PageTransitionViewportReady());
2203    else
2204#endif
2205
2206    m_drawingArea->setLayerTreeStateIsFrozen(false);
2207}
2208
2209void WebPage::show()
2210{
2211    send(Messages::WebPageProxy::ShowPage());
2212}
2213
2214void WebPage::setUserAgent(const String& userAgent)
2215{
2216    m_userAgent = userAgent;
2217}
2218
2219void WebPage::suspendActiveDOMObjectsAndAnimations()
2220{
2221    m_page->suspendActiveDOMObjectsAndAnimations();
2222}
2223
2224void WebPage::resumeActiveDOMObjectsAndAnimations()
2225{
2226    m_page->resumeActiveDOMObjectsAndAnimations();
2227}
2228
2229IntPoint WebPage::screenToWindow(const IntPoint& point)
2230{
2231    IntPoint windowPoint;
2232    sendSync(Messages::WebPageProxy::ScreenToWindow(point), Messages::WebPageProxy::ScreenToWindow::Reply(windowPoint));
2233    return windowPoint;
2234}
2235
2236IntRect WebPage::windowToScreen(const IntRect& rect)
2237{
2238    IntRect screenRect;
2239    sendSync(Messages::WebPageProxy::WindowToScreen(rect), Messages::WebPageProxy::WindowToScreen::Reply(screenRect));
2240    return screenRect;
2241}
2242
2243IntRect WebPage::windowResizerRect() const
2244{
2245    if (m_windowResizerSize.isEmpty())
2246        return IntRect();
2247
2248    IntSize frameViewSize;
2249    if (Frame* coreFrame = m_mainFrame->coreFrame()) {
2250        if (FrameView* view = coreFrame->view())
2251            frameViewSize = view->size();
2252    }
2253
2254    return IntRect(frameViewSize.width() - m_windowResizerSize.width(), frameViewSize.height() - m_windowResizerSize.height(),
2255                   m_windowResizerSize.width(), m_windowResizerSize.height());
2256}
2257
2258KeyboardUIMode WebPage::keyboardUIMode()
2259{
2260    bool fullKeyboardAccessEnabled = WebProcess::shared().fullKeyboardAccessEnabled();
2261    return static_cast<KeyboardUIMode>((fullKeyboardAccessEnabled ? KeyboardAccessFull : KeyboardAccessDefault) | (m_tabToLinks ? KeyboardAccessTabsToLinks : 0));
2262}
2263
2264void WebPage::runJavaScriptInMainFrame(const String& script, uint64_t callbackID)
2265{
2266    // NOTE: We need to be careful when running scripts that the objects we depend on don't
2267    // disappear during script execution.
2268
2269    // Retain the SerializedScriptValue at this level so it (and the internal data) lives
2270    // long enough for the DataReference to be encoded by the sent message.
2271    RefPtr<SerializedScriptValue> serializedResultValue;
2272    CoreIPC::DataReference dataReference;
2273
2274    JSLockHolder lock(JSDOMWindow::commonVM());
2275    if (JSValue resultValue = m_mainFrame->coreFrame()->script()->executeScript(script, true).jsValue()) {
2276        if ((serializedResultValue = SerializedScriptValue::create(m_mainFrame->jsContext(), toRef(m_mainFrame->coreFrame()->script()->globalObject(mainThreadNormalWorld())->globalExec(), resultValue), 0)))
2277            dataReference = serializedResultValue->data();
2278    }
2279
2280    send(Messages::WebPageProxy::ScriptValueCallback(dataReference, callbackID));
2281}
2282
2283void WebPage::getContentsAsString(uint64_t callbackID)
2284{
2285    String resultString = m_mainFrame->contentsAsString();
2286    send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
2287}
2288
2289#if ENABLE(MHTML)
2290void WebPage::getContentsAsMHTMLData(uint64_t callbackID, bool useBinaryEncoding)
2291{
2292    CoreIPC::DataReference dataReference;
2293
2294    RefPtr<SharedBuffer> buffer = useBinaryEncoding
2295        ? MHTMLArchive::generateMHTMLDataUsingBinaryEncoding(m_page.get())
2296        : MHTMLArchive::generateMHTMLData(m_page.get());
2297
2298    if (buffer)
2299        dataReference = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size());
2300
2301    send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
2302}
2303#endif
2304
2305void WebPage::getRenderTreeExternalRepresentation(uint64_t callbackID)
2306{
2307    String resultString = renderTreeExternalRepresentation();
2308    send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
2309}
2310
2311static Frame* frameWithSelection(Page* page)
2312{
2313    for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
2314        if (frame->selection()->isRange())
2315            return frame;
2316    }
2317
2318    return 0;
2319}
2320
2321void WebPage::getSelectionAsWebArchiveData(uint64_t callbackID)
2322{
2323    CoreIPC::DataReference dataReference;
2324
2325#if PLATFORM(MAC)
2326    RefPtr<LegacyWebArchive> archive;
2327    RetainPtr<CFDataRef> data;
2328
2329    Frame* frame = frameWithSelection(m_page.get());
2330    if (frame) {
2331        archive = LegacyWebArchive::createFromSelection(frame);
2332        data = archive->rawDataRepresentation();
2333        dataReference = CoreIPC::DataReference(CFDataGetBytePtr(data.get()), CFDataGetLength(data.get()));
2334    }
2335#endif
2336
2337    send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
2338}
2339
2340void WebPage::getSelectionOrContentsAsString(uint64_t callbackID)
2341{
2342    String resultString = m_mainFrame->selectionAsString();
2343    if (resultString.isEmpty())
2344        resultString = m_mainFrame->contentsAsString();
2345    send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
2346}
2347
2348void WebPage::getSourceForFrame(uint64_t frameID, uint64_t callbackID)
2349{
2350    String resultString;
2351    if (WebFrame* frame = WebProcess::shared().webFrame(frameID))
2352       resultString = frame->source();
2353
2354    send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
2355}
2356
2357void WebPage::getMainResourceDataOfFrame(uint64_t frameID, uint64_t callbackID)
2358{
2359    CoreIPC::DataReference dataReference;
2360
2361    RefPtr<ResourceBuffer> buffer;
2362    RefPtr<SharedBuffer> pdfResource;
2363    if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) {
2364        if (PluginView* pluginView = pluginViewForFrame(frame->coreFrame())) {
2365            if ((pdfResource = pluginView->liveResourceData()))
2366                dataReference = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>(pdfResource->data()), pdfResource->size());
2367        }
2368
2369        if (dataReference.isEmpty()) {
2370            if (DocumentLoader* loader = frame->coreFrame()->loader()->documentLoader()) {
2371                if ((buffer = loader->mainResourceData()))
2372                    dataReference = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size());
2373            }
2374        }
2375    }
2376
2377    send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
2378}
2379
2380static PassRefPtr<SharedBuffer> resourceDataForFrame(Frame* frame, const KURL& resourceURL)
2381{
2382    DocumentLoader* loader = frame->loader()->documentLoader();
2383    if (!loader)
2384        return 0;
2385
2386    RefPtr<ArchiveResource> subresource = loader->subresource(resourceURL);
2387    if (!subresource)
2388        return 0;
2389
2390    return subresource->data();
2391}
2392
2393void WebPage::getResourceDataFromFrame(uint64_t frameID, const String& resourceURLString, uint64_t callbackID)
2394{
2395    CoreIPC::DataReference dataReference;
2396    KURL resourceURL(KURL(), resourceURLString);
2397
2398    RefPtr<SharedBuffer> buffer;
2399    if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) {
2400        buffer = resourceDataForFrame(frame->coreFrame(), resourceURL);
2401        if (!buffer) {
2402            // Try to get the resource data from the cache.
2403            buffer = cachedResponseDataForURL(resourceURL);
2404        }
2405
2406        if (buffer)
2407            dataReference = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size());
2408    }
2409
2410    send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
2411}
2412
2413void WebPage::getWebArchiveOfFrame(uint64_t frameID, uint64_t callbackID)
2414{
2415    CoreIPC::DataReference dataReference;
2416
2417#if PLATFORM(MAC)
2418    RetainPtr<CFDataRef> data;
2419    if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) {
2420        if ((data = frame->webArchiveData(0, 0)))
2421            dataReference = CoreIPC::DataReference(CFDataGetBytePtr(data.get()), CFDataGetLength(data.get()));
2422    }
2423#else
2424    UNUSED_PARAM(frameID);
2425#endif
2426
2427    send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
2428}
2429
2430void WebPage::forceRepaintWithoutCallback()
2431{
2432    m_drawingArea->forceRepaint();
2433}
2434
2435void WebPage::forceRepaint(uint64_t callbackID)
2436{
2437    if (m_drawingArea->forceRepaintAsync(callbackID))
2438        return;
2439
2440    forceRepaintWithoutCallback();
2441    send(Messages::WebPageProxy::VoidCallback(callbackID));
2442}
2443
2444void WebPage::preferencesDidChange(const WebPreferencesStore& store)
2445{
2446    WebPreferencesStore::removeTestRunnerOverrides();
2447    updatePreferences(store);
2448}
2449
2450void WebPage::updatePreferences(const WebPreferencesStore& store)
2451{
2452    Settings* settings = m_page->settings();
2453
2454    m_tabToLinks = store.getBoolValueForKey(WebPreferencesKey::tabsToLinksKey());
2455    m_asynchronousPluginInitializationEnabled = store.getBoolValueForKey(WebPreferencesKey::asynchronousPluginInitializationEnabledKey());
2456    m_asynchronousPluginInitializationEnabledForAllPlugins = store.getBoolValueForKey(WebPreferencesKey::asynchronousPluginInitializationEnabledForAllPluginsKey());
2457    m_artificialPluginInitializationDelayEnabled = store.getBoolValueForKey(WebPreferencesKey::artificialPluginInitializationDelayEnabledKey());
2458
2459    m_scrollingPerformanceLoggingEnabled = store.getBoolValueForKey(WebPreferencesKey::scrollingPerformanceLoggingEnabledKey());
2460
2461#if PLATFORM(MAC)
2462    m_pdfPluginEnabled = store.getBoolValueForKey(WebPreferencesKey::pdfPluginEnabledKey());
2463#endif
2464
2465    // FIXME: This should be generated from macro expansion for all preferences,
2466    // but we currently don't match the naming of WebCore exactly so we are
2467    // handrolling the boolean and integer preferences until that is fixed.
2468
2469#define INITIALIZE_SETTINGS(KeyUpper, KeyLower, TypeName, Type, DefaultValue) settings->set##KeyUpper(store.get##TypeName##ValueForKey(WebPreferencesKey::KeyLower##Key()));
2470
2471    FOR_EACH_WEBKIT_STRING_PREFERENCE(INITIALIZE_SETTINGS)
2472
2473#undef INITIALIZE_SETTINGS
2474
2475    settings->setScriptEnabled(store.getBoolValueForKey(WebPreferencesKey::javaScriptEnabledKey()));
2476    settings->setScriptMarkupEnabled(store.getBoolValueForKey(WebPreferencesKey::javaScriptMarkupEnabledKey()));
2477    settings->setLoadsImagesAutomatically(store.getBoolValueForKey(WebPreferencesKey::loadsImagesAutomaticallyKey()));
2478    settings->setLoadsSiteIconsIgnoringImageLoadingSetting(store.getBoolValueForKey(WebPreferencesKey::loadsSiteIconsIgnoringImageLoadingPreferenceKey()));
2479    settings->setPluginsEnabled(store.getBoolValueForKey(WebPreferencesKey::pluginsEnabledKey()));
2480    settings->setJavaEnabled(store.getBoolValueForKey(WebPreferencesKey::javaEnabledKey()));
2481    settings->setJavaEnabledForLocalFiles(store.getBoolValueForKey(WebPreferencesKey::javaEnabledForLocalFilesKey()));
2482    settings->setOfflineWebApplicationCacheEnabled(store.getBoolValueForKey(WebPreferencesKey::offlineWebApplicationCacheEnabledKey()));
2483    settings->setLocalStorageEnabled(store.getBoolValueForKey(WebPreferencesKey::localStorageEnabledKey()));
2484    settings->setXSSAuditorEnabled(store.getBoolValueForKey(WebPreferencesKey::xssAuditorEnabledKey()));
2485    settings->setFrameFlatteningEnabled(store.getBoolValueForKey(WebPreferencesKey::frameFlatteningEnabledKey()));
2486    settings->setPrivateBrowsingEnabled(store.getBoolValueForKey(WebPreferencesKey::privateBrowsingEnabledKey()));
2487    settings->setDeveloperExtrasEnabled(store.getBoolValueForKey(WebPreferencesKey::developerExtrasEnabledKey()));
2488    settings->setJavaScriptExperimentsEnabled(store.getBoolValueForKey(WebPreferencesKey::javaScriptExperimentsEnabledKey()));
2489    settings->setTextAreasAreResizable(store.getBoolValueForKey(WebPreferencesKey::textAreasAreResizableKey()));
2490    settings->setNeedsSiteSpecificQuirks(store.getBoolValueForKey(WebPreferencesKey::needsSiteSpecificQuirksKey()));
2491    settings->setJavaScriptCanOpenWindowsAutomatically(store.getBoolValueForKey(WebPreferencesKey::javaScriptCanOpenWindowsAutomaticallyKey()));
2492    settings->setForceFTPDirectoryListings(store.getBoolValueForKey(WebPreferencesKey::forceFTPDirectoryListingsKey()));
2493    settings->setDNSPrefetchingEnabled(store.getBoolValueForKey(WebPreferencesKey::dnsPrefetchingEnabledKey()));
2494#if ENABLE(WEB_ARCHIVE)
2495    settings->setWebArchiveDebugModeEnabled(store.getBoolValueForKey(WebPreferencesKey::webArchiveDebugModeEnabledKey()));
2496#endif
2497    settings->setLocalFileContentSniffingEnabled(store.getBoolValueForKey(WebPreferencesKey::localFileContentSniffingEnabledKey()));
2498    settings->setUsesPageCache(store.getBoolValueForKey(WebPreferencesKey::usesPageCacheKey()));
2499    settings->setPageCacheSupportsPlugins(store.getBoolValueForKey(WebPreferencesKey::pageCacheSupportsPluginsKey()));
2500    settings->setAuthorAndUserStylesEnabled(store.getBoolValueForKey(WebPreferencesKey::authorAndUserStylesEnabledKey()));
2501    settings->setPaginateDuringLayoutEnabled(store.getBoolValueForKey(WebPreferencesKey::paginateDuringLayoutEnabledKey()));
2502    settings->setDOMPasteAllowed(store.getBoolValueForKey(WebPreferencesKey::domPasteAllowedKey()));
2503    settings->setJavaScriptCanAccessClipboard(store.getBoolValueForKey(WebPreferencesKey::javaScriptCanAccessClipboardKey()));
2504    settings->setShouldPrintBackgrounds(store.getBoolValueForKey(WebPreferencesKey::shouldPrintBackgroundsKey()));
2505    settings->setWebSecurityEnabled(store.getBoolValueForKey(WebPreferencesKey::webSecurityEnabledKey()));
2506    settings->setAllowUniversalAccessFromFileURLs(store.getBoolValueForKey(WebPreferencesKey::allowUniversalAccessFromFileURLsKey()));
2507    settings->setAllowFileAccessFromFileURLs(store.getBoolValueForKey(WebPreferencesKey::allowFileAccessFromFileURLsKey()));
2508
2509    settings->setMinimumFontSize(store.getUInt32ValueForKey(WebPreferencesKey::minimumFontSizeKey()));
2510    settings->setMinimumLogicalFontSize(store.getUInt32ValueForKey(WebPreferencesKey::minimumLogicalFontSizeKey()));
2511    settings->setDefaultFontSize(store.getUInt32ValueForKey(WebPreferencesKey::defaultFontSizeKey()));
2512    settings->setDefaultFixedFontSize(store.getUInt32ValueForKey(WebPreferencesKey::defaultFixedFontSizeKey()));
2513    settings->setScreenFontSubstitutionEnabled(store.getBoolValueForKey(WebPreferencesKey::screenFontSubstitutionEnabledKey())
2514#if PLATFORM(MAC)
2515        || WebProcess::shared().shouldForceScreenFontSubstitution()
2516#endif
2517    );
2518    settings->setLayoutFallbackWidth(store.getUInt32ValueForKey(WebPreferencesKey::layoutFallbackWidthKey()));
2519    settings->setDeviceWidth(store.getUInt32ValueForKey(WebPreferencesKey::deviceWidthKey()));
2520    settings->setDeviceHeight(store.getUInt32ValueForKey(WebPreferencesKey::deviceHeightKey()));
2521    settings->setEditableLinkBehavior(static_cast<WebCore::EditableLinkBehavior>(store.getUInt32ValueForKey(WebPreferencesKey::editableLinkBehaviorKey())));
2522    settings->setShowsToolTipOverTruncatedText(store.getBoolValueForKey(WebPreferencesKey::showsToolTipOverTruncatedTextKey()));
2523
2524    settings->setAcceleratedCompositingForOverflowScrollEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedCompositingForOverflowScrollEnabledKey()));
2525    settings->setAcceleratedCompositingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedCompositingEnabledKey()) && LayerTreeHost::supportsAcceleratedCompositing());
2526    settings->setAcceleratedDrawingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedDrawingEnabledKey()) && LayerTreeHost::supportsAcceleratedCompositing());
2527    settings->setCanvasUsesAcceleratedDrawing(store.getBoolValueForKey(WebPreferencesKey::canvasUsesAcceleratedDrawingKey()) && LayerTreeHost::supportsAcceleratedCompositing());
2528    settings->setShowDebugBorders(store.getBoolValueForKey(WebPreferencesKey::compositingBordersVisibleKey()));
2529    settings->setShowRepaintCounter(store.getBoolValueForKey(WebPreferencesKey::compositingRepaintCountersVisibleKey()));
2530    settings->setShowTiledScrollingIndicator(store.getBoolValueForKey(WebPreferencesKey::tiledScrollingIndicatorVisibleKey()));
2531    settings->setAggressiveTileRetentionEnabled(store.getBoolValueForKey(WebPreferencesKey::aggressiveTileRetentionEnabledKey()));
2532    settings->setCSSCustomFilterEnabled(store.getBoolValueForKey(WebPreferencesKey::cssCustomFilterEnabledKey()));
2533    RuntimeEnabledFeatures::setCSSRegionsEnabled(store.getBoolValueForKey(WebPreferencesKey::cssRegionsEnabledKey()));
2534    RuntimeEnabledFeatures::setCSSCompositingEnabled(store.getBoolValueForKey(WebPreferencesKey::cssCompositingEnabledKey()));
2535    settings->setCSSGridLayoutEnabled(store.getBoolValueForKey(WebPreferencesKey::cssGridLayoutEnabledKey()));
2536    settings->setRegionBasedColumnsEnabled(store.getBoolValueForKey(WebPreferencesKey::regionBasedColumnsEnabledKey()));
2537    settings->setWebGLEnabled(store.getBoolValueForKey(WebPreferencesKey::webGLEnabledKey()));
2538    settings->setAccelerated2dCanvasEnabled(store.getBoolValueForKey(WebPreferencesKey::accelerated2dCanvasEnabledKey()));
2539    settings->setMediaPlaybackRequiresUserGesture(store.getBoolValueForKey(WebPreferencesKey::mediaPlaybackRequiresUserGestureKey()));
2540    settings->setMediaPlaybackAllowsInline(store.getBoolValueForKey(WebPreferencesKey::mediaPlaybackAllowsInlineKey()));
2541    settings->setMockScrollbarsEnabled(store.getBoolValueForKey(WebPreferencesKey::mockScrollbarsEnabledKey()));
2542    settings->setHyperlinkAuditingEnabled(store.getBoolValueForKey(WebPreferencesKey::hyperlinkAuditingEnabledKey()));
2543    settings->setRequestAnimationFrameEnabled(store.getBoolValueForKey(WebPreferencesKey::requestAnimationFrameEnabledKey()));
2544#if ENABLE(SMOOTH_SCROLLING)
2545    settings->setScrollAnimatorEnabled(store.getBoolValueForKey(WebPreferencesKey::scrollAnimatorEnabledKey()));
2546#endif
2547    settings->setInteractiveFormValidationEnabled(store.getBoolValueForKey(WebPreferencesKey::interactiveFormValidationEnabledKey()));
2548
2549#if ENABLE(SQL_DATABASE)
2550    DatabaseManager::manager().setIsAvailable(store.getBoolValueForKey(WebPreferencesKey::databasesEnabledKey()));
2551#endif
2552
2553#if ENABLE(FULLSCREEN_API)
2554    settings->setFullScreenEnabled(store.getBoolValueForKey(WebPreferencesKey::fullScreenEnabledKey()));
2555#endif
2556
2557#if USE(AVFOUNDATION)
2558    settings->setAVFoundationEnabled(store.getBoolValueForKey(WebPreferencesKey::isAVFoundationEnabledKey()));
2559#endif
2560
2561#if PLATFORM(MAC)
2562    settings->setQTKitEnabled(store.getBoolValueForKey(WebPreferencesKey::isQTKitEnabledKey()));
2563#endif
2564
2565#if ENABLE(WEB_AUDIO)
2566    settings->setWebAudioEnabled(store.getBoolValueForKey(WebPreferencesKey::webAudioEnabledKey()));
2567#endif
2568
2569    settings->setApplicationChromeMode(store.getBoolValueForKey(WebPreferencesKey::applicationChromeModeKey()));
2570    settings->setSuppressesIncrementalRendering(store.getBoolValueForKey(WebPreferencesKey::suppressesIncrementalRenderingKey()));
2571    settings->setIncrementalRenderingSuppressionTimeoutInSeconds(store.getDoubleValueForKey(WebPreferencesKey::incrementalRenderingSuppressionTimeoutKey()));
2572    settings->setBackspaceKeyNavigationEnabled(store.getBoolValueForKey(WebPreferencesKey::backspaceKeyNavigationEnabledKey()));
2573    settings->setWantsBalancedSetDefersLoadingBehavior(store.getBoolValueForKey(WebPreferencesKey::wantsBalancedSetDefersLoadingBehaviorKey()));
2574    settings->setCaretBrowsingEnabled(store.getBoolValueForKey(WebPreferencesKey::caretBrowsingEnabledKey()));
2575
2576#if ENABLE(VIDEO_TRACK)
2577    settings->setShouldDisplaySubtitles(store.getBoolValueForKey(WebPreferencesKey::shouldDisplaySubtitlesKey()));
2578    settings->setShouldDisplayCaptions(store.getBoolValueForKey(WebPreferencesKey::shouldDisplayCaptionsKey()));
2579    settings->setShouldDisplayTextDescriptions(store.getBoolValueForKey(WebPreferencesKey::shouldDisplayTextDescriptionsKey()));
2580#endif
2581
2582#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
2583    settings->setNotificationsEnabled(store.getBoolValueForKey(WebPreferencesKey::notificationsEnabledKey()));
2584#endif
2585
2586    settings->setShouldRespectImageOrientation(store.getBoolValueForKey(WebPreferencesKey::shouldRespectImageOrientationKey()));
2587    settings->setStorageBlockingPolicy(static_cast<SecurityOrigin::StorageBlockingPolicy>(store.getUInt32ValueForKey(WebPreferencesKey::storageBlockingPolicyKey())));
2588    settings->setCookieEnabled(store.getBoolValueForKey(WebPreferencesKey::cookieEnabledKey()));
2589
2590    settings->setDiagnosticLoggingEnabled(store.getBoolValueForKey(WebPreferencesKey::diagnosticLoggingEnabledKey()));
2591
2592    settings->setScrollingPerformanceLoggingEnabled(m_scrollingPerformanceLoggingEnabled);
2593
2594    settings->setPlugInSnapshottingEnabled(store.getBoolValueForKey(WebPreferencesKey::plugInSnapshottingEnabledKey()));
2595    settings->setSnapshotAllPlugIns(store.getBoolValueForKey(WebPreferencesKey::snapshotAllPlugInsKey()));
2596    settings->setAutostartOriginPlugInSnapshottingEnabled(store.getBoolValueForKey(WebPreferencesKey::autostartOriginPlugInSnapshottingEnabledKey()));
2597    settings->setPrimaryPlugInSnapshotDetectionEnabled(store.getBoolValueForKey(WebPreferencesKey::primaryPlugInSnapshotDetectionEnabledKey()));
2598    settings->setUsesEncodingDetector(store.getBoolValueForKey(WebPreferencesKey::usesEncodingDetectorKey()));
2599
2600#if ENABLE(TEXT_AUTOSIZING)
2601    settings->setTextAutosizingEnabled(store.getBoolValueForKey(WebPreferencesKey::textAutosizingEnabledKey()));
2602#endif
2603
2604    settings->setLogsPageMessagesToSystemConsoleEnabled(store.getBoolValueForKey(WebPreferencesKey::logsPageMessagesToSystemConsoleEnabledKey()));
2605    settings->setAsynchronousSpellCheckingEnabled(store.getBoolValueForKey(WebPreferencesKey::asynchronousSpellCheckingEnabledKey()));
2606
2607    settings->setSmartInsertDeleteEnabled(store.getBoolValueForKey(WebPreferencesKey::smartInsertDeleteEnabledKey()));
2608    settings->setSelectTrailingWhitespaceEnabled(store.getBoolValueForKey(WebPreferencesKey::selectTrailingWhitespaceEnabledKey()));
2609    settings->setShowsURLsInToolTips(store.getBoolValueForKey(WebPreferencesKey::showsURLsInToolTipsEnabledKey()));
2610
2611    settings->setEnableInheritURIQueryComponent(store.getBoolValueForKey(WebPreferencesKey::enableInheritURIQueryComponentKey()));
2612
2613#if ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING)
2614    settings->setHiddenPageDOMTimerThrottlingEnabled(store.getBoolValueForKey(WebPreferencesKey::hiddenPageDOMTimerThrottlingEnabledKey()));
2615#endif
2616#if ENABLE(PAGE_VISIBILITY_API)
2617    settings->setHiddenPageCSSAnimationSuspensionEnabled(store.getBoolValueForKey(WebPreferencesKey::hiddenPageCSSAnimationSuspensionEnabledKey()));
2618#endif
2619
2620    settings->setLowPowerVideoAudioBufferSizeEnabled(store.getBoolValueForKey(WebPreferencesKey::lowPowerVideoAudioBufferSizeEnabledKey()));
2621
2622    settings->setUseLegacyTextAlignPositionedElementBehavior(store.getBoolValueForKey(WebPreferencesKey::useLegacyTextAlignPositionedElementBehaviorKey()));
2623
2624    platformPreferencesDidChange(store);
2625
2626    if (m_drawingArea)
2627        m_drawingArea->updatePreferences(store);
2628}
2629
2630#if ENABLE(INSPECTOR)
2631WebInspector* WebPage::inspector()
2632{
2633    if (m_isClosed)
2634        return 0;
2635    if (!m_inspector)
2636        m_inspector = WebInspector::create(this, m_inspectorClient);
2637    return m_inspector.get();
2638}
2639#endif
2640
2641#if ENABLE(FULLSCREEN_API)
2642WebFullScreenManager* WebPage::fullScreenManager()
2643{
2644    if (!m_fullScreenManager)
2645        m_fullScreenManager = WebFullScreenManager::create(this);
2646    return m_fullScreenManager.get();
2647}
2648#endif
2649
2650NotificationPermissionRequestManager* WebPage::notificationPermissionRequestManager()
2651{
2652    if (m_notificationPermissionRequestManager)
2653        return m_notificationPermissionRequestManager.get();
2654
2655    m_notificationPermissionRequestManager = NotificationPermissionRequestManager::create(this);
2656    return m_notificationPermissionRequestManager.get();
2657}
2658
2659#if !PLATFORM(GTK) && !PLATFORM(MAC)
2660bool WebPage::handleEditingKeyboardEvent(KeyboardEvent* evt)
2661{
2662    Node* node = evt->target()->toNode();
2663    ASSERT(node);
2664    Frame* frame = node->document()->frame();
2665    ASSERT(frame);
2666
2667    const PlatformKeyboardEvent* keyEvent = evt->keyEvent();
2668    if (!keyEvent)
2669        return false;
2670
2671    Editor::Command command = frame->editor().command(interpretKeyEvent(evt));
2672
2673    if (keyEvent->type() == PlatformEvent::RawKeyDown) {
2674        // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated,
2675        // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated
2676        // (e.g. Tab that inserts a Tab character, or Enter).
2677        return !command.isTextInsertion() && command.execute(evt);
2678    }
2679
2680    if (command.execute(evt))
2681        return true;
2682
2683    // Don't allow text insertion for nodes that cannot edit.
2684    if (!frame->editor().canEdit())
2685        return false;
2686
2687    // Don't insert null or control characters as they can result in unexpected behaviour
2688    if (evt->charCode() < ' ')
2689        return false;
2690
2691    return frame->editor().insertText(evt->keyEvent()->text(), evt);
2692}
2693#endif
2694
2695#if ENABLE(DRAG_SUPPORT)
2696
2697#if PLATFORM(QT) || PLATFORM(GTK)
2698void WebPage::performDragControllerAction(uint64_t action, WebCore::DragData dragData)
2699{
2700    if (!m_page) {
2701        send(Messages::WebPageProxy::DidPerformDragControllerAction(WebCore::DragSession()));
2702#if PLATFORM(QT)
2703        QMimeData* data = const_cast<QMimeData*>(dragData.platformData());
2704        delete data;
2705#elif PLATFORM(GTK)
2706        DataObjectGtk* data = const_cast<DataObjectGtk*>(dragData.platformData());
2707        data->deref();
2708#endif
2709        return;
2710    }
2711
2712    switch (action) {
2713    case DragControllerActionEntered:
2714        send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragEntered(&dragData)));
2715        break;
2716
2717    case DragControllerActionUpdated:
2718        send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragUpdated(&dragData)));
2719        break;
2720
2721    case DragControllerActionExited:
2722        m_page->dragController()->dragExited(&dragData);
2723        break;
2724
2725    case DragControllerActionPerformDrag: {
2726        m_page->dragController()->performDrag(&dragData);
2727        break;
2728    }
2729
2730    default:
2731        ASSERT_NOT_REACHED();
2732    }
2733    // DragData does not delete its platformData so we need to do that here.
2734#if PLATFORM(QT)
2735    QMimeData* data = const_cast<QMimeData*>(dragData.platformData());
2736    delete data;
2737#elif PLATFORM(GTK)
2738    DataObjectGtk* data = const_cast<DataObjectGtk*>(dragData.platformData());
2739    data->deref();
2740#endif
2741}
2742
2743#else
2744void 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)
2745{
2746    if (!m_page) {
2747        send(Messages::WebPageProxy::DidPerformDragControllerAction(WebCore::DragSession()));
2748        return;
2749    }
2750
2751    DragData dragData(dragStorageName, clientPosition, globalPosition, static_cast<DragOperation>(draggingSourceOperationMask), static_cast<DragApplicationFlags>(flags));
2752    switch (action) {
2753    case DragControllerActionEntered:
2754        send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragEntered(&dragData)));
2755        break;
2756
2757    case DragControllerActionUpdated:
2758        send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragUpdated(&dragData)));
2759        break;
2760
2761    case DragControllerActionExited:
2762        m_page->dragController()->dragExited(&dragData);
2763        break;
2764
2765    case DragControllerActionPerformDrag: {
2766        ASSERT(!m_pendingDropSandboxExtension);
2767
2768        m_pendingDropSandboxExtension = SandboxExtension::create(sandboxExtensionHandle);
2769        for (size_t i = 0; i < sandboxExtensionsHandleArray.size(); i++) {
2770            if (RefPtr<SandboxExtension> extension = SandboxExtension::create(sandboxExtensionsHandleArray[i]))
2771                m_pendingDropExtensionsForFileUpload.append(extension);
2772        }
2773
2774        m_page->dragController()->performDrag(&dragData);
2775
2776        // If we started loading a local file, the sandbox extension tracker would have adopted this
2777        // pending drop sandbox extension. If not, we'll play it safe and clear it.
2778        m_pendingDropSandboxExtension = nullptr;
2779
2780        m_pendingDropExtensionsForFileUpload.clear();
2781        break;
2782    }
2783
2784    default:
2785        ASSERT_NOT_REACHED();
2786    }
2787}
2788#endif
2789
2790void WebPage::dragEnded(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t operation)
2791{
2792    IntPoint adjustedClientPosition(clientPosition.x() + m_page->dragController()->dragOffset().x(), clientPosition.y() + m_page->dragController()->dragOffset().y());
2793    IntPoint adjustedGlobalPosition(globalPosition.x() + m_page->dragController()->dragOffset().x(), globalPosition.y() + m_page->dragController()->dragOffset().y());
2794
2795    m_page->dragController()->dragEnded();
2796    FrameView* view = m_page->mainFrame()->view();
2797    if (!view)
2798        return;
2799    // FIXME: These are fake modifier keys here, but they should be real ones instead.
2800    PlatformMouseEvent event(adjustedClientPosition, adjustedGlobalPosition, LeftButton, PlatformEvent::MouseMoved, 0, false, false, false, false, currentTime());
2801    m_page->mainFrame()->eventHandler()->dragSourceEndedAt(event, (DragOperation)operation);
2802}
2803
2804void WebPage::willPerformLoadDragDestinationAction()
2805{
2806    m_sandboxExtensionTracker.willPerformLoadDragDestinationAction(m_pendingDropSandboxExtension.release());
2807}
2808
2809void WebPage::mayPerformUploadDragDestinationAction()
2810{
2811    for (size_t i = 0; i < m_pendingDropExtensionsForFileUpload.size(); i++)
2812        m_pendingDropExtensionsForFileUpload[i]->consumePermanently();
2813    m_pendingDropExtensionsForFileUpload.clear();
2814}
2815
2816#endif // ENABLE(DRAG_SUPPORT)
2817
2818WebUndoStep* WebPage::webUndoStep(uint64_t stepID)
2819{
2820    return m_undoStepMap.get(stepID);
2821}
2822
2823void WebPage::addWebUndoStep(uint64_t stepID, WebUndoStep* entry)
2824{
2825    m_undoStepMap.set(stepID, entry);
2826}
2827
2828void WebPage::removeWebEditCommand(uint64_t stepID)
2829{
2830    m_undoStepMap.remove(stepID);
2831}
2832
2833void WebPage::unapplyEditCommand(uint64_t stepID)
2834{
2835    WebUndoStep* step = webUndoStep(stepID);
2836    if (!step)
2837        return;
2838
2839    step->step()->unapply();
2840}
2841
2842void WebPage::reapplyEditCommand(uint64_t stepID)
2843{
2844    WebUndoStep* step = webUndoStep(stepID);
2845    if (!step)
2846        return;
2847
2848    m_isInRedo = true;
2849    step->step()->reapply();
2850    m_isInRedo = false;
2851}
2852
2853void WebPage::didRemoveEditCommand(uint64_t commandID)
2854{
2855    removeWebEditCommand(commandID);
2856}
2857
2858void WebPage::setActivePopupMenu(WebPopupMenu* menu)
2859{
2860    m_activePopupMenu = menu;
2861}
2862
2863#if ENABLE(INPUT_TYPE_COLOR)
2864void WebPage::setActiveColorChooser(WebColorChooser* colorChooser)
2865{
2866    m_activeColorChooser = colorChooser;
2867}
2868
2869void WebPage::didEndColorChooser()
2870{
2871    m_activeColorChooser->didEndChooser();
2872}
2873
2874void WebPage::didChooseColor(const WebCore::Color& color)
2875{
2876    m_activeColorChooser->didChooseColor(color);
2877}
2878#endif
2879
2880void WebPage::setActiveOpenPanelResultListener(PassRefPtr<WebOpenPanelResultListener> openPanelResultListener)
2881{
2882    m_activeOpenPanelResultListener = openPanelResultListener;
2883}
2884
2885bool WebPage::findStringFromInjectedBundle(const String& target, FindOptions options)
2886{
2887    return m_page->findString(target, options);
2888}
2889
2890void WebPage::findString(const String& string, uint32_t options, uint32_t maxMatchCount)
2891{
2892    m_findController.findString(string, static_cast<FindOptions>(options), maxMatchCount);
2893}
2894
2895void WebPage::findStringMatches(const String& string, uint32_t options, uint32_t maxMatchCount)
2896{
2897    m_findController.findStringMatches(string, static_cast<FindOptions>(options), maxMatchCount);
2898}
2899
2900void WebPage::getImageForFindMatch(uint32_t matchIndex)
2901{
2902    m_findController.getImageForFindMatch(matchIndex);
2903}
2904
2905void WebPage::selectFindMatch(uint32_t matchIndex)
2906{
2907    m_findController.selectFindMatch(matchIndex);
2908}
2909
2910void WebPage::hideFindUI()
2911{
2912    m_findController.hideFindUI();
2913}
2914
2915void WebPage::countStringMatches(const String& string, uint32_t options, uint32_t maxMatchCount)
2916{
2917    m_findController.countStringMatches(string, static_cast<FindOptions>(options), maxMatchCount);
2918}
2919
2920void WebPage::didChangeSelectedIndexForActivePopupMenu(int32_t newIndex)
2921{
2922    changeSelectedIndex(newIndex);
2923    m_activePopupMenu = 0;
2924}
2925
2926void WebPage::changeSelectedIndex(int32_t index)
2927{
2928    if (!m_activePopupMenu)
2929        return;
2930
2931    m_activePopupMenu->didChangeSelectedIndex(index);
2932}
2933
2934void WebPage::didChooseFilesForOpenPanel(const Vector<String>& files)
2935{
2936    if (!m_activeOpenPanelResultListener)
2937        return;
2938
2939    m_activeOpenPanelResultListener->didChooseFiles(files);
2940    m_activeOpenPanelResultListener = 0;
2941}
2942
2943void WebPage::didCancelForOpenPanel()
2944{
2945    m_activeOpenPanelResultListener = 0;
2946}
2947
2948#if ENABLE(WEB_PROCESS_SANDBOX)
2949void WebPage::extendSandboxForFileFromOpenPanel(const SandboxExtension::Handle& handle)
2950{
2951    SandboxExtension::create(handle)->consumePermanently();
2952}
2953#endif
2954
2955#if ENABLE(GEOLOCATION)
2956void WebPage::didReceiveGeolocationPermissionDecision(uint64_t geolocationID, bool allowed)
2957{
2958    m_geolocationPermissionRequestManager.didReceiveGeolocationPermissionDecision(geolocationID, allowed);
2959}
2960#endif
2961
2962void WebPage::didReceiveNotificationPermissionDecision(uint64_t notificationID, bool allowed)
2963{
2964    notificationPermissionRequestManager()->didReceiveNotificationPermissionDecision(notificationID, allowed);
2965}
2966
2967void WebPage::advanceToNextMisspelling(bool startBeforeSelection)
2968{
2969    Frame* frame = m_page->focusController()->focusedOrMainFrame();
2970    frame->editor().advanceToNextMisspelling(startBeforeSelection);
2971}
2972
2973void WebPage::changeSpellingToWord(const String& word)
2974{
2975    replaceSelectionWithText(m_page->focusController()->focusedOrMainFrame(), word);
2976}
2977
2978void WebPage::unmarkAllMisspellings()
2979{
2980    for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
2981        if (Document* document = frame->document())
2982            document->markers()->removeMarkers(DocumentMarker::Spelling);
2983    }
2984}
2985
2986void WebPage::unmarkAllBadGrammar()
2987{
2988    for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
2989        if (Document* document = frame->document())
2990            document->markers()->removeMarkers(DocumentMarker::Grammar);
2991    }
2992}
2993
2994#if USE(APPKIT)
2995void WebPage::uppercaseWord()
2996{
2997    m_page->focusController()->focusedOrMainFrame()->editor().uppercaseWord();
2998}
2999
3000void WebPage::lowercaseWord()
3001{
3002    m_page->focusController()->focusedOrMainFrame()->editor().lowercaseWord();
3003}
3004
3005void WebPage::capitalizeWord()
3006{
3007    m_page->focusController()->focusedOrMainFrame()->editor().capitalizeWord();
3008}
3009#endif
3010
3011void WebPage::setTextForActivePopupMenu(int32_t index)
3012{
3013    if (!m_activePopupMenu)
3014        return;
3015
3016    m_activePopupMenu->setTextForIndex(index);
3017}
3018
3019#if PLATFORM(GTK)
3020void WebPage::failedToShowPopupMenu()
3021{
3022    if (!m_activePopupMenu)
3023        return;
3024
3025    m_activePopupMenu->client()->popupDidHide();
3026}
3027#endif
3028
3029#if ENABLE(CONTEXT_MENUS)
3030void WebPage::didSelectItemFromActiveContextMenu(const WebContextMenuItemData& item)
3031{
3032    if (!m_contextMenu)
3033        return;
3034
3035    m_contextMenu->itemSelected(item);
3036    m_contextMenu = 0;
3037}
3038#endif
3039
3040void WebPage::replaceSelectionWithText(Frame* frame, const String& text)
3041{
3042    bool selectReplacement = true;
3043    bool smartReplace = false;
3044    return frame->editor().replaceSelectionWithText(text, selectReplacement, smartReplace);
3045}
3046
3047void WebPage::clearSelection()
3048{
3049    m_page->focusController()->focusedOrMainFrame()->selection()->clear();
3050}
3051
3052bool WebPage::mainFrameHasCustomRepresentation() const
3053{
3054    if (Frame* frame = mainFrame()) {
3055        WebFrameLoaderClient* webFrameLoaderClient = toWebFrameLoaderClient(frame->loader()->client());
3056        ASSERT(webFrameLoaderClient);
3057        return webFrameLoaderClient->frameHasCustomRepresentation();
3058    }
3059
3060    return false;
3061}
3062
3063void WebPage::didChangeScrollOffsetForMainFrame()
3064{
3065    Frame* frame = m_page->mainFrame();
3066    IntPoint scrollPosition = frame->view()->scrollPosition();
3067    IntPoint maximumScrollPosition = frame->view()->maximumScrollPosition();
3068    IntPoint minimumScrollPosition = frame->view()->minimumScrollPosition();
3069
3070    bool isPinnedToLeftSide = (scrollPosition.x() <= minimumScrollPosition.x());
3071    bool isPinnedToRightSide = (scrollPosition.x() >= maximumScrollPosition.x());
3072    bool isPinnedToTopSide = (scrollPosition.y() <= minimumScrollPosition.y());
3073    bool isPinnedToBottomSide = (scrollPosition.y() >= maximumScrollPosition.y());
3074
3075    if (isPinnedToLeftSide != m_cachedMainFrameIsPinnedToLeftSide || isPinnedToRightSide != m_cachedMainFrameIsPinnedToRightSide || isPinnedToTopSide != m_cachedMainFrameIsPinnedToTopSide || isPinnedToBottomSide != m_cachedMainFrameIsPinnedToBottomSide) {
3076        send(Messages::WebPageProxy::DidChangeScrollOffsetPinningForMainFrame(isPinnedToLeftSide, isPinnedToRightSide, isPinnedToTopSide, isPinnedToBottomSide));
3077
3078        m_cachedMainFrameIsPinnedToLeftSide = isPinnedToLeftSide;
3079        m_cachedMainFrameIsPinnedToRightSide = isPinnedToRightSide;
3080        m_cachedMainFrameIsPinnedToTopSide = isPinnedToTopSide;
3081        m_cachedMainFrameIsPinnedToBottomSide = isPinnedToBottomSide;
3082    }
3083}
3084
3085void WebPage::mainFrameDidLayout()
3086{
3087    unsigned pageCount = m_page->pageCount();
3088    if (pageCount != m_cachedPageCount) {
3089        send(Messages::WebPageProxy::DidChangePageCount(pageCount));
3090        m_cachedPageCount = pageCount;
3091    }
3092
3093#if USE(TILED_BACKING_STORE) && USE(ACCELERATED_COMPOSITING)
3094    if (m_drawingArea && m_drawingArea->layerTreeHost()) {
3095        double red, green, blue, alpha;
3096        m_mainFrame->getDocumentBackgroundColor(&red, &green, &blue, &alpha);
3097        RGBA32 rgba = makeRGBA32FromFloats(red, green, blue, alpha);
3098        if (m_backgroundColor.rgb() != rgba) {
3099            m_backgroundColor.setRGB(rgba);
3100            m_drawingArea->layerTreeHost()->setBackgroundColor(m_backgroundColor);
3101        }
3102    }
3103#endif
3104}
3105
3106void WebPage::addPluginView(PluginView* pluginView)
3107{
3108    ASSERT(!m_pluginViews.contains(pluginView));
3109
3110    m_pluginViews.add(pluginView);
3111    m_hasSeenPlugin = true;
3112#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC)
3113    LOG(Plugins, "Primary Plug-In Detection: triggering detection from addPluginView(%p)", pluginView);
3114    m_determinePrimarySnapshottedPlugInTimer.startOneShot(0);
3115#endif
3116}
3117
3118void WebPage::removePluginView(PluginView* pluginView)
3119{
3120    ASSERT(m_pluginViews.contains(pluginView));
3121
3122    m_pluginViews.remove(pluginView);
3123#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC)
3124    LOG(Plugins, "Primary Plug-In Detection: removePluginView(%p)", pluginView);
3125#endif
3126}
3127
3128void WebPage::sendSetWindowFrame(const FloatRect& windowFrame)
3129{
3130#if PLATFORM(MAC)
3131    m_hasCachedWindowFrame = false;
3132#endif
3133    send(Messages::WebPageProxy::SetWindowFrame(windowFrame));
3134}
3135
3136#if PLATFORM(MAC)
3137void WebPage::setWindowIsVisible(bool windowIsVisible)
3138{
3139    m_windowIsVisible = windowIsVisible;
3140
3141    corePage()->focusController()->setContainingWindowIsVisible(windowIsVisible);
3142
3143    // Tell all our plug-in views that the window visibility changed.
3144    for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
3145        (*it)->setWindowIsVisible(windowIsVisible);
3146}
3147
3148void WebPage::windowAndViewFramesChanged(const FloatRect& windowFrameInScreenCoordinates, const FloatRect& windowFrameInUnflippedScreenCoordinates, const FloatRect& viewFrameInWindowCoordinates, const FloatPoint& accessibilityViewCoordinates)
3149{
3150    m_windowFrameInScreenCoordinates = windowFrameInScreenCoordinates;
3151    m_windowFrameInUnflippedScreenCoordinates = windowFrameInUnflippedScreenCoordinates;
3152    m_viewFrameInWindowCoordinates = viewFrameInWindowCoordinates;
3153    m_accessibilityPosition = accessibilityViewCoordinates;
3154
3155    // Tell all our plug-in views that the window and view frames have changed.
3156    for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
3157        (*it)->windowAndViewFramesChanged(enclosingIntRect(windowFrameInScreenCoordinates), enclosingIntRect(viewFrameInWindowCoordinates));
3158
3159    m_hasCachedWindowFrame = !m_windowFrameInUnflippedScreenCoordinates.isEmpty();
3160}
3161#endif
3162
3163void WebPage::viewExposedRectChanged(const FloatRect& exposedRect, bool clipsToExposedRect)
3164{
3165    m_drawingArea->setExposedRect(exposedRect);
3166    m_drawingArea->setClipsToExposedRect(clipsToExposedRect);
3167}
3168
3169void WebPage::setMainFrameIsScrollable(bool isScrollable)
3170{
3171    m_mainFrameIsScrollable = isScrollable;
3172    m_drawingArea->mainFrameScrollabilityChanged(isScrollable);
3173
3174    if (FrameView* frameView = m_mainFrame->coreFrame()->view()) {
3175        frameView->setCanHaveScrollbars(isScrollable);
3176        frameView->setProhibitsScrolling(!isScrollable);
3177    }
3178}
3179
3180bool WebPage::windowIsFocused() const
3181{
3182    return m_page->focusController()->isActive();
3183}
3184
3185bool WebPage::windowAndWebPageAreFocused() const
3186{
3187#if PLATFORM(MAC)
3188    if (!m_windowIsVisible)
3189        return false;
3190#endif
3191    return m_page->focusController()->isFocused() && m_page->focusController()->isActive();
3192}
3193
3194void WebPage::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageDecoder& decoder)
3195{
3196    if (decoder.messageReceiverName() == Messages::DrawingArea::messageReceiverName()) {
3197        if (m_drawingArea)
3198            m_drawingArea->didReceiveDrawingAreaMessage(connection, decoder);
3199        return;
3200    }
3201
3202#if USE(TILED_BACKING_STORE) && USE(ACCELERATED_COMPOSITING)
3203    if (decoder.messageReceiverName() == Messages::CoordinatedLayerTreeHost::messageReceiverName()) {
3204        if (m_drawingArea)
3205            m_drawingArea->didReceiveCoordinatedLayerTreeHostMessage(connection, decoder);
3206        return;
3207    }
3208#endif
3209
3210#if ENABLE(INSPECTOR)
3211    if (decoder.messageReceiverName() == Messages::WebInspector::messageReceiverName()) {
3212        if (WebInspector* inspector = this->inspector())
3213            inspector->didReceiveWebInspectorMessage(connection, decoder);
3214        return;
3215    }
3216#endif
3217
3218#if ENABLE(FULLSCREEN_API)
3219    if (decoder.messageReceiverName() == Messages::WebFullScreenManager::messageReceiverName()) {
3220        fullScreenManager()->didReceiveMessage(connection, decoder);
3221        return;
3222    }
3223#endif
3224
3225    didReceiveWebPageMessage(connection, decoder);
3226}
3227
3228void WebPage::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageDecoder& decoder, OwnPtr<CoreIPC::MessageEncoder>& replyEncoder)
3229{
3230    didReceiveSyncWebPageMessage(connection, decoder, replyEncoder);
3231}
3232
3233InjectedBundleBackForwardList* WebPage::backForwardList()
3234{
3235    if (!m_backForwardList)
3236        m_backForwardList = InjectedBundleBackForwardList::create(this);
3237    return m_backForwardList.get();
3238}
3239
3240#if PLATFORM(QT)
3241#if ENABLE(TOUCH_ADJUSTMENT)
3242void WebPage::findZoomableAreaForPoint(const WebCore::IntPoint& point, const WebCore::IntSize& area)
3243{
3244    Node* node = 0;
3245    IntRect zoomableArea;
3246    bool foundAreaForTouchPoint = m_mainFrame->coreFrame()->eventHandler()->bestZoomableAreaForTouchPoint(point, IntSize(area.width() / 2, area.height() / 2), zoomableArea, node);
3247
3248    if (!foundAreaForTouchPoint)
3249        return;
3250
3251    ASSERT(node);
3252
3253    if (node->document() && node->document()->view())
3254        zoomableArea = node->document()->view()->contentsToWindow(zoomableArea);
3255
3256    send(Messages::WebPageProxy::DidFindZoomableArea(point, zoomableArea));
3257}
3258
3259#else
3260void WebPage::findZoomableAreaForPoint(const WebCore::IntPoint& point, const WebCore::IntSize& area)
3261{
3262    UNUSED_PARAM(area);
3263    Frame* mainframe = m_mainFrame->coreFrame();
3264    HitTestResult result = mainframe->eventHandler()->hitTestResultAtPoint(mainframe->view()->windowToContents(point), HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowShadowContent);
3265
3266    Node* node = result.innerNode();
3267
3268    if (!node)
3269        return;
3270
3271    IntRect zoomableArea = node->getRect();
3272
3273    while (true) {
3274        bool found = !node->isTextNode() && !node->isShadowRoot();
3275
3276        // No candidate found, bail out.
3277        if (!found && !node->parentNode())
3278            return;
3279
3280        // Candidate found, and it is a better candidate than its parent.
3281        // NB: A parent is considered a better candidate iff the node is
3282        // contained by it and it is the only child.
3283        if (found && (!node->parentNode() || node->parentNode()->childNodeCount() != 1))
3284            break;
3285
3286        node = node->parentNode();
3287        zoomableArea.unite(node->getRect());
3288    }
3289
3290    if (node->document() && node->document()->frame() && node->document()->frame()->view()) {
3291        const ScrollView* view = node->document()->frame()->view();
3292        zoomableArea = view->contentsToWindow(zoomableArea);
3293    }
3294
3295    send(Messages::WebPageProxy::DidFindZoomableArea(point, zoomableArea));
3296}
3297#endif
3298#endif
3299
3300WebPage::SandboxExtensionTracker::~SandboxExtensionTracker()
3301{
3302    invalidate();
3303}
3304
3305void WebPage::SandboxExtensionTracker::invalidate()
3306{
3307    m_pendingProvisionalSandboxExtension = nullptr;
3308
3309    if (m_provisionalSandboxExtension) {
3310        m_provisionalSandboxExtension->revoke();
3311        m_provisionalSandboxExtension = nullptr;
3312    }
3313
3314    if (m_committedSandboxExtension) {
3315        m_committedSandboxExtension->revoke();
3316        m_committedSandboxExtension = nullptr;
3317    }
3318}
3319
3320void WebPage::SandboxExtensionTracker::willPerformLoadDragDestinationAction(PassRefPtr<SandboxExtension> pendingDropSandboxExtension)
3321{
3322    setPendingProvisionalSandboxExtension(pendingDropSandboxExtension);
3323}
3324
3325void WebPage::SandboxExtensionTracker::beginLoad(WebFrame* frame, const SandboxExtension::Handle& handle)
3326{
3327    ASSERT_UNUSED(frame, frame->isMainFrame());
3328
3329    setPendingProvisionalSandboxExtension(SandboxExtension::create(handle));
3330}
3331
3332void WebPage::SandboxExtensionTracker::setPendingProvisionalSandboxExtension(PassRefPtr<SandboxExtension> pendingProvisionalSandboxExtension)
3333{
3334    m_pendingProvisionalSandboxExtension = pendingProvisionalSandboxExtension;
3335}
3336
3337static bool shouldReuseCommittedSandboxExtension(WebFrame* frame)
3338{
3339    ASSERT(frame->isMainFrame());
3340
3341    FrameLoader* frameLoader = frame->coreFrame()->loader();
3342    FrameLoadType frameLoadType = frameLoader->loadType();
3343
3344    // If the page is being reloaded, it should reuse whatever extension is committed.
3345    if (frameLoadType == FrameLoadTypeReload || frameLoadType == FrameLoadTypeReloadFromOrigin)
3346        return true;
3347
3348    DocumentLoader* documentLoader = frameLoader->documentLoader();
3349    DocumentLoader* provisionalDocumentLoader = frameLoader->provisionalDocumentLoader();
3350    if (!documentLoader || !provisionalDocumentLoader)
3351        return false;
3352
3353    if (documentLoader->url().isLocalFile() && provisionalDocumentLoader->url().isLocalFile())
3354        return true;
3355
3356    return false;
3357}
3358
3359void WebPage::SandboxExtensionTracker::didStartProvisionalLoad(WebFrame* frame)
3360{
3361    if (!frame->isMainFrame())
3362        return;
3363
3364    // We should only reuse the commited sandbox extension if it is not null. It can be
3365    // null if the last load was for an error page.
3366    if (m_committedSandboxExtension && shouldReuseCommittedSandboxExtension(frame))
3367        m_pendingProvisionalSandboxExtension = m_committedSandboxExtension;
3368
3369    ASSERT(!m_provisionalSandboxExtension);
3370
3371    m_provisionalSandboxExtension = m_pendingProvisionalSandboxExtension.release();
3372    if (!m_provisionalSandboxExtension)
3373        return;
3374
3375    ASSERT(!m_provisionalSandboxExtension || frame->coreFrame()->loader()->provisionalDocumentLoader()->url().isLocalFile());
3376
3377    m_provisionalSandboxExtension->consume();
3378}
3379
3380void WebPage::SandboxExtensionTracker::didCommitProvisionalLoad(WebFrame* frame)
3381{
3382    if (!frame->isMainFrame())
3383        return;
3384
3385    if (m_committedSandboxExtension)
3386        m_committedSandboxExtension->revoke();
3387
3388    m_committedSandboxExtension = m_provisionalSandboxExtension.release();
3389
3390    // We can also have a non-null m_pendingProvisionalSandboxExtension if a new load is being started.
3391    // This extension is not cleared, because it does not pertain to the failed load, and will be needed.
3392}
3393
3394void WebPage::SandboxExtensionTracker::didFailProvisionalLoad(WebFrame* frame)
3395{
3396    if (!frame->isMainFrame())
3397        return;
3398
3399    if (!m_provisionalSandboxExtension)
3400        return;
3401
3402    m_provisionalSandboxExtension->revoke();
3403    m_provisionalSandboxExtension = nullptr;
3404
3405    // We can also have a non-null m_pendingProvisionalSandboxExtension if a new load is being started
3406    // (notably, if the current one fails because the new one cancels it). This extension is not cleared,
3407    // because it does not pertain to the failed load, and will be needed.
3408}
3409
3410bool WebPage::hasLocalDataForURL(const KURL& url)
3411{
3412    if (url.isLocalFile())
3413        return true;
3414
3415    FrameLoader* frameLoader = m_page->mainFrame()->loader();
3416    DocumentLoader* documentLoader = frameLoader ? frameLoader->documentLoader() : 0;
3417    if (documentLoader && documentLoader->subresource(url))
3418        return true;
3419
3420    return platformHasLocalDataForURL(url);
3421}
3422
3423void WebPage::setCustomTextEncodingName(const String& encoding)
3424{
3425    m_page->mainFrame()->loader()->reloadWithOverrideEncoding(encoding);
3426}
3427
3428void WebPage::didRemoveBackForwardItem(uint64_t itemID)
3429{
3430    WebBackForwardListProxy::removeItem(itemID);
3431}
3432
3433#if PLATFORM(MAC)
3434
3435bool WebPage::isSpeaking()
3436{
3437    bool result;
3438    return sendSync(Messages::WebPageProxy::GetIsSpeaking(), Messages::WebPageProxy::GetIsSpeaking::Reply(result)) && result;
3439}
3440
3441void WebPage::speak(const String& string)
3442{
3443    send(Messages::WebPageProxy::Speak(string));
3444}
3445
3446void WebPage::stopSpeaking()
3447{
3448    send(Messages::WebPageProxy::StopSpeaking());
3449}
3450
3451#endif
3452
3453#if PLATFORM(MAC)
3454RetainPtr<PDFDocument> WebPage::pdfDocumentForPrintingFrame(Frame* coreFrame)
3455{
3456    Document* document = coreFrame->document();
3457    if (!document)
3458        return 0;
3459
3460    if (!document->isPluginDocument())
3461        return 0;
3462
3463    PluginView* pluginView = static_cast<PluginView*>(toPluginDocument(document)->pluginWidget());
3464    if (!pluginView)
3465        return 0;
3466
3467    return pluginView->pdfDocumentForPrinting();
3468}
3469#endif // PLATFORM(MAC)
3470
3471void WebPage::beginPrinting(uint64_t frameID, const PrintInfo& printInfo)
3472{
3473    WebFrame* frame = WebProcess::shared().webFrame(frameID);
3474    if (!frame)
3475        return;
3476
3477    Frame* coreFrame = frame->coreFrame();
3478    if (!coreFrame)
3479        return;
3480
3481#if PLATFORM(MAC)
3482    if (pdfDocumentForPrintingFrame(coreFrame))
3483        return;
3484#endif // PLATFORM(MAC)
3485
3486    if (!m_printContext)
3487        m_printContext = adoptPtr(new PrintContext(coreFrame));
3488
3489    drawingArea()->setLayerTreeStateIsFrozen(true);
3490    m_printContext->begin(printInfo.availablePaperWidth, printInfo.availablePaperHeight);
3491
3492    float fullPageHeight;
3493    m_printContext->computePageRects(FloatRect(0, 0, printInfo.availablePaperWidth, printInfo.availablePaperHeight), 0, 0, printInfo.pageSetupScaleFactor, fullPageHeight, true);
3494
3495#if PLATFORM(GTK)
3496    if (!m_printOperation)
3497        m_printOperation = WebPrintOperationGtk::create(this, printInfo);
3498#endif
3499}
3500
3501void WebPage::endPrinting()
3502{
3503    drawingArea()->setLayerTreeStateIsFrozen(false);
3504#if PLATFORM(GTK)
3505    m_printOperation = 0;
3506#endif
3507    m_printContext = nullptr;
3508}
3509
3510void WebPage::computePagesForPrinting(uint64_t frameID, const PrintInfo& printInfo, uint64_t callbackID)
3511{
3512    Vector<IntRect> resultPageRects;
3513    double resultTotalScaleFactorForPrinting = 1;
3514
3515    beginPrinting(frameID, printInfo);
3516
3517    if (m_printContext) {
3518        resultPageRects = m_printContext->pageRects();
3519        resultTotalScaleFactorForPrinting = m_printContext->computeAutomaticScaleFactor(FloatSize(printInfo.availablePaperWidth, printInfo.availablePaperHeight)) * printInfo.pageSetupScaleFactor;
3520    }
3521#if PLATFORM(MAC)
3522    else
3523        computePagesForPrintingPDFDocument(frameID, printInfo, resultPageRects);
3524#endif // PLATFORM(MAC)
3525
3526    // If we're asked to print, we should actually print at least a blank page.
3527    if (resultPageRects.isEmpty())
3528        resultPageRects.append(IntRect(0, 0, 1, 1));
3529
3530    send(Messages::WebPageProxy::ComputedPagesCallback(resultPageRects, resultTotalScaleFactorForPrinting, callbackID));
3531}
3532
3533#if PLATFORM(MAC)
3534void WebPage::drawRectToImage(uint64_t frameID, const PrintInfo& printInfo, const IntRect& rect, const WebCore::IntSize& imageSize, uint64_t callbackID)
3535{
3536    WebFrame* frame = WebProcess::shared().webFrame(frameID);
3537    Frame* coreFrame = frame ? frame->coreFrame() : 0;
3538
3539    RefPtr<WebImage> image;
3540
3541#if USE(CG)
3542    if (coreFrame) {
3543#if PLATFORM(MAC)
3544        ASSERT(coreFrame->document()->printing() || pdfDocumentForPrintingFrame(coreFrame));
3545#else
3546        ASSERT(coreFrame->document()->printing());
3547#endif
3548
3549        RefPtr<ShareableBitmap> bitmap = ShareableBitmap::createShareable(imageSize, ShareableBitmap::SupportsAlpha);
3550        OwnPtr<GraphicsContext> graphicsContext = bitmap->createGraphicsContext();
3551
3552        float printingScale = static_cast<float>(imageSize.width()) / rect.width();
3553        graphicsContext->scale(FloatSize(printingScale, printingScale));
3554
3555#if PLATFORM(MAC)
3556        if (RetainPtr<PDFDocument> pdfDocument = pdfDocumentForPrintingFrame(coreFrame)) {
3557            ASSERT(!m_printContext);
3558            graphicsContext->scale(FloatSize(1, -1));
3559            graphicsContext->translate(0, -rect.height());
3560            drawPDFDocument(graphicsContext->platformContext(), pdfDocument.get(), printInfo, rect);
3561        } else
3562#endif
3563        {
3564            m_printContext->spoolRect(*graphicsContext, rect);
3565        }
3566
3567        image = WebImage::create(bitmap.release());
3568    }
3569#endif
3570
3571    ShareableBitmap::Handle handle;
3572
3573    if (image)
3574        image->bitmap()->createHandle(handle, SharedMemory::ReadOnly);
3575
3576    send(Messages::WebPageProxy::ImageCallback(handle, callbackID));
3577}
3578
3579void WebPage::drawPagesToPDF(uint64_t frameID, const PrintInfo& printInfo, uint32_t first, uint32_t count, uint64_t callbackID)
3580{
3581    WebFrame* frame = WebProcess::shared().webFrame(frameID);
3582    Frame* coreFrame = frame ? frame->coreFrame() : 0;
3583
3584    RetainPtr<CFMutableDataRef> pdfPageData = adoptCF(CFDataCreateMutable(0, 0));
3585
3586#if USE(CG)
3587    if (coreFrame) {
3588
3589#if PLATFORM(MAC)
3590        ASSERT(coreFrame->document()->printing() || pdfDocumentForPrintingFrame(coreFrame));
3591#else
3592        ASSERT(coreFrame->document()->printing());
3593#endif
3594
3595        // FIXME: Use CGDataConsumerCreate with callbacks to avoid copying the data.
3596        RetainPtr<CGDataConsumerRef> pdfDataConsumer = adoptCF(CGDataConsumerCreateWithCFData(pdfPageData.get()));
3597
3598        CGRect mediaBox = (m_printContext && m_printContext->pageCount()) ? m_printContext->pageRect(0) : CGRectMake(0, 0, printInfo.availablePaperWidth, printInfo.availablePaperHeight);
3599        RetainPtr<CGContextRef> context = adoptCF(CGPDFContextCreate(pdfDataConsumer.get(), &mediaBox, 0));
3600
3601#if PLATFORM(MAC)
3602        if (RetainPtr<PDFDocument> pdfDocument = pdfDocumentForPrintingFrame(coreFrame)) {
3603            ASSERT(!m_printContext);
3604            drawPagesToPDFFromPDFDocument(context.get(), pdfDocument.get(), printInfo, first, count);
3605        } else
3606#endif
3607        {
3608            size_t pageCount = m_printContext->pageCount();
3609            for (uint32_t page = first; page < first + count; ++page) {
3610                if (page >= pageCount)
3611                    break;
3612
3613                RetainPtr<CFDictionaryRef> pageInfo = adoptCF(CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
3614                CGPDFContextBeginPage(context.get(), pageInfo.get());
3615
3616                GraphicsContext ctx(context.get());
3617                ctx.scale(FloatSize(1, -1));
3618                ctx.translate(0, -m_printContext->pageRect(page).height());
3619                m_printContext->spoolPage(ctx, page, m_printContext->pageRect(page).width());
3620
3621                CGPDFContextEndPage(context.get());
3622            }
3623        }
3624        CGPDFContextClose(context.get());
3625    }
3626#endif
3627
3628    send(Messages::WebPageProxy::DataCallback(CoreIPC::DataReference(CFDataGetBytePtr(pdfPageData.get()), CFDataGetLength(pdfPageData.get())), callbackID));
3629}
3630
3631#elif PLATFORM(GTK)
3632
3633void WebPage::drawPagesForPrinting(uint64_t frameID, const PrintInfo& printInfo, uint64_t callbackID)
3634{
3635    beginPrinting(frameID, printInfo);
3636    if (m_printContext && m_printOperation) {
3637        m_printOperation->startPrint(m_printContext.get(), callbackID);
3638        return;
3639    }
3640
3641    send(Messages::WebPageProxy::VoidCallback(callbackID));
3642}
3643#endif
3644
3645void WebPage::savePDFToFileInDownloadsFolder(const String& suggestedFilename, const String& originatingURLString, const uint8_t* data, unsigned long size)
3646{
3647    send(Messages::WebPageProxy::SavePDFToFileInDownloadsFolder(suggestedFilename, originatingURLString, CoreIPC::DataReference(data, size)));
3648}
3649
3650#if PLATFORM(MAC)
3651void WebPage::savePDFToTemporaryFolderAndOpenWithNativeApplication(const String& suggestedFilename, const String& originatingURLString, const uint8_t* data, unsigned long size, const String& pdfUUID)
3652{
3653    send(Messages::WebPageProxy::SavePDFToTemporaryFolderAndOpenWithNativeApplication(suggestedFilename, originatingURLString, CoreIPC::DataReference(data, size), pdfUUID));
3654}
3655#endif
3656
3657void WebPage::setMediaVolume(float volume)
3658{
3659    m_page->setMediaVolume(volume);
3660}
3661
3662void WebPage::setMayStartMediaWhenInWindow(bool mayStartMedia)
3663{
3664    if (mayStartMedia == m_mayStartMediaWhenInWindow)
3665        return;
3666
3667    m_mayStartMediaWhenInWindow = mayStartMedia;
3668    if (m_mayStartMediaWhenInWindow && m_page->isOnscreen())
3669        m_setCanStartMediaTimer.startOneShot(0);
3670}
3671
3672void WebPage::runModal()
3673{
3674    if (m_isClosed)
3675        return;
3676    if (m_isRunningModal)
3677        return;
3678
3679    m_isRunningModal = true;
3680    send(Messages::WebPageProxy::RunModal());
3681    RunLoop::run();
3682    ASSERT(!m_isRunningModal);
3683}
3684
3685void WebPage::setMemoryCacheMessagesEnabled(bool memoryCacheMessagesEnabled)
3686{
3687    m_page->setMemoryCacheClientCallsEnabled(memoryCacheMessagesEnabled);
3688}
3689
3690bool WebPage::canHandleRequest(const WebCore::ResourceRequest& request)
3691{
3692    if (SchemeRegistry::shouldLoadURLSchemeAsEmptyDocument(request.url().protocol()))
3693        return true;
3694
3695#if ENABLE(BLOB)
3696    if (request.url().protocolIs("blob"))
3697        return true;
3698#endif
3699
3700    return platformCanHandleRequest(request);
3701}
3702
3703#if USE(TILED_BACKING_STORE)
3704void WebPage::commitPageTransitionViewport()
3705{
3706    m_drawingArea->setLayerTreeStateIsFrozen(false);
3707}
3708#endif
3709
3710#if PLATFORM(MAC)
3711void WebPage::handleAlternativeTextUIResult(const String& result)
3712{
3713    Frame* frame = m_page->focusController()->focusedOrMainFrame();
3714    if (!frame)
3715        return;
3716    frame->editor().handleAlternativeTextUIResult(result);
3717}
3718#endif
3719
3720void WebPage::simulateMouseDown(int button, WebCore::IntPoint position, int clickCount, WKEventModifiers modifiers, double time)
3721{
3722    mouseEvent(WebMouseEvent(WebMouseEvent::MouseDown, static_cast<WebMouseEvent::Button>(button), position, position, 0, 0, 0, clickCount, static_cast<WebMouseEvent::Modifiers>(modifiers), time));
3723}
3724
3725void WebPage::simulateMouseUp(int button, WebCore::IntPoint position, int clickCount, WKEventModifiers modifiers, double time)
3726{
3727    mouseEvent(WebMouseEvent(WebMouseEvent::MouseUp, static_cast<WebMouseEvent::Button>(button), position, position, 0, 0, 0, clickCount, static_cast<WebMouseEvent::Modifiers>(modifiers), time));
3728}
3729
3730void WebPage::simulateMouseMotion(WebCore::IntPoint position, double time)
3731{
3732    mouseEvent(WebMouseEvent(WebMouseEvent::MouseMove, WebMouseEvent::NoButton, position, position, 0, 0, 0, 0, WebMouseEvent::Modifiers(), time));
3733}
3734
3735void WebPage::setCompositionForTesting(const String& compositionString, uint64_t from, uint64_t length)
3736{
3737    Frame* frame = m_page->focusController()->focusedOrMainFrame();
3738    if (!frame || !frame->editor().canEdit())
3739        return;
3740
3741    Vector<CompositionUnderline> underlines;
3742    underlines.append(CompositionUnderline(0, compositionString.length(), Color(Color::black), false));
3743    frame->editor().setComposition(compositionString, underlines, from, from + length);
3744}
3745
3746bool WebPage::hasCompositionForTesting()
3747{
3748    Frame* frame = m_page->focusController()->focusedOrMainFrame();
3749    return frame && frame->editor().hasComposition();
3750}
3751
3752void WebPage::confirmCompositionForTesting(const String& compositionString)
3753{
3754    Frame* frame = m_page->focusController()->focusedOrMainFrame();
3755    if (!frame || !frame->editor().canEdit())
3756        return;
3757
3758    if (compositionString.isNull())
3759        frame->editor().confirmComposition();
3760    frame->editor().confirmComposition(compositionString);
3761}
3762
3763void WebPage::numWheelEventHandlersChanged(unsigned numWheelEventHandlers)
3764{
3765    if (m_numWheelEventHandlers == numWheelEventHandlers)
3766        return;
3767
3768    m_numWheelEventHandlers = numWheelEventHandlers;
3769    recomputeShortCircuitHorizontalWheelEventsState();
3770}
3771
3772static bool hasEnabledHorizontalScrollbar(ScrollableArea* scrollableArea)
3773{
3774    if (Scrollbar* scrollbar = scrollableArea->horizontalScrollbar())
3775        return scrollbar->enabled();
3776
3777    return false;
3778}
3779
3780static bool pageContainsAnyHorizontalScrollbars(Frame* mainFrame)
3781{
3782    if (FrameView* frameView = mainFrame->view()) {
3783        if (hasEnabledHorizontalScrollbar(frameView))
3784            return true;
3785    }
3786
3787    for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext()) {
3788        FrameView* frameView = frame->view();
3789        if (!frameView)
3790            continue;
3791
3792        const HashSet<ScrollableArea*>* scrollableAreas = frameView->scrollableAreas();
3793        if (!scrollableAreas)
3794            continue;
3795
3796        for (HashSet<ScrollableArea*>::const_iterator it = scrollableAreas->begin(), end = scrollableAreas->end(); it != end; ++it) {
3797            ScrollableArea* scrollableArea = *it;
3798            if (!scrollableArea->scrollbarsCanBeActive())
3799                continue;
3800
3801            if (hasEnabledHorizontalScrollbar(scrollableArea))
3802                return true;
3803        }
3804    }
3805
3806    return false;
3807}
3808
3809void WebPage::recomputeShortCircuitHorizontalWheelEventsState()
3810{
3811    bool canShortCircuitHorizontalWheelEvents = !m_numWheelEventHandlers;
3812
3813    if (canShortCircuitHorizontalWheelEvents) {
3814        // Check if we have any horizontal scroll bars on the page.
3815        if (pageContainsAnyHorizontalScrollbars(mainFrame()))
3816            canShortCircuitHorizontalWheelEvents = false;
3817    }
3818
3819    if (m_canShortCircuitHorizontalWheelEvents == canShortCircuitHorizontalWheelEvents)
3820        return;
3821
3822    m_canShortCircuitHorizontalWheelEvents = canShortCircuitHorizontalWheelEvents;
3823    send(Messages::WebPageProxy::SetCanShortCircuitHorizontalWheelEvents(m_canShortCircuitHorizontalWheelEvents));
3824}
3825
3826Frame* WebPage::mainFrame() const
3827{
3828    return m_page ? m_page->mainFrame() : 0;
3829}
3830
3831FrameView* WebPage::mainFrameView() const
3832{
3833    if (Frame* frame = mainFrame())
3834        return frame->view();
3835
3836    return 0;
3837}
3838
3839#if ENABLE(PAGE_VISIBILITY_API) || ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING)
3840void WebPage::setVisibilityState(uint32_t visibilityState, bool isInitialState)
3841{
3842    if (!m_page)
3843        return;
3844
3845    WebCore::PageVisibilityState state = static_cast<WebCore::PageVisibilityState>(visibilityState);
3846
3847#if ENABLE(PAGE_VISIBILITY_API)
3848    if (m_visibilityState == state)
3849        return;
3850
3851    FrameView* view = m_page->mainFrame() ? m_page->mainFrame()->view() : 0;
3852
3853    if (state == WebCore::PageVisibilityStateVisible) {
3854        m_page->didMoveOnscreen();
3855        if (view)
3856            view->show();
3857    }
3858
3859    m_page->setVisibilityState(state, isInitialState);
3860    m_visibilityState = state;
3861
3862    if (state == WebCore::PageVisibilityStateHidden) {
3863        m_page->willMoveOffscreen();
3864        if (view)
3865            view->hide();
3866    }
3867#endif
3868
3869#if ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING) && !ENABLE(PAGE_VISIBILITY_API)
3870    m_page->setVisibilityState(state, isInitialState);
3871#endif
3872}
3873#endif
3874
3875void WebPage::setThrottled(bool isThrottled)
3876{
3877    if (m_page)
3878        m_page->setThrottled(isThrottled);
3879}
3880
3881void WebPage::setScrollingPerformanceLoggingEnabled(bool enabled)
3882{
3883    m_scrollingPerformanceLoggingEnabled = enabled;
3884
3885    FrameView* frameView = m_mainFrame->coreFrame()->view();
3886    if (!frameView)
3887        return;
3888
3889    frameView->setScrollingPerformanceLoggingEnabled(enabled);
3890}
3891
3892bool WebPage::canPluginHandleResponse(const ResourceResponse& response)
3893{
3894#if ENABLE(NETSCAPE_PLUGIN_API)
3895    uint32_t pluginLoadPolicy;
3896    bool allowOnlyApplicationPlugins = !m_mainFrame->coreFrame()->loader()->subframeLoader()->allowPlugins(NotAboutToInstantiatePlugin);
3897
3898    uint64_t pluginProcessToken;
3899    String newMIMEType;
3900    String unavailabilityDescription;
3901    if (!sendSync(Messages::WebPageProxy::FindPlugin(response.mimeType(), PluginProcessTypeNormal, response.url().string(), response.url().string(), response.url().string(), allowOnlyApplicationPlugins), Messages::WebPageProxy::FindPlugin::Reply(pluginProcessToken, newMIMEType, pluginLoadPolicy, unavailabilityDescription)))
3902        return false;
3903
3904    return pluginLoadPolicy != PluginModuleBlocked && pluginProcessToken;
3905#else
3906    return false;
3907#endif
3908}
3909
3910bool WebPage::shouldUseCustomRepresentationForResponse(const ResourceResponse& response)
3911{
3912    if (!m_mimeTypesWithCustomRepresentations.contains(response.mimeType()))
3913        return false;
3914
3915    // If a plug-in exists that claims to support this response, it should take precedence over the custom representation.
3916    return !canPluginHandleResponse(response);
3917}
3918
3919#if PLATFORM(QT) || PLATFORM(GTK)
3920static Frame* targetFrameForEditing(WebPage* page)
3921{
3922    Frame* targetFrame = page->corePage()->focusController()->focusedOrMainFrame();
3923
3924    if (!targetFrame)
3925        return 0;
3926
3927    Editor& editor = targetFrame->editor();
3928    if (!editor.canEdit())
3929        return 0;
3930
3931    if (editor.hasComposition()) {
3932        // We should verify the parent node of this IME composition node are
3933        // editable because JavaScript may delete a parent node of the composition
3934        // node. In this case, WebKit crashes while deleting texts from the parent
3935        // node, which doesn't exist any longer.
3936        if (PassRefPtr<Range> range = editor.compositionRange()) {
3937            Node* node = range->startContainer();
3938            if (!node || !node->isContentEditable())
3939                return 0;
3940        }
3941    }
3942    return targetFrame;
3943}
3944
3945void WebPage::confirmComposition(const String& compositionString, int64_t selectionStart, int64_t selectionLength)
3946{
3947    Frame* targetFrame = targetFrameForEditing(this);
3948    if (!targetFrame) {
3949        send(Messages::WebPageProxy::EditorStateChanged(editorState()));
3950        return;
3951    }
3952
3953    targetFrame->editor().confirmComposition(compositionString);
3954
3955    if (selectionStart == -1) {
3956        send(Messages::WebPageProxy::EditorStateChanged(editorState()));
3957        return;
3958    }
3959
3960    Element* scope = targetFrame->selection()->rootEditableElement();
3961    RefPtr<Range> selectionRange = TextIterator::rangeFromLocationAndLength(scope, selectionStart, selectionLength);
3962    ASSERT_WITH_MESSAGE(selectionRange, "Invalid selection: [%lld:%lld] in text of length %d", static_cast<long long>(selectionStart), static_cast<long long>(selectionLength), scope->innerText().length());
3963
3964    if (selectionRange) {
3965        VisibleSelection selection(selectionRange.get(), SEL_DEFAULT_AFFINITY);
3966        targetFrame->selection()->setSelection(selection);
3967    }
3968    send(Messages::WebPageProxy::EditorStateChanged(editorState()));
3969}
3970
3971void WebPage::setComposition(const String& text, Vector<CompositionUnderline> underlines, uint64_t selectionStart, uint64_t selectionEnd, uint64_t replacementStart, uint64_t replacementLength)
3972{
3973    Frame* targetFrame = targetFrameForEditing(this);
3974    if (!targetFrame || !targetFrame->selection()->isContentEditable()) {
3975        send(Messages::WebPageProxy::EditorStateChanged(editorState()));
3976        return;
3977    }
3978
3979    if (replacementLength > 0) {
3980        // The layout needs to be uptodate before setting a selection
3981        targetFrame->document()->updateLayout();
3982
3983        Element* scope = targetFrame->selection()->rootEditableElement();
3984        RefPtr<Range> replacementRange = TextIterator::rangeFromLocationAndLength(scope, replacementStart, replacementLength);
3985        targetFrame->editor().setIgnoreCompositionSelectionChange(true);
3986        targetFrame->selection()->setSelection(VisibleSelection(replacementRange.get(), SEL_DEFAULT_AFFINITY));
3987        targetFrame->editor().setIgnoreCompositionSelectionChange(false);
3988    }
3989
3990    targetFrame->editor().setComposition(text, underlines, selectionStart, selectionEnd);
3991    send(Messages::WebPageProxy::EditorStateChanged(editorState()));
3992}
3993
3994void WebPage::cancelComposition()
3995{
3996    if (Frame* targetFrame = targetFrameForEditing(this))
3997        targetFrame->editor().cancelComposition();
3998    send(Messages::WebPageProxy::EditorStateChanged(editorState()));
3999}
4000#endif
4001
4002void WebPage::didChangeSelection()
4003{
4004    send(Messages::WebPageProxy::EditorStateChanged(editorState()));
4005}
4006
4007void WebPage::setMainFrameInViewSourceMode(bool inViewSourceMode)
4008{
4009    m_mainFrame->coreFrame()->setInViewSourceMode(inViewSourceMode);
4010}
4011
4012void WebPage::setMinimumLayoutSize(const IntSize& minimumLayoutSize)
4013{
4014    if (m_minimumLayoutSize == minimumLayoutSize)
4015        return;
4016
4017    m_minimumLayoutSize = minimumLayoutSize;
4018    if (minimumLayoutSize.width() <= 0) {
4019        corePage()->mainFrame()->view()->enableAutoSizeMode(false, IntSize(), IntSize());
4020        return;
4021    }
4022
4023    int minimumLayoutWidth = minimumLayoutSize.width();
4024    int minimumLayoutHeight = std::max(minimumLayoutSize.height(), 1);
4025
4026    int maximumSize = std::numeric_limits<int>::max();
4027
4028    corePage()->mainFrame()->view()->enableAutoSizeMode(true, IntSize(minimumLayoutWidth, minimumLayoutHeight), IntSize(maximumSize, maximumSize));
4029}
4030
4031void WebPage::setAutoSizingShouldExpandToViewHeight(bool shouldExpand)
4032{
4033    if (m_autoSizingShouldExpandToViewHeight == shouldExpand)
4034        return;
4035
4036    m_autoSizingShouldExpandToViewHeight = shouldExpand;
4037
4038    corePage()->mainFrame()->view()->setAutoSizeFixedMinimumHeight(shouldExpand ? m_viewSize.height() : 0);
4039}
4040
4041bool WebPage::isSmartInsertDeleteEnabled()
4042{
4043    return m_page->settings()->smartInsertDeleteEnabled();
4044}
4045
4046void WebPage::setSmartInsertDeleteEnabled(bool enabled)
4047{
4048    if (m_page->settings()->smartInsertDeleteEnabled() != enabled) {
4049        m_page->settings()->setSmartInsertDeleteEnabled(enabled);
4050        setSelectTrailingWhitespaceEnabled(!enabled);
4051    }
4052}
4053
4054bool WebPage::isSelectTrailingWhitespaceEnabled()
4055{
4056    return m_page->settings()->selectTrailingWhitespaceEnabled();
4057}
4058
4059void WebPage::setSelectTrailingWhitespaceEnabled(bool enabled)
4060{
4061    if (m_page->settings()->selectTrailingWhitespaceEnabled() != enabled) {
4062        m_page->settings()->setSelectTrailingWhitespaceEnabled(enabled);
4063        setSmartInsertDeleteEnabled(!enabled);
4064    }
4065}
4066
4067bool WebPage::canShowMIMEType(const String& MIMEType) const
4068{
4069    if (MIMETypeRegistry::canShowMIMEType(MIMEType))
4070        return true;
4071
4072    if (PluginData* pluginData = m_page->pluginData()) {
4073        if (pluginData->supportsMimeType(MIMEType, PluginData::AllPlugins) && corePage()->mainFrame()->loader()->subframeLoader()->allowPlugins(NotAboutToInstantiatePlugin))
4074            return true;
4075
4076        // We can use application plugins even if plugins aren't enabled.
4077        if (pluginData->supportsMimeType(MIMEType, PluginData::OnlyApplicationPlugins))
4078            return true;
4079    }
4080
4081    return false;
4082}
4083
4084void WebPage::addTextCheckingRequest(uint64_t requestID, PassRefPtr<TextCheckingRequest> request)
4085{
4086    m_pendingTextCheckingRequestMap.add(requestID, request);
4087}
4088
4089void WebPage::didFinishCheckingText(uint64_t requestID, const Vector<TextCheckingResult>& result)
4090{
4091    TextCheckingRequest* request = m_pendingTextCheckingRequestMap.get(requestID);
4092    if (!request)
4093        return;
4094
4095    request->didSucceed(result);
4096    m_pendingTextCheckingRequestMap.remove(requestID);
4097}
4098
4099void WebPage::didCancelCheckingText(uint64_t requestID)
4100{
4101    TextCheckingRequest* request = m_pendingTextCheckingRequestMap.get(requestID);
4102    if (!request)
4103        return;
4104
4105    request->didCancel();
4106    m_pendingTextCheckingRequestMap.remove(requestID);
4107}
4108
4109void WebPage::didCommitLoad(WebFrame* frame)
4110{
4111    if (!frame->isMainFrame())
4112        return;
4113
4114    // If previous URL is invalid, then it's not a real page that's being navigated away from.
4115    // Most likely, this is actually the first load to be committed in this page.
4116    if (frame->coreFrame()->loader()->previousURL().isValid())
4117        reportUsedFeatures();
4118
4119    // Only restore the scale factor for standard frame loads (of the main frame).
4120    if (frame->coreFrame()->loader()->loadType() == FrameLoadTypeStandard) {
4121        Page* page = frame->coreFrame()->page();
4122        if (page && page->pageScaleFactor() != 1)
4123            scalePage(1, IntPoint());
4124    }
4125
4126#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC)
4127    resetPrimarySnapshottedPlugIn();
4128#endif
4129
4130    WebProcess::shared().updateActivePages();
4131}
4132
4133void WebPage::didFinishLoad(WebFrame* frame)
4134{
4135#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC)
4136    if (!frame->isMainFrame())
4137        return;
4138
4139    m_readyToFindPrimarySnapshottedPlugin = true;
4140    LOG(Plugins, "Primary Plug-In Detection: triggering detection from didFinishLoad (marking as ready to detect).");
4141    m_determinePrimarySnapshottedPlugInTimer.startOneShot(0);
4142#else
4143    UNUSED_PARAM(frame);
4144#endif
4145}
4146
4147#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC)
4148static int primarySnapshottedPlugInSearchLimit = 3000;
4149static int primarySnapshottedPlugInSearchGap = 200;
4150static float primarySnapshottedPlugInSearchBucketSize = 1.1;
4151static int primarySnapshottedPlugInMinimumWidth = 400;
4152static int primarySnapshottedPlugInMinimumHeight = 300;
4153static unsigned maxPrimarySnapshottedPlugInDetectionAttempts = 2;
4154static int deferredPrimarySnapshottedPlugInDetectionDelay = 3;
4155
4156#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC)
4157void WebPage::determinePrimarySnapshottedPlugInTimerFired()
4158{
4159    if (!m_page)
4160        return;
4161
4162    Settings* settings = m_page->settings();
4163    if (!settings->snapshotAllPlugIns() && settings->primaryPlugInSnapshotDetectionEnabled())
4164        determinePrimarySnapshottedPlugIn();
4165}
4166#endif
4167
4168void WebPage::determinePrimarySnapshottedPlugIn()
4169{
4170    if (!m_page->settings()->plugInSnapshottingEnabled())
4171        return;
4172
4173    LOG(Plugins, "Primary Plug-In Detection: began.");
4174
4175    if (!m_readyToFindPrimarySnapshottedPlugin) {
4176        LOG(Plugins, "Primary Plug-In Detection: exiting - not ready to find plugins.");
4177        return;
4178    }
4179
4180    if (!m_hasSeenPlugin) {
4181        LOG(Plugins, "Primary Plug-In Detection: exiting - we never saw a plug-in get added to the page.");
4182        return;
4183    }
4184
4185    if (m_didFindPrimarySnapshottedPlugin) {
4186        LOG(Plugins, "Primary Plug-In Detection: exiting - we've already found a primary plug-in.");
4187        return;
4188    }
4189
4190    ++m_numberOfPrimarySnapshotDetectionAttempts;
4191
4192    RenderView* renderView = corePage()->mainFrame()->view()->renderView();
4193
4194    IntRect searchRect = IntRect(IntPoint(), corePage()->mainFrame()->view()->contentsSize());
4195    searchRect.intersect(IntRect(IntPoint(), IntSize(primarySnapshottedPlugInSearchLimit, primarySnapshottedPlugInSearchLimit)));
4196
4197    HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::AllowChildFrameContent | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowShadowContent);
4198
4199    HashSet<RenderObject*> seenRenderers;
4200    HTMLPlugInImageElement* candidatePlugIn = 0;
4201    unsigned candidatePlugInArea = 0;
4202
4203    for (int x = searchRect.x(); x <= searchRect.width(); x += primarySnapshottedPlugInSearchGap) {
4204        for (int y = searchRect.y(); y <= searchRect.height(); y += primarySnapshottedPlugInSearchGap) {
4205            HitTestResult hitTestResult = HitTestResult(LayoutPoint(x, y));
4206            renderView->hitTest(request, hitTestResult);
4207
4208            Element* element = hitTestResult.innerElement();
4209            if (!element)
4210                continue;
4211
4212            RenderObject* renderer = element->renderer();
4213            if (!renderer || !renderer->isBox())
4214                continue;
4215
4216            RenderBox* renderBox = toRenderBox(renderer);
4217
4218            if (!seenRenderers.add(renderer).isNewEntry)
4219                continue;
4220
4221            if (!element->isPluginElement())
4222                continue;
4223
4224            HTMLPlugInElement* plugInElement = toHTMLPlugInElement(element);
4225            if (!plugInElement->isPlugInImageElement())
4226                continue;
4227
4228            HTMLPlugInImageElement* plugInImageElement = toHTMLPlugInImageElement(plugInElement);
4229
4230            if (plugInElement->displayState() == HTMLPlugInElement::Playing)
4231                continue;
4232
4233            if (renderBox->contentWidth() < primarySnapshottedPlugInMinimumWidth || renderBox->contentHeight() < primarySnapshottedPlugInMinimumHeight)
4234                continue;
4235
4236            LayoutUnit contentArea = renderBox->contentWidth() * renderBox->contentHeight();
4237
4238            if (contentArea > candidatePlugInArea * primarySnapshottedPlugInSearchBucketSize) {
4239                candidatePlugIn = plugInImageElement;
4240                candidatePlugInArea = contentArea;
4241            }
4242        }
4243    }
4244
4245    if (!candidatePlugIn) {
4246        LOG(Plugins, "Primary Plug-In Detection: fail - did not find a candidate plug-in.");
4247        if (m_numberOfPrimarySnapshotDetectionAttempts < maxPrimarySnapshottedPlugInDetectionAttempts) {
4248            LOG(Plugins, "Primary Plug-In Detection: will attempt again in %ds.", deferredPrimarySnapshottedPlugInDetectionDelay);
4249            m_determinePrimarySnapshottedPlugInTimer.startOneShot(deferredPrimarySnapshottedPlugInDetectionDelay);
4250        }
4251        return;
4252    }
4253
4254    LOG(Plugins, "Primary Plug-In Detection: success - found a candidate plug-in - inform it.");
4255    m_didFindPrimarySnapshottedPlugin = true;
4256    m_primaryPlugInPageOrigin = m_page->mainFrame()->document()->baseURL().host();
4257    m_primaryPlugInOrigin = candidatePlugIn->loadedUrl().host();
4258    m_primaryPlugInMimeType = candidatePlugIn->loadedMimeType();
4259
4260    candidatePlugIn->setIsPrimarySnapshottedPlugIn(true);
4261}
4262
4263void WebPage::resetPrimarySnapshottedPlugIn()
4264{
4265    m_readyToFindPrimarySnapshottedPlugin = false;
4266    m_didFindPrimarySnapshottedPlugin = false;
4267    m_numberOfPrimarySnapshotDetectionAttempts = 0;
4268    m_hasSeenPlugin = false;
4269}
4270
4271bool WebPage::matchesPrimaryPlugIn(const String& pageOrigin, const String& pluginOrigin, const String& mimeType) const
4272{
4273    if (!m_didFindPrimarySnapshottedPlugin)
4274        return false;
4275
4276    return (pageOrigin == m_primaryPlugInPageOrigin && pluginOrigin == m_primaryPlugInOrigin && mimeType == m_primaryPlugInMimeType);
4277}
4278#endif // ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC)
4279
4280PassRefPtr<Range> WebPage::currentSelectionAsRange()
4281{
4282    Frame* frame = frameWithSelection(m_page.get());
4283    if (!frame)
4284        return 0;
4285
4286    return frame->selection()->toNormalizedRange();
4287}
4288
4289void WebPage::reportUsedFeatures()
4290{
4291    // FIXME: Feature names should not be hardcoded.
4292    const BitVector* features = m_page->featureObserver()->accumulatedFeatureBits();
4293    Vector<String> namedFeatures;
4294    if (features && features->quickGet(FeatureObserver::SharedWorkerStart))
4295        namedFeatures.append("SharedWorker");
4296
4297    m_loaderClient.featuresUsedInPage(this, namedFeatures);
4298}
4299
4300unsigned WebPage::extendIncrementalRenderingSuppression()
4301{
4302    unsigned token = m_maximumRenderingSuppressionToken + 1;
4303    while (!HashSet<unsigned>::isValidValue(token) || m_activeRenderingSuppressionTokens.contains(token))
4304        token++;
4305
4306    m_activeRenderingSuppressionTokens.add(token);
4307    m_page->mainFrame()->view()->setVisualUpdatesAllowedByClient(false);
4308
4309    m_maximumRenderingSuppressionToken = token;
4310
4311    return token;
4312}
4313
4314void WebPage::stopExtendingIncrementalRenderingSuppression(unsigned token)
4315{
4316    if (!m_activeRenderingSuppressionTokens.contains(token))
4317        return;
4318
4319    m_activeRenderingSuppressionTokens.remove(token);
4320    m_page->mainFrame()->view()->setVisualUpdatesAllowedByClient(!shouldExtendIncrementalRenderingSuppression());
4321}
4322
4323void WebPage::setScrollPinningBehavior(uint32_t pinning)
4324{
4325    m_scrollPinningBehavior = static_cast<ScrollPinningBehavior>(pinning);
4326    m_page->mainFrame()->view()->setScrollPinningBehavior(m_scrollPinningBehavior);
4327}
4328
4329} // namespace WebKit
4330